1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 8 9 int main(int argc, char** argv) 10 { 11 Mat src; 12 src = imread("数字.jpg",0); 13 if (src.empty()){ 14 printf("Can not load Image..."); 15 return -1; 16 } 17 imshow("input Image", src); 18 19 //进行Harris角点检测 20 Mat cornerStrength; 21 cornerHarris(src, cornerStrength,2,3,0.01);//返回局部最大值作为像素,角点坐标存储在cornerStrength中 22 imshow("角点检测的图", cornerStrength);//值太小,未转成二值图像显示不明显 23 24 Mat harrisCorner; 25 threshold(cornerStrength, harrisCorner,0.00001,255,THRESH_BINARY); 26 imshow("角点检测的二值图", harrisCorner); 27 28 29 waitKey(0); 30 return 0; 31 }
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 8 Mat src,src_gray; 9 10 int thresh = 150; 11 int max_count = 255; 12 13 const char* output_title = "Harris_CornerDetection Result"; 14 15 void Harris_demo(int,void*); 16 17 int main(int argc, char** argv) 18 { 19 src = imread("数字.jpg"); 20 if (src.empty()) { 21 printf("Can not load Image..."); 22 return -1; 23 } 24 imshow("input Image",src); 25 26 cvtColor(src, src_gray, COLOR_BGR2GRAY); 27 28 namedWindow(output_title,CV_WINDOW_AUTOSIZE); 29 createTrackbar("Threshold", output_title,&thresh, max_count, Harris_demo); 30 Harris_demo(0, 0); 31 32 33 34 35 waitKey(0); 36 return 0; 37 } 38 39 void Harris_demo(int, void*) { 40 41 Mat cornerStrength; 42 int blockSize = 2; 43 int ksize = 3; 44 double k = 0.04; 45 cornerHarris(src_gray, cornerStrength, blockSize, ksize,k,BORDER_DEFAULT);//返回局部最大值作为像素,角点坐标存储在cornerStrength中 46 normalize(cornerStrength, cornerStrength, 0, 255, NORM_MINMAX);//归一化 47 convertScaleAbs(cornerStrength, cornerStrength);//变成8位无符号整型 48 49 //循环遍历每个像素,将大于阈值的点画出来 50 Mat resultImage = src.clone(); 51 for (int row = 0; row < resultImage.rows; row++) { 52 uchar* currentRow = cornerStrength.ptr(row); 53 for (int col = 0; col < resultImage.cols; col++) { 54 int value = (int)*currentRow; 55 if (value > thresh) { 56 circle(resultImage,Point(col,row),2,Scalar(0,0,255),2,8,0); 57 } 58 currentRow++; 59 } 60 } 61 62 63 imshow(output_title, resultImage); 64 65 }
因为公式更简单,所以Shi-Tomasi角点检测比Harris要快得多
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 Mat src,src_gray; 8 9 int num_corners = 25; 10 int max_corners = 200; 11 const char* output_title = "Shi_Tomasi Detector"; 12 13 void Shi_Tomasi_demo(int,void*); 14 15 RNG rng(12345); 16 17 int main(int argc, char** argv) { 18 src = imread("数字.jpg"); 19 if (src.empty()) { 20 printf("could not load image...\n"); 21 return -1; 22 } 23 namedWindow("input image", CV_WINDOW_AUTOSIZE); 24 imshow("input image", src); 25 26 cvtColor(src,src_gray,COLOR_BGR2GRAY); 27 28 namedWindow(output_title, CV_WINDOW_AUTOSIZE); 29 createTrackbar("角点数:", output_title, &num_corners, max_corners, Shi_Tomasi_demo); 30 Shi_Tomasi_demo(0,0); 31 32 waitKey(0); 33 return 0; 34 } 35 36 void Shi_Tomasi_demo(int, void*) { 37 if (num_corners < 5) num_corners = 5; 38 39 vector<Point2f> corners;//保存检测到的角点 40 //参数设置 41 double qualityLevel = 0.01; 42 double minDistance = 10; 43 int blockSize = 3; 44 bool useHarris = false;//是否使用Harris角点检测 45 double k = 0.04;//如果前面使用了角点检测,则需要用到这一项,没有则没有用 46 47 goodFeaturesToTrack(src_gray,corners,num_corners,qualityLevel,minDistance,Mat(),blockSize,useHarris,k); 48 printf("Number of detected corner: %d\n",(int)corners.size()); 49 50 //画出角点 51 Mat resultImage = src.clone(); 52 for (size_t t=0; t < corners.size(); t++) 53 { 54 circle(resultImage, corners[t], 2, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 2, 8, 0); 55 } 56 imshow(output_title, resultImage); 57 58 }
自定义角点检测器简介:
-
基于Harris与Shi-Tomasi角点检测
-
首先通过计算矩阵M得到lamda1和lamda2两个特征值根据他们得到角点响应值
-
然后自己设置阈值实现计算出阈值得到有效响应值的角点设置
相关API
C++: void cornerEigenValsAndVecs( InputArray src, --单通道输入8位或浮点图像 OutputArray dst, --输出图像,同源图像或CV_32FC(6) int blockSize, --邻域大小值 int apertureSize, --Sobel算子的参数 int borderType=BORDER_DEFAULT --像素外插方法 )//对应于Harris C++: void cornerMinEigenVal( InputArray src, --单通道输入8位或浮点图像 OutputArray dst, --图像存储的最小特征值。类型为CV_32FC1 int blockSize, --邻域大小值 int apertureSize=3, --Sobel算子的参数 int borderType=BORDER_DEFAULT --像素外插方法
}//对应Shi-Tomasi
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 8 Mat src,src_gray; 9 Mat HarrisRsImage; 10 11 double harris_min_rsp,harris_max_rsp; 12 int qualityLevel = 40; 13 int max_count = 100; 14 15 const char* harris_window = "Harris"; 16 17 void CustomHarris_demo(int, void*); 18 19 int main(int argc, char** argv) 20 { 21 src = imread("数字.jpg"); 22 if (src.empty()) { 23 printf("Can not load Image..."); 24 return -1; 25 } 26 imshow("input Image",src); 27 28 cvtColor(src, src_gray, COLOR_BGR2GRAY); 29 30 //计算特征值lambda1和lambda2 31 int blockSize = 3; 32 int ksize = 3; 33 Mat Harris_dst=Mat::zeros(src.size(),CV_32FC(6));//CV_32FC(6),有6个值要存储 34 cornerEigenValsAndVecs(src_gray, Harris_dst, blockSize, ksize,4); 35 36 //计算响应 37 HarrisRsImage = Mat::zeros(src.size(), CV_32FC1); 38 double k = 0.04; 39 for (int row = 0; row < Harris_dst.rows; row++) { 40 for (int col = 0; col < Harris_dst.cols; col++) { 41 double lambda1=Harris_dst.at<Vec6f>(row, col)[0]; 42 double lambda2= Harris_dst.at<Vec6f>(row, col)[1]; 43 HarrisRsImage.at<float>(row, col) = lambda1 * lambda2 - k * pow((lambda1 + lambda2), 2); 44 } 45 } 46 47 minMaxLoc(HarrisRsImage,&harris_min_rsp,&harris_max_rsp,0,0,Mat()); 48 namedWindow(harris_window,CV_WINDOW_AUTOSIZE); 49 createTrackbar("Quality", harris_window,&qualityLevel, max_count,CustomHarris_demo); 50 CustomHarris_demo(0,0); 51 52 waitKey(0); 53 return 0; 54 } 55 56 void CustomHarris_demo(int, void*) 57 { 58 if (qualityLevel < 10) qualityLevel = 10; 59 Mat resultImage = src.clone(); 60 61 float thresh = harris_min_rsp + (((double)qualityLevel) / max_count)*(harris_max_rsp - harris_min_rsp);//阈值 62 for (int row = 0; row < src.rows; row++) { 63 for (int col = 0; col < src.cols; col++) { 64 float value = HarrisRsImage.at<float>(row, col); 65 if (value > thresh) { 66 circle(resultImage, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0); 67 } 68 69 } 70 } 71 72 imshow(harris_window, resultImage); 73 }
1 //Shi-Tomasi和Harris自定义角点检测 2 3 #include <opencv2/opencv.hpp> 4 #include <iostream> 5 6 #include <math.h> 7 using namespace cv; 8 using namespace std; 9 const char* harris_win = "Custom Harris Corners Detector"; 10 const char* shitomasi_win = "Custom Shi-Tomasi Corners Detector"; 11 Mat src, gray_src; 12 // harris corner response 13 Mat harris_dst, harrisRspImg; 14 double harris_min_rsp; 15 double harris_max_rsp; 16 // shi-tomasi corner response 17 Mat shiTomasiRsp; 18 double shitomasi_max_rsp; 19 double shitomasi_min_rsp; 20 int sm_qualitylevel = 30; 21 // quality level 22 int qualityLevel = 30; 23 int max_count = 100; 24 void CustomHarris_Demo(int, void*); 25 void CustomShiTomasi_Demo(int, void*); 26 int main(int argc, char** argv) { 27 src = imread("D:/vcprojects/images/home.jpg"); 28 if (src.empty()) { 29 printf("could not load image...\n"); 30 return -1; 31 } 32 namedWindow("input image", CV_WINDOW_AUTOSIZE); 33 imshow("input image", src); 34 cvtColor(src, gray_src, COLOR_BGR2GRAY); 35 // 计算特征值 36 int blockSize = 3; 37 int ksize = 3; 38 double k = 0.04; 39 harris_dst = Mat::zeros(src.size(), CV_32FC(6)); 40 harrisRspImg = Mat::zeros(src.size(), CV_32FC1); 41 cornerEigenValsAndVecs(gray_src, harris_dst, blockSize, ksize, 4); 42 // 计算响应 43 for (int row = 0; row < harris_dst.rows; row++) { 44 for (int col = 0; col < harris_dst.cols; col++) { 45 double lambda1 =harris_dst.at<Vec6f>(row, col)[0]; 46 double lambda2 = harris_dst.at<Vec6f>(row, col)[1]; 47 harrisRspImg.at<float>(row, col) = lambda1*lambda2 - k*pow((lambda1 + lambda2), 2); 48 } 49 } 50 minMaxLoc(harrisRspImg, &harris_min_rsp, &harris_max_rsp, 0, 0, Mat()); 51 namedWindow(harris_win, CV_WINDOW_AUTOSIZE); 52 createTrackbar("Quality Value:", harris_win, &qualityLevel, max_count, CustomHarris_Demo); 53 CustomHarris_Demo(0, 0); 54 55 // 计算最小特征值 56 shiTomasiRsp = Mat::zeros(src.size(), CV_32FC1); 57 cornerMinEigenVal(gray_src, shiTomasiRsp, blockSize, ksize, 4); 58 minMaxLoc(shiTomasiRsp, &shitomasi_min_rsp, &shitomasi_max_rsp, 0, 0, Mat()); 59 namedWindow(shitomasi_win, CV_WINDOW_AUTOSIZE); 60 createTrackbar("Quality:", shitomasi_win, &sm_qualitylevel, max_count, CustomShiTomasi_Demo); 61 CustomShiTomasi_Demo(0, 0); 62 63 waitKey(0); 64 return 0; 65 } 66 67 void CustomHarris_Demo(int, void*) { 68 if (qualityLevel < 10) { 69 qualityLevel = 10; 70 } 71 Mat resultImg = src.clone(); 72 float t = harris_min_rsp + (((double)qualityLevel) / max_count)*(harris_max_rsp - harris_min_rsp); 73 for (int row = 0; row < src.rows; row++) { 74 for (int col = 0; col < src.cols; col++) { 75 float v = harrisRspImg.at<float>(row, col); 76 if (v > t) { 77 circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0); 78 } 79 } 80 } 81 82 imshow(harris_win, resultImg); 83 } 84 85 void CustomShiTomasi_Demo(int, void*) { 86 if (sm_qualitylevel < 20) { 87 sm_qualitylevel = 20; 88 } 89 90 Mat resultImg = src.clone(); 91 float t = shitomasi_min_rsp + (((double)sm_qualitylevel) / max_count)*(shitomasi_max_rsp - shitomasi_min_rsp); 92 for (int row = 0; row < src.rows; row++) { 93 for (int col = 0; col < src.cols; col++) { 94 float v = shiTomasiRsp.at<float>(row, col); 95 if (v > t) { 96 circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0); 97 } 98 } 99 } 100 imshow(shitomasi_win, resultImg); 101 }
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 Mat src,src_gray; 8 9 int max_corners = 20; 10 int max_count = 50; 11 12 const char* output_title = "SubPix Result"; 13 14 void SubPixel_demo(int,void*); 15 16 int main(int argc, char** argv) 17 { 18 src = imread("数字.jpg"); 19 if (src.empty()) { 20 printf("Can not load Image..."); 21 return -1; 22 } 23 imshow("input Image",src); 24 25 cvtColor(src, src_gray, COLOR_BGR2GRAY); 26 27 namedWindow(output_title,CV_WINDOW_AUTOSIZE); 28 createTrackbar("Corners:", output_title,&max_corners, max_count, SubPixel_demo); 29 SubPixel_demo(0,0); 30 31 waitKey(0); 32 return 0; 33 } 34 35 void SubPixel_demo(int, void*) 36 { 37 if (max_corners < 5) max_corners = 5; 38 39 //先进行Shi-Tomasi角点检测 40 vector<Point2f> corners; 41 double qualityLevel = 0.01; 42 double minDistance = 10; 43 int blockSize = 3; 44 goodFeaturesToTrack(src_gray, corners,max_corners,qualityLevel,minDistance,Mat()); 45 cout << "number of corners:" << corners.size() << endl; 46 47 //画出角点 48 Mat resultImage = src.clone(); 49 for (size_t t = 0; t < corners.size(); t++) 50 { 51 circle(resultImage, corners[t],2,Scalar(0,0,255),2,8,0); 52 } 53 54 imshow(output_title, resultImage); 55 56 Size winSize = Size(5,5); 57 Size zerozone = Size(-1, -1); 58 TermCriteria tc = TermCriteria(TermCriteria::EPS+ TermCriteria::MAX_ITER,40,0.001);//最大值迭代次数40,精度半径0.001 59 cornerSubPix(src_gray, corners, winSize, zerozone, tc);//corners需要输入初始坐标,然后输出精确坐标(因此前面才会先做Shi—Tomasi) 60 for (size_t t = 0; t < corners.size(); t++) 61 { 62 cout << (t + 1) << "Point(x,y):" << corners[t].x << "," << corners[t].y << endl; 63 } 64 }