zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Excel 向程序发送命令时出现问题
    JavaScript中undefined,null,NaN的区别
    MYSQL查询优化(一)
    win7 去除任务栏上出现的过期图标
    InnoDB与MyISAM区别
    form表单 按回车自动提交 实现方式
    多线程下载图片
    MySQL启动不了,InnoDB: autoextending data file .\ibdata1 is of a different size 78592 pages (rounded down to MB) than specified in the .cnf file: initial 131072 pages, max 0 (relevant if nonzero) pages!
    Net EF to MySQL生成edmx文件时报错:StrongTypingException:表“TableDetails"中列“IsPrimaryKey"的值为DBNull
    DataTable转置
  • 原文地址:https://www.cnblogs.com/long5683/p/9692969.html
Copyright © 2011-2022 走看看