OpenCV——Harris、Shi Tomas、自定义、亚像素角点检测

 

 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...
");
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
",(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得到lamda1lamda2两个特征值根据他们得到角点响应值

  • 然后自己设置阈值实现计算出阈值得到有效响应值的角点设置

相关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...
");
 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 }
View Code

 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 }
原文地址:https://www.cnblogs.com/long5683/p/9692969.html