29 const vector<int>& u_max)
31 int m_01 = 0, m_10 = 0;
33 const uchar* center = &image.at<uchar>(cvRound(pt.y), cvRound(pt.x));
37 m_10 += u * center[u];
40 int step = (int)image.step1();
45 int d = u_max[(uint)v];
46 for (
int u = -d; u <= d; ++u)
48 int val_plus = center[u + v *
step], val_minus = center[u - v *
step];
49 v_sum += (val_plus - val_minus);
50 m_10 += u * (val_plus + val_minus);
55 return fastAtan2((
float)m_01, (
float)m_10);
68 float angle = (float)kpt.angle *
factorPI;
69 float a = (
float)cos(angle), b = (float)sin(angle);
71 const uchar* center = &img.at<uchar>(cvRound(kpt.pt.y), cvRound(kpt.pt.x));
72 const int step = (int)img.step;
75 center[cvRound(pattern[idx].x * b + pattern[idx].y * a) *
step + \
76 cvRound(pattern[idx].x * a - pattern[idx].y * b)]
80 for (
int i = 0; i < 32; ++i, pattern += 16)
370 : nfeatures(_nfeatures),
371 scaleFactor(_scaleFactor),
372 nlevels((uint)_nlevels),
373 iniThFAST(_iniThFAST),
374 minThFAST(_minThFAST)
381 for (uint i = 1; i <
nlevels; i++)
389 for (uint i = 0; i <
nlevels; i++)
399 float nDesiredFeaturesPerScale =
nfeatures * (1 - factor) / (1 - (
float)pow((
double)factor, (
double)
nlevels));
402 for (uint level = 0; level <
nlevels - 1; level++)
406 nDesiredFeaturesPerScale *= factor;
410 const int npoints = 512;
412 std::copy(pattern0, pattern0 + npoints, std::back_inserter(
pattern));
422 for (v = 0; v <= vmax; ++v)
423 umax[(uint)v] = cvRound(sqrt(hp2 - v * v));
428 while (
umax[(uint)v0] ==
umax[(uint)v0 + 1])
438 const vector<int>& umax)
440 for (CVVKeyPoint::iterator keypoint = keypoints.begin(),
441 keypointEnd = keypoints.end();
442 keypoint != keypointEnd;
445 keypoint->angle =
IC_Angle(image, keypoint->pt, umax);
459 const int nIni = (int)round(
static_cast<float>(maxX - minX) / (maxY - minY));
461 const float hX =
static_cast<float>(maxX - minX) / nIni;
463 list<CVRaulMurExtNode> lNodes;
465 vector<CVRaulMurExtNode*> vpIniNodes;
466 vpIniNodes.resize((uint)nIni);
468 for (
int i = 0; i < nIni; i++)
479 ni.
vKeys.reserve(vToDistributeKeys.size());
481 lNodes.push_back(ni);
482 vpIniNodes[(uint)i] = &lNodes.back();
486 for (
size_t i = 0; i < vToDistributeKeys.size(); i++)
489 vpIniNodes[(uint)(kp.pt.x / hX)]->vKeys.push_back(kp);
492 list<CVRaulMurExtNode>::iterator lit = lNodes.begin();
494 while (lit != lNodes.end())
496 if (lit->vKeys.size() == 1)
501 else if (lit->vKeys.empty())
502 lit = lNodes.erase(lit);
507 bool bFinish =
false;
511 vector<pair<int, CVRaulMurExtNode*>> vSizeAndPointerToNode;
512 vSizeAndPointerToNode.reserve(lNodes.size() * 4);
516 int prevSize = (int)lNodes.size();
518 lit = lNodes.begin();
522 vSizeAndPointerToNode.clear();
524 while (lit != lNodes.end())
539 if (!n1.
vKeys.empty())
541 lNodes.push_front(n1);
542 if (!n1.
vKeys.empty())
545 vSizeAndPointerToNode.push_back(std::make_pair(n1.
vKeys.size(), &lNodes.front()));
546 lNodes.front().lit = lNodes.begin();
549 if (!n2.
vKeys.empty())
551 lNodes.push_front(n2);
552 if (n2.
vKeys.size() > 1)
555 vSizeAndPointerToNode.push_back(std::make_pair(n2.
vKeys.size(), &lNodes.front()));
556 lNodes.front().lit = lNodes.begin();
559 if (!n3.
vKeys.empty())
561 lNodes.push_front(n3);
562 if (n3.
vKeys.size() > 1)
565 vSizeAndPointerToNode.push_back(std::make_pair(n3.
vKeys.size(), &lNodes.front()));
566 lNodes.front().lit = lNodes.begin();
569 if (!n4.
vKeys.empty())
571 lNodes.push_front(n4);
572 if (n4.
vKeys.size() > 1)
575 vSizeAndPointerToNode.push_back(std::make_pair(n4.
vKeys.size(), &lNodes.front()));
576 lNodes.front().lit = lNodes.begin();
580 lit = lNodes.erase(lit);
588 if ((
int)lNodes.size() >= N || (int)lNodes.size() == prevSize)
592 else if (((
int)lNodes.size() + nToExpand * 3) > N)
596 prevSize = (int)lNodes.size();
598 vector<pair<int, CVRaulMurExtNode*>> vPrevSizeAndPointerToNode = vSizeAndPointerToNode;
599 vSizeAndPointerToNode.clear();
601 sort(vPrevSizeAndPointerToNode.begin(), vPrevSizeAndPointerToNode.end());
602 for (
int j = (
int)vPrevSizeAndPointerToNode.size() - 1; j >= 0; j--)
605 vPrevSizeAndPointerToNode[(uint)j].second->
DivideNode(n1, n2, n3, n4);
608 if (!n1.
vKeys.empty())
610 lNodes.push_front(n1);
611 if (n1.
vKeys.size() > 1)
613 vSizeAndPointerToNode.push_back(std::make_pair(n1.
vKeys.size(), &lNodes.front()));
614 lNodes.front().lit = lNodes.begin();
617 if (!n2.
vKeys.empty())
619 lNodes.push_front(n2);
620 if (n2.
vKeys.size() > 1)
622 vSizeAndPointerToNode.push_back(std::make_pair(n2.
vKeys.size(), &lNodes.front()));
623 lNodes.front().lit = lNodes.begin();
626 if (!n3.
vKeys.empty())
628 lNodes.push_front(n3);
629 if (n3.
vKeys.size() > 1)
631 vSizeAndPointerToNode.push_back(std::make_pair(n3.
vKeys.size(), &lNodes.front()));
632 lNodes.front().lit = lNodes.begin();
635 if (!n4.
vKeys.empty())
637 lNodes.push_front(n4);
638 if (n4.
vKeys.size() > 1)
640 vSizeAndPointerToNode.push_back(std::make_pair(n4.
vKeys.size(), &lNodes.front()));
641 lNodes.front().lit = lNodes.begin();
645 lNodes.erase(vPrevSizeAndPointerToNode[(uint)j].second->lit);
647 if ((
int)lNodes.size() >= N)
651 if ((
int)lNodes.size() >= N || (int)lNodes.size() == prevSize)
660 for (list<CVRaulMurExtNode>::iterator lit = lNodes.begin(); lit != lNodes.end(); lit++)
664 float maxResponse = pKP->response;
666 for (
size_t k = 1; k < vNodeKeys.size(); k++)
668 if (vNodeKeys[k].response > maxResponse)
671 maxResponse = vNodeKeys[k].response;
675 vResultKeys.push_back(*pKP);
686 for (uint level = 0; level <
nlevels; ++level)
689 const int minBorderY = minBorderX;
694 vToDistributeKeys.reserve((uint)
nfeatures * 10);
696 const float width = (float)(maxBorderX - minBorderX);
697 const float height = (float)(maxBorderY - minBorderY);
700 const int nCols = (int)(width / W);
701 const int nRows = (int)(height / W);
702 const int wCell = (int)(
ceil(width / nCols));
703 const int hCell = (int)(
ceil(height / nRows));
705 for (
int i = 0; i < nRows; i++)
707 const float iniY = (float)(minBorderY + i * hCell);
708 float maxY = iniY + hCell + 6;
710 if (iniY >= maxBorderY - 3)
712 if (maxY > maxBorderY)
713 maxY = (float)maxBorderY;
715 for (
int j = 0; j < nCols; j++)
717 const float iniX = (float)(minBorderX + j * wCell);
718 float maxX = iniX + wCell + 6;
719 if (iniX >= maxBorderX - 6)
721 if (maxX > maxBorderX)
722 maxX = (float)maxBorderX;
729 .rowRange((
int)iniY, (
int)maxY)
730 .colRange((
int)iniX, (
int)maxX),
736 if (vKeysCell.empty())
739 .rowRange((
int)iniY, (
int)maxY)
740 .colRange((
int)iniX, (
int)maxX),
746 if (!vKeysCell.empty())
748 for (CVVKeyPoint::iterator vit = vKeysCell.begin(); vit != vKeysCell.end(); vit++)
750 (*vit).pt.x += j * wCell;
751 (*vit).pt.y += i * hCell;
752 vToDistributeKeys.push_back(*vit);
772 const int nkps = (int)keypoints.size();
773 for (uint i = 0; i < (uint)nkps; i++)
775 keypoints[i].pt.x += minBorderX;
776 keypoints[i].pt.y += minBorderY;
777 keypoints[i].octave = (int)level;
778 keypoints[i].size = (float)scaledPatchSize;
784 for (uint level = 0; level <
nlevels; ++level)
797 descriptors = CVMat::zeros((
int)keypoints.size(), 32, CV_8UC1);
799 for (
size_t i = 0; i < keypoints.size(); i++)
803 descriptors.ptr((
int)i));
814 bool useProvidedKeypoints)
819 CVMat image = _image.getMat();
820 assert(image.type() == CV_8UC1);
828 if (!useProvidedKeypoints)
832 for (uint level = 0; level <
nlevels; ++level)
833 nkeypoints += (
int)allKeypoints[level].size();
835 _keypoints.reserve((uint)nkeypoints);
841 KeyPointsFilter::runByImageBorder(_keypoints, _image.size(), 31);
842 nkeypoints = (int)_keypoints.size();
844 for (uint index = 0; index < _keypoints.size(); index++)
846 if (_keypoints[index].octave > last_level)
847 last_level = _keypoints[index].octave;
849 _keypoints[index].pt /=
mvScaleFactor[(uint)_keypoints[index].octave];
850 allKeypoints[(uint)_keypoints[index].octave].push_back(_keypoints[index]);
854 _descriptors.release();
855 else if (_descriptors.needed())
857 _descriptors.create(nkeypoints, 32, CV_8U);
858 descriptors = _descriptors.getMat();
862 for (uint level = 0; level <
nlevels; ++level)
865 int nkeypointsLevel = (int)keypoints.size();
867 if (nkeypointsLevel == 0)
869 if (_descriptors.needed())
873 GaussianBlur(workingMat, workingMat, cv::Size(7, 7), 2, 2, BORDER_REFLECT_101);
876 CVMat desc = descriptors.rowRange(offset, offset + nkeypointsLevel);
880 offset += nkeypointsLevel;
886 for (CVVKeyPoint::iterator keypoint = keypoints.begin(),
887 keypointEnd = keypoints.end();
888 keypoint != keypointEnd;
890 keypoint->pt *= scale;
893 if (!useProvidedKeypoints)
895 _keypoints.insert(_keypoints.end(), keypoints.begin(), keypoints.end());
902 for (uint level = 0; level < (uint)
nlevels; ++level)
905 CVSize sz(cvRound((
float)image.cols * scale),
906 cvRound((
float)image.rows * scale));
909 CVMat temp(wholeSize, image.type()), masktemp;
932 BORDER_REFLECT_101 + BORDER_ISOLATED);
Declares the Raul Mur ORB feature detector and descriptor.
const int HALF_PATCH_SIZE
static float IC_Angle(const CVMat &image, CVPoint2f pt, const vector< int > &u_max)
Returns the angle of the image patch around a keypoint based on the center of gravity.
static void computeDescriptors(const CVMat &image, CVVKeyPoint &keypoints, CVMat &descriptors, CVVPoint &pattern)
Computes the descriptors for all passed keypoints.
static void computeOrientation(const CVMat &image, CVVKeyPoint &keypoints, const vector< int > &umax)
Compute the angle for a keypoint and save it.
static int bit_pattern_31_[256 *4]
static void computeOrbDescriptor(const CVKeyPoint &kpt, const CVMat &img, const CVPoint *pattern, uchar *desc)
Calculate the Orb descriptor for a keypoint.
Declares the Raul Mur ORB feature detector and descriptor.
vector< vector< cv::KeyPoint > > CVVVKeyPoint
cv::InputArray CVInputArray
cv::OutputArray CVOutputArray
vector< cv::Point > CVVPoint
vector< cv::KeyPoint > CVVKeyPoint
Data structure used to subdivide the Image with key points into segments.
void DivideNode(CVRaulMurExtNode &n1, CVRaulMurExtNode &n2, CVRaulMurExtNode &n3, CVRaulMurExtNode &n4)
CVVKeyPoint DistributeOctTree(const CVVKeyPoint &vToDistributeKeys, const int &minX, const int &maxX, const int &minY, const int &maxY, const int &nFeatures, const int &level)
Create The tree and distribute it.
vector< float > mvInvLevelSigma2
vector< float > mvInvScaleFactor
vector< int > mnFeaturesPerLevel
CVRaulMurOrb(int nfeatures, float scaleFactor, int nlevels, int iniThFAST, int minThFAST)
void detectAndCompute(CVInputArray image, CVInputArray mask, CVVKeyPoint &keypoints, CVOutputArray descriptors, bool useProvidedKeypoints)
vector< float > mvLevelSigma2
vector< float > mvScaleFactor
void ComputePyramid(CVMat image)
void ComputeKeyPointsOctTree(CVVVKeyPoint &allKeypoints)
Get the Keypoints and distribute them.