Harris角点
可参考:http://www.cnblogs.com/ronny/p/4009425.html
http://www.cnblogs.com/ztfei/archive/2012/05/07/2487123.html
http://blog.csdn.net/crzy_sparrow/article/details/7391511
矩阵M(x)的特征值能表示在水平和竖直方向的变化程度,但Harris给出的角点差别方法并不需要计算具体的特征值,而是计算一个
角点响应值R来判断。
alpha的值对角点检测的影响:增大α的值,将减小角点响应值R,降低角点检测的灵性,减少被检测角点的数量;减小α值,将增大角点响应值R,增加角点检测的灵敏性,增加被检测角点的数量。
关于尺度不变性:
下面是代码,我加了部分注释
#include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/nonfree/nonfree.hpp" #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; /*void drawCornerOnImage(Mat& image, const Mat&binary) { Mat_<uchar>::const_iterator it = binary.begin<uchar>(); Mat_<uchar>::const_iterator itd = binary.end<uchar>(); for (int i = 0; it != itd; it++, i++) { //Point内时什么意思? if (*it) circle(image, Point(i%image.cols, i / image.cols), 3, Scalar(0, 255, 0), 1); } } */ /******************下面是Harris角点检测的C++实现*******************************/ /* void detectHarrisCorners(const Mat& imgSrc,Mat& imgDst,double alpha ) { Mat gray; if (imgSrc.channels() == 3) cvtColor(imgSrc, gray, CV_BGR2GRAY); else gray = imgSrc.clone(); gray.convertTo(gray, CV_64F);//第二个参数depth Mat xKernel = (Mat_<double>(1, 3) << -1, 0, 1);//模板一行三列,后面为相应的值 Mat yKernel = xKernel.t(); Mat Ix, Iy; //Convolves an image with the kernel. filter2D(gray, Ix, CV_64F, xKernel); filter2D(gray, Iy, CV_64F, yKernel); Mat Ix2, Iy2, Ixy;//计算图像两个梯度方向的乘积 Ix2 = Ix.mul(Ix); Iy2 = Iy.mul(Iy); Ixy = Ix.mul(Iy); Mat gaussKernel = getGaussianKernel(7, 1); filter2D(Ix2, Ix2, CV_64F, gaussKernel); filter2D(Iy2, Iy2, CV_64F, gaussKernel); filter2D(Ixy, Ixy, CV_64F, gaussKernel); Mat cornerStrength(gray.size(), gray.type()); for (int i = 0; i < gray.rows; i++) { for (int j = 0; j < gray.cols; j++) { double det_m = Ix2.at<double>(i, j)*Iy2.at<double>(i, j)- Ixy.at<double>(i,j)*Ixy.at<double>(i,j); double trace_m = Ix2.at<double>(i, j) + Iy2.at<double>(i, j); cornerStrength.at<double>(i,j) = det_m - trace_m; } } //threshold double maxStrength; minMaxLoc(cornerStrength, NULL, &maxStrength, NULL, NULL); Mat dilated, localMax; //默认3*3核膨胀,膨胀之后,除了局部最大值点和原来相同,其它非局部最大值点被 //3*3邻域内的最大值点取代 dilate(cornerStrength, dilated, Mat()); imshow("dilated", dilated); imshow("cornerStrength", cornerStrength); //与原图相比,只剩下和原图值相同的点,这些点都是局部最大值点,保存到localMax compare(cornerStrength, dilated, localMax, CMP_EQ);//两图中相同的地方进行比较,相等的地方设为255 imshow("localMax", localMax); Mat cornerMap; double qualityLevel = 0.01; double thresh = qualityLevel * maxStrength; cornerMap = cornerStrength > thresh; bitwise_and(cornerMap, localMax, cornerMap);//将两图进行与操作 imgDst = cornerMap.clone(); } */ int main() { /******harris角点检测的C++实现********/ /* Mat img = imread("1.jpg"); imshow("原图", img); Mat gray,dst; cvtColor(img, gray, CV_BGR2GRAY); detectHarrisCorners(img, dst, 0.01); imshow("目标", dst); drawCornerOnImage(img, dst); imshow("处理后", img);*/ ////*************************下面是用opencv自带的角点检测函数*************************///////// /* Mat img = imread("1.jpg"); imshow("原图", img); Mat gray; cvtColor(img, gray, CV_BGR2GRAY); Mat cornerStrenth; cornerHarris(gray, cornerStrenth, 3, 3, 0.1); //imshow("cornerstrenth", cornerStrenth); threshold(cornerStrenth, cornerStrenth, 0.001, 255, THRESH_BINARY); //imshow("cornerstrenth", cornerStrenth); double maxStrength, minStrength; minMaxLoc(cornerStrenth, &minStrength, &maxStrength); Mat dilated; Mat locaMax; // // 膨胀图像,找出图像中全部的局部最大值点 dilate(cornerStrenth, dilated, Mat()); //imshow("dilated", dilated); // compare是一个逻辑比较函数,返回两幅图像中对应点相同的二值图像 compare(cornerStrenth, dilated, locaMax, CMP_EQ); //imshow("locaMax", locaMax); Mat cornerMap; double qualityLevel = 0.01; double th = qualityLevel*maxStrength; // 阈值计算 threshold(cornerStrenth, cornerMap, th, 255, THRESH_BINARY); //imshow("cornerMap", cornerMap); // 转为8-bit图 cornerMap.convertTo(cornerMap, CV_8U); //imshow("cornerMap1", cornerMap); // 逐点的位运算 // 和局部最大值图与,剩下角点局部最大值图,即:完成非最大值抑制 bitwise_and(cornerMap, locaMax, cornerMap); //imshow("cornerMap2", cornerMap); drawCornerOnImage(img, cornerMap); namedWindow("result"); imshow("result", img); //imshow("角点", cornerStrenth); waitKey(0); return 0; */ waitKey(0); return 0; }