阈值的设定主要是通过R值矩阵中的R值大小来确定的:
通过阈值来确定需要的角点R值的范围
R值矩阵的计算参看:https://www.cnblogs.com/Jack-Elvis/p/11640931.html
harris和shiTomasi两种自定义阈值的角点检测代码如下:
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 #include <math.h> 5 using namespace cv; 6 using namespace std; 7 const char* harris_win = "Custom Harris Corners Detector"; 8 const char* shitomasi_win = "Custom Shi-Tomasi Corners Detector"; 9 10 Mat src, gray_src; 11 // harris corner response 12 Mat harris_dst, harrisRspImg; 13 double harris_min_rsp; 14 double harris_max_rsp; 15 // shi-tomasi corner response 16 17 Mat shiTomasiRsp; 18 double shitomasi_max_rsp; 19 double shitomasi_min_rsp; 20 int sm_qualitylevel = 30; //shiTomasiRsp矩阵的拖动变量 21 // quality level 22 int qualityLevel = 30; //harrisRspImg R矩阵的拖动变量 23 int max_count = 100; 24 25 void CustomHarris_Demo(int, void*); 26 void CustomShiTomasi_Demo(int, void*); 27 28 29 int main(int argc, char** argv) { 30 src = imread("L:/6.jpg"); 31 if (src.empty()) { 32 printf("could not load image...\n"); 33 return -1; 34 } 35 namedWindow("input image", CV_WINDOW_AUTOSIZE); 36 imshow("input image", src); 37 cvtColor(src, gray_src, COLOR_BGR2GRAY); 38 39 40 //1.harris方法 计算特征值: 41 int blockSize = 3; 42 int ksize = 3; 43 double k = 0.04; 44 harris_dst = Mat::zeros(src.size(), CV_32FC(6)); 45 harrisRspImg = Mat::zeros(src.size(), CV_32FC1); 46 cornerEigenValsAndVecs(gray_src, harris_dst, blockSize, ksize, 4); 47 // 计算gray_src响应, 输出herris_dst特征矩阵 48 49 for (int row = 0; row < harris_dst.rows; row++) { 50 for (int col = 0; col < harris_dst.cols; col++) { 51 double lambda1 = harris_dst.at<Vec6f>(row, col)[0]; //harris_dst:M特征矩阵中的特征值:λ1 52 double lambda2 = harris_dst.at<Vec6f>(row, col)[1]; //harris_dst:M特征矩阵中的特征值:λ2 53 harrisRspImg.at<float>(row, col) = lambda1*lambda2 - k*pow((lambda1 + lambda2), 2); 54 //harrisRspImg:R矩阵 R = det(M)-k(traceM)2 //平方 55 } 56 } 57 minMaxLoc(harrisRspImg, &harris_min_rsp, &harris_max_rsp, 0, 0, Mat()); 58 //寻找harrisRspImg矩阵中R的最大最小值: harris_min_rsp harris_max_rsp 59 namedWindow(harris_win, CV_WINDOW_AUTOSIZE); 60 createTrackbar("Quality Value:", harris_win, &qualityLevel, max_count, CustomHarris_Demo); 61 CustomHarris_Demo(0, 0); 62 63 64 65 //2. shiTomasi方法 计算最小特征值: 66 shiTomasiRsp = Mat::zeros(src.size(), CV_32FC1); //定义R矩阵类型 67 cornerMinEigenVal(gray_src, shiTomasiRsp, blockSize, ksize, 4); 68 // 输出shiTomasiRsp特征矩阵;即R矩阵 69 minMaxLoc(shiTomasiRsp, &shitomasi_min_rsp, &shitomasi_max_rsp, 0, 0, Mat()); 70 //找出shiTomasiRsp矩阵最大最小值 71 namedWindow(shitomasi_win, CV_WINDOW_AUTOSIZE); 72 createTrackbar("Quality:", shitomasi_win, &sm_qualitylevel, max_count, CustomShiTomasi_Demo); 73 CustomShiTomasi_Demo(0, 0); 74 75 waitKey(0); 76 return 0; 77 } 78 79 void CustomHarris_Demo(int, void*) { 80 if (qualityLevel < 10) { 81 qualityLevel = 10; 82 } 83 Mat resultImg = src.clone(); 84 float t = harris_min_rsp + (((double)qualityLevel) / max_count)*(harris_max_rsp - harris_min_rsp); 85 //阈值t = R矩阵最小值 + 百分之qualityLevel(滑动条)* R矩阵的值得范围(max-min) 86 for (int row = 0; row < src.rows; row++) { 87 for (int col = 0; col < src.cols; col++) { 88 float v = harrisRspImg.at<float>(row, col); //提取R矩阵的值给v 89 if (v > t) { //画出v>t的点 90 circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0); 91 } 92 } 93 } 94 95 imshow(harris_win, resultImg); 96 } 97 98 //下面函数与上面CustomHarris_Demo函数一样 99 void CustomShiTomasi_Demo(int, void*) { 100 if (sm_qualitylevel < 20) { 101 sm_qualitylevel = 20; 102 } 103 104 Mat resultImg = src.clone(); 105 float t = shitomasi_min_rsp + (((double)sm_qualitylevel) / max_count)*(shitomasi_max_rsp - shitomasi_min_rsp); 106 for (int row = 0; row < src.rows; row++) { 107 for (int col = 0; col < src.cols; col++) { 108 float v = shiTomasiRsp.at<float>(row, col); 109 if (v > t) { 110 circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0); 111 } 112 } 113 } 114 imshow(shitomasi_win, resultImg); 115 }
结果:
1.harris 2.shiTomasi