在计算机视觉中,兴趣点(也叫关键点或者特征点)的概念被大量用于解决物体识别、图像匹配、视觉跟踪、三维重建等问题。它依赖于这个想法,即不再观察整副图像,而是选择某些特殊的点,然后对它们执行局部分析。如果能检测到足够多的这种点,同时它们的区分度很高,并且可以精确定位稳定的特征,那么这个方法就很有效。
Harris角点的理论部分见opencv1的这篇blog:http://blog.youkuaiyun.com/lu597203933/article/details/15088485。 下面阐述opencv2中如何进行harris角点检测和极大值抑制。
一:harris角点检测
Code:
- int main()
- {
- Mat image = imread("F:\\huangrong.jpg", 0);
- if(!image.data)
- {
- cout << "Fail to load image" << endl;
- return 0;
- }
- Mat cornerStrength;
- int blockSize = 2;
- int kSize = 3;
- cornerHarris(image, cornerStrength, blockSize, kSize, 0.01);
-
- Mat harrisCorner;
- double thresh = 0.00001;
- threshold(cornerStrength, harrisCorner, thresh, 255, THRESH_BINARY_INV);
- namedWindow("image");
- imshow("image", image);
- namedWindow("cornerStrength");
- imshow("cornerStrength", cornerStrength);
- namedWindow("harrisCorner");
- imshow("harrisCorner", harrisCorner);
- waitKey(0);
- return 0;
- }
Explaination:
<1>opencv2中使用cornerHarris(InputArray src, OutputArray dst, int blockSize,int ksize, double k, int borderType=BORDER_DEFAULT );
第一个参数: 输入源图像
第二个参数:输出 用于保存计算得到的得分
第三个参数:相邻像素尺寸
第四个:sobel运算核大小
第五:公式中的参数
<2>二值化函数threshold( InputArray src, OutputArray dst,doublethresh,double maxval, inttype );

Result:

二:极大值抑制
以上获取到的角点图像包含许多角点群,所以需要极大值抑制。我们使用膨胀函数dilate和比较compare运算来进行抑制。
主要思想是通过dilate和compare这两个函数得到极大值点所对应的标识,后将二值化的得分值与标识进行与运算即bitwise_and 函数。具体解释见代码注释。
Code:
HarrisDetector.h
- class HarrisDetector{
- private:
-
- Mat cornerStrength;
-
- Mat cornerTh;
-
- Mat localMax;
- int neighbourhood;
- int aperture;
- double k;
-
- double thre;
-
- public:
- HarrisDetector():neighbourhood(2),aperture(3), k(0.01),
- thre(0.00001){
-
- }
- void detect(Mat &image);
- Mat getCornerMap();
- void getCorners(vector<Point> &points);
- void drawOnImage(Mat &image, vector<Point> &points);
- };
-
- void HarrisDetector::detect(Mat &image){
- cornerHarris(image, cornerStrength, neighbourhood, aperture, k);
- Mat dilated;
-
- dilate(cornerStrength, dilated, Mat());
- compare(cornerStrength, dilated, localMax, CMP_EQ);
- }
-
- Mat HarrisDetector::getCornerMap()
- {
- Mat cornerMap;
-
- threshold(cornerStrength, cornerTh, thre, 255, THRESH_BINARY);
-
- cornerTh.convertTo(cornerMap, CV_8U);
-
- bitwise_and(cornerMap, localMax, cornerMap);
- return cornerMap;
- }
- void HarrisDetector::getCorners(vector<Point> &points)
- {
- Mat cornerMap = getCornerMap();
- for(int y = 0; y < cornerMap.rows; y++)
- {
- uchar *cornerPtr = cornerMap.ptr<uchar>(y);
- for(int x = 0; x < cornerMap.cols; x++)
- {
- if(cornerPtr[x]){
- points.push_back(Point(x, y));
- }
- }
- }
- }
-
- void HarrisDetector::drawOnImage(Mat &image, vector<Point> &points)
- {
- int radius = 3, thickness = 2;
- vector<Point>::iterator it = points.begin();
-
- while(it!= points.end())
- {
-
- circle(image, *it, radius, Scalar(255,255,255), thickness);
- it ++;
- }
- }
main.cpp:
- Mat image = imread("F:\\huangrong.jpg", 0);
- vector<Point> points;
- HarrisDetector hdetector;
- hdetector.detect(image);
- hdetector.getCorners(points);
- cout << points.size()<< endl;
- hdetector.drawOnImage(image, points);<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
Result:

三:适合跟踪的优质特征
Opencv2自带了goodFeaturesToTrack这个函数,用于解决特征点聚类问题,除了引入局部极大值的条件,特征点倾向于在图像中不均匀分布,集中在在纹理丰富的部分。该函数的具体解释见代码注释。
Code:
-
-
-
- goodFeaturesToTrack(image, points, 100, 0.01, 10);
- cout << points.size() << endl;
此外cv:: goodFeaturesToTrack函数拥有一个封装类cv::GoodFeaturesToTrackDetector,他继承自抽象类FeatureDetector类。下面代码实现功能和上面一样。
Code:
-
- Mat result;
- vector<KeyPoint> keypoints;
- GoodFeaturesToTrackDetector gftt(100, 0.01, 10);
- gftt.detect(image, keypoints);
- drawKeypoints(image, keypoints, result);
作者:小村长 出处:http://blog.youkuaiyun.com/lu597203933
欢迎转载或分享,但请务必声明文章出处。 (新浪微博:小村长zack, 欢迎交流!)