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.