41 #include "opencv2/features2d/features2d.hpp" 42 #include "opencv2/imgproc/imgproc.hpp" 43 #include "opencv2/imgproc/imgproc_c.h" 62 HarrisResponses(
const Mat& img, std::vector<KeyPoint>& pts,
int blockSize,
float harris_k)
64 CV_Assert( img.type() == CV_8UC1 && blockSize*blockSize <= 2048 );
66 size_t ptidx, ptsize = pts.size();
69 int step = (int)(img.step/img.elemSize1());
72 float scale = (1 << 2) * blockSize * 255.0
f;
74 float scale_sq_sq = scale * scale * scale *
scale;
76 AutoBuffer<int> ofsbuf(blockSize*blockSize);
78 for(
int i = 0; i < blockSize; i++ )
79 for(
int j = 0; j < blockSize; j++ )
80 ofs[i*blockSize + j] = (
int)(i*step + j);
82 for( ptidx = 0; ptidx < ptsize; ptidx++ )
84 int x0 = cvRound(pts[ptidx].pt.x - r);
85 int y0 = cvRound(pts[ptidx].pt.y - r);
87 const uchar* ptr0 = ptr00 + y0*step + x0;
88 int a = 0, b = 0, c = 0;
90 for(
int k = 0; k < blockSize*blockSize; k++ )
92 const uchar* ptr = ptr0 + ofs[k];
93 int Ix = (ptr[1] - ptr[-1])*2 + (ptr[-step+1] - ptr[-step-1]) + (ptr[step+1] - ptr[step-1]);
94 int Iy = (ptr[
step] - ptr[-
step])*2 + (ptr[step-1] - ptr[-step-1]) + (ptr[step+1] - ptr[-step+1]);
99 pts[ptidx].response = ((float)a * b - (
float)c * c -
100 harris_k * ((float)a + b) * ((float)a + b))*scale_sq_sq;
106 static float IC_Angle(
const Mat& image,
const int half_k, Point2f pt,
107 const std::vector<int> & u_max)
109 int m_01 = 0, m_10 = 0;
111 const uchar* center = &image.at<
uchar> (cvRound(pt.y), cvRound(pt.x));
114 for (
int u = -half_k; u <= half_k; ++u)
115 m_10 += u * center[u];
118 int step = (int)image.step1();
119 for (
int v = 1; v <= half_k; ++v)
124 for (
int u = -d; u <= d; ++u)
126 int val_plus = center[u + v*
step], val_minus = center[u - v*
step];
127 v_sum += (val_plus - val_minus);
128 m_10 += u * (val_plus + val_minus);
133 return fastAtan2((
float)m_01, (
float)m_10);
139 const Mat& img,
const Point* pattern,
140 uchar* desc,
int dsize,
int WTA_K)
142 float angle = kpt.angle;
144 angle *= (float)(CV_PI/180.
f);
145 float a = (float)
cos(angle), b = (float)
sin(angle);
147 const uchar* center = &img.at<
uchar>(cvRound(kpt.pt.y), cvRound(kpt.pt.x));
148 int step = (int)img.step;
154 (x = pattern[idx].x*a - pattern[idx].y*b, \
155 y = pattern[idx].x*b + pattern[idx].y*a, \
158 *(center + iy*step + ix) )
160 #define GET_VALUE(idx) \ 161 (x = pattern[idx].x*a - pattern[idx].y*b, \ 162 y = pattern[idx].x*b + pattern[idx].y*a, \ 163 ix = cvFloor(x), iy = cvFloor(y), \ 165 cvRound(center[iy*step + ix]*(1-x)*(1-y) + center[(iy+1)*step + ix]*(1-x)*y + \ 166 center[iy*step + ix+1]*x*(1-y) + center[(iy+1)*step + ix+1]*x*y)) 171 for (
int i = 0; i < dsize; ++i, pattern += 16)
177 val |= (t0 < t1) << 1;
179 val |= (t0 < t1) << 2;
181 val |= (t0 < t1) << 3;
183 val |= (t0 < t1) << 4;
185 val |= (t0 < t1) << 5;
187 val |= (t0 < t1) << 6;
189 val |= (t0 < t1) << 7;
191 desc[i] = (
uchar)val;
194 else if( WTA_K == 3 )
196 for (
int i = 0; i < dsize; ++i, pattern += 12)
200 val = t2 > t1 ? (t2 > t0 ? 2 : 0) : (t1 > t0);
203 val |= (t2 > t1 ? (t2 > t0 ? 2 : 0) : (t1 > t0)) << 2;
206 val |= (t2 > t1 ? (t2 > t0 ? 2 : 0) : (t1 > t0)) << 4;
209 val |= (t2 > t1 ? (t2 > t0 ? 2 : 0) : (t1 > t0)) << 6;
211 desc[i] = (
uchar)val;
214 else if( WTA_K == 4 )
216 for (
int i = 0; i < dsize; ++i, pattern += 16)
218 int t0, t1, t2, t3, u, v, k, val;
222 if( t1 > t0 ) t0 = t1, u = 1;
223 if( t3 > t2 ) t2 = t3, v = 3;
230 if( t1 > t0 ) t0 = t1, u = 1;
231 if( t3 > t2 ) t2 = t3, v = 3;
238 if( t1 > t0 ) t0 = t1, u = 1;
239 if( t3 > t2 ) t2 = t3, v = 3;
246 if( t1 > t0 ) t0 = t1, u = 1;
247 if( t3 > t2 ) t2 = t3, v = 3;
251 desc[i] = (
uchar)val;
255 CV_Error( CV_StsBadSize,
"Wrong WTA_K. It can be only 2, 3 or 4." );
261 static void initializeOrbPattern(
const Point* pattern0, std::vector<Point>& pattern,
int ntuples,
int tupleSize,
int poolSize )
265 pattern.resize(ntuples*tupleSize);
267 for( i = 0; i < ntuples; i++ )
269 for( k = 0; k < tupleSize; k++ )
273 int idx = rng.uniform(0, poolSize);
274 Point pt = pattern0[idx];
275 for( k1 = 0; k1 < k; k1++ )
276 if( pattern[tupleSize*i + k1] == pt )
280 pattern[tupleSize*i + k] = pt;
553 for(
int i = 0; i < npoints; i++ )
555 pattern[i].x = rng.uniform(-patchSize/2, patchSize/2+1);
556 pattern[i].y = rng.uniform(-patchSize/2, patchSize/2+1);
561 static inline float getScale(
int level,
int firstLevel,
double scaleFactor)
563 return (
float)std::pow(scaleFactor, (
double)(level - firstLevel));
569 CV_ORB::CV_ORB(
int _nfeatures,
float _scaleFactor,
int _nlevels,
int _edgeThreshold,
570 int _firstLevel,
int _WTA_K,
int _scoreType,
int _patchSize,
const ParametersMap & _fastParameters) :
571 nfeatures(_nfeatures), scaleFactor(_scaleFactor), nlevels(_nlevels),
572 edgeThreshold(_edgeThreshold), firstLevel(_firstLevel), WTA_K(_WTA_K),
573 scoreType(_scoreType), patchSize(_patchSize), fastParameters(_fastParameters)
594 (*this)(image,
mask, keypoints, noArray(),
false);
605 int halfPatchSize,
const std::vector<int>& umax)
608 for (std::vector<KeyPoint>::iterator keypoint = keypoints.begin(),
609 keypointEnd = keypoints.end(); keypoint != keypointEnd; ++keypoint)
611 keypoint->angle =
IC_Angle(image, halfPatchSize, keypoint->pt, umax);
622 const std::vector<Mat>& maskPyramid,
623 std::vector<std::vector<KeyPoint> >& allKeypoints,
628 int nlevels = (int)imagePyramid.size();
629 std::vector<int> nfeaturesPerLevel(nlevels);
632 float factor = (float)(1.0 / scaleFactor);
633 float ndesiredFeaturesPerScale = nfeatures*(1 - factor)/(1 - (
float)
pow((
double)factor, (
double)nlevels));
636 for(
int level = 0; level < nlevels-1; level++ )
638 nfeaturesPerLevel[level] = cvRound(ndesiredFeaturesPerScale);
639 sumFeatures += nfeaturesPerLevel[level];
640 ndesiredFeaturesPerScale *= factor;
642 nfeaturesPerLevel[nlevels-1] =
std::max(nfeatures - sumFeatures, 0);
648 int halfPatchSize = patchSize / 2;
649 std::vector<int> umax(halfPatchSize + 2);
651 int v, v0, vmax = cvFloor(halfPatchSize *
sqrt(2.
f) / 2 + 1);
652 int vmin = cvCeil(halfPatchSize *
sqrt(2.
f) / 2);
653 for (v = 0; v <= vmax; ++v)
654 umax[v] = cvRound(
sqrt((
double)halfPatchSize * halfPatchSize - v * v));
657 for (v = halfPatchSize, v0 = 0; v >= vmin; --v)
659 while (umax[v0] == umax[v0 + 1])
665 allKeypoints.resize(nlevels);
667 for (
int level = 0; level <
nlevels; ++level)
669 int featuresNum = nfeaturesPerLevel[level];
670 allKeypoints[level].reserve(featuresNum*2);
672 std::vector<KeyPoint> & keypoints = allKeypoints[level];
680 KeyPointsFilter::runByImageBorder(keypoints, imagePyramid[level].size(), edgeThreshold);
685 KeyPointsFilter::retainBest(keypoints, 2 * featuresNum);
692 KeyPointsFilter::retainBest(keypoints, featuresNum);
694 float sf =
getScale(level, firstLevel, scaleFactor);
697 for (std::vector<KeyPoint>::iterator keypoint = keypoints.begin(),
698 keypointEnd = keypoints.end(); keypoint != keypointEnd; ++keypoint)
700 keypoint->octave = level;
701 keypoint->size = patchSize*sf;
717 const std::vector<Point>& pattern,
int dsize,
int WTA_K)
720 CV_Assert(image.type() == CV_8UC1);
722 descriptors = Mat::zeros((
int)keypoints.size(), dsize, CV_8UC1);
724 for (
size_t i = 0; i < keypoints.size(); i++)
737 void CV_ORB::operator()( InputArray _image, InputArray _mask, std::vector<KeyPoint>& _keypoints,
738 OutputArray _descriptors,
bool useProvidedKeypoints)
const 742 bool do_keypoints = !useProvidedKeypoints;
743 bool do_descriptors = _descriptors.needed();
745 if( (!do_keypoints && !do_descriptors) || _image.empty() )
749 const int HARRIS_BLOCK_SIZE = 9;
753 Mat image = _image.getMat(), mask = _mask.getMat();
754 if( image.type() != CV_8UC1 )
755 cvtColor(_image, image, CV_BGR2GRAY);
771 for(
size_t i = 0; i < _keypoints.size(); i++ )
777 std::vector<Mat> imagePyramid(levelsNum), maskPyramid(levelsNum);
778 for (
int level = 0; level < levelsNum; ++level)
781 Size sz(cvRound(image.cols*scale), cvRound(image.rows*scale));
782 Size wholeSize(sz.width + border*2, sz.height + border*2);
783 Mat temp(wholeSize, image.type()), masktemp;
784 imagePyramid[level] = temp(Rect(border, border, sz.width, sz.height));
788 masktemp = Mat(wholeSize, mask.type());
789 maskPyramid[level] = masktemp(Rect(border, border, sz.width, sz.height));
797 resize(image, imagePyramid[level], sz, 0, 0, INTER_LINEAR);
799 resize(mask, maskPyramid[level], sz, 0, 0, INTER_LINEAR);
803 resize(imagePyramid[level-1], imagePyramid[level], sz, 0, 0, INTER_LINEAR);
806 resize(maskPyramid[level-1], maskPyramid[level], sz, 0, 0, INTER_LINEAR);
807 threshold(maskPyramid[level], maskPyramid[level], 254, 0, THRESH_TOZERO);
811 copyMakeBorder(imagePyramid[level], temp, border, border, border, border,
812 BORDER_REFLECT_101+BORDER_ISOLATED);
814 copyMakeBorder(maskPyramid[level], masktemp, border, border, border, border,
815 BORDER_CONSTANT+BORDER_ISOLATED);
819 copyMakeBorder(image, temp, border, border, border, border,
822 copyMakeBorder(mask, masktemp, border, border, border, border,
823 BORDER_CONSTANT+BORDER_ISOLATED);
828 std::vector < std::vector<KeyPoint> > allKeypoints;
856 KeyPointsFilter::runByImageBorder(_keypoints, image.size(),
edgeThreshold);
859 allKeypoints.resize(levelsNum);
860 for (std::vector<KeyPoint>::iterator keypoint = _keypoints.begin(),
861 keypointEnd = _keypoints.end(); keypoint != keypointEnd; ++keypoint)
862 allKeypoints[keypoint->octave].push_back(*keypoint);
865 for (
int level = 0; level < levelsNum; ++level)
870 std::vector<KeyPoint> & keypoints = allKeypoints[level];
872 for (std::vector<KeyPoint>::iterator keypoint = keypoints.begin(),
873 keypointEnd = keypoints.end(); keypoint != keypointEnd; ++keypoint)
874 keypoint->pt *= scale;
879 std::vector<Point> pattern;
884 for (
int level = 0; level < levelsNum; ++level)
885 nkeypoints += (
int)allKeypoints[level].size();
886 if( nkeypoints == 0 )
887 _descriptors.release();
891 descriptors = _descriptors.getMat();
894 const int npoints = 512;
895 Point patternbuf[npoints];
896 const Point* pattern0 = (
const Point*)bit_pattern_31_;
900 pattern0 = patternbuf;
907 std::copy(pattern0, pattern0 + npoints, std::back_inserter(pattern));
917 for (
int level = 0; level < levelsNum; ++level)
920 std::vector<KeyPoint>& keypoints = allKeypoints[level];
921 int nkeypoints = (int)keypoints.size();
927 if (!descriptors.empty())
929 desc = descriptors.rowRange(offset, offset + nkeypoints);
932 offset += nkeypoints;
934 Mat& workingMat = imagePyramid[level];
936 GaussianBlur(workingMat, workingMat, Size(7, 7), 2, 2, BORDER_REFLECT_101);
944 for (std::vector<KeyPoint>::iterator keypoint = keypoints.begin(),
945 keypointEnd = keypoints.end(); keypoint != keypointEnd; ++keypoint)
946 keypoint->pt *= scale;
949 _keypoints.insert(_keypoints.end(), keypoints.begin(), keypoints.end());
955 (*this)(image,
mask, keypoints, noArray(),
false);
960 (*this)(image, Mat(), keypoints, descriptors,
true);
GLM_FUNC_DECL genIType mask(genIType const &count)
static void computeDescriptors(const Mat &image, std::vector< KeyPoint > &keypoints, Mat &descriptors, const std::vector< Point > &pattern, int dsize, int WTA_K)
CV_PROP_RW double scaleFactor
constexpr T pow(const T base, const std::size_t exponent)
static float getScale(int level, int firstLevel, double scaleFactor)
void detectImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints, const cv::Mat &mask=cv::Mat()) const
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
std::pair< std::string, std::string > ParametersPair
ParametersMap fastParameters
std::map< std::string, std::string > ParametersMap
GLM_FUNC_DECL T angle(detail::tquat< T, P > const &x)
static int bit_pattern_31_[256 *4]
Some conversion functions.
static void HarrisResponses(const Mat &img, std::vector< KeyPoint > &pts, int blockSize, float harris_k)
std::vector< cv::KeyPoint > generateKeypoints(const cv::Mat &image, const cv::Mat &mask=cv::Mat())
GLM_FUNC_DECL genType step(genType const &edge, genType const &x)
CV_PROP_RW int edgeThreshold
GLM_FUNC_DECL genType cos(genType const &angle)
Wrappers of STL for convenient functions.
GLM_FUNC_DECL genType sin(genType const &angle)
static void initializeOrbPattern(const Point *pattern0, std::vector< Point > &pattern, int ntuples, int tupleSize, int poolSize)
CvImagePtr cvtColor(const CvImageConstPtr &source, const std::string &encoding)
static void makeRandomPattern(int patchSize, Point *pattern, int npoints)
int descriptorSize() const
static void computeKeyPoints(const std::vector< Mat > &imagePyramid, const std::vector< Mat > &maskPyramid, std::vector< std::vector< KeyPoint > > &allKeypoints, int nfeatures, int firstLevel, double scaleFactor, int edgeThreshold, int patchSize, int scoreType, ParametersMap fastParameters)
int descriptorType() const
static void computeOrbDescriptor(const KeyPoint &kpt, const Mat &img, const Point *pattern, uchar *desc, int dsize, int WTA_K)
void computeImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints, cv::Mat &descriptors) const
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
static bool computeOrientation(Eigen::Vector3f A, Eigen::Vector3f E, Eigen::Quaternionf &orientation)
static float IC_Angle(const Mat &image, const int half_k, Point2f pt, const std::vector< int > &u_max)
void operator()(cv::InputArray image, cv::InputArray mask, std::vector< cv::KeyPoint > &keypoints) const
std::string UTILITE_EXP uNumber2Str(unsigned int number)
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
CV_PROP_RW int firstLevel