直接上代码
1 #include "mainwindow.h" 2 #include "ui_mainwindow.h" 3 4 #include<opencv2/opencv.hpp> 5 #include<QDebug> 6 #include<QElapsedTimer> 7 8 using namespace cv; 9 #pragma execution_character_set("utf-8") 10 MainWindow::MainWindow(QWidget *parent) 11 : QMainWindow(parent) 12 , ui(new Ui::MainWindow) 13 { 14 ui->setupUi(this); 15 16 QElapsedTimer time; 17 18 Mat img = imread("1.png"); 19 if(img.empty()) 20 return; 21 22 Mat grayImg; 23 if(img.channels() == 3) 24 cvtColor(img, grayImg, COLOR_BGR2GRAY); 25 else 26 img.copyTo(grayImg); 27 28 time.start(); 29 //[0] 找角点 30 int x = 688, y = 63, w = 100, h = 100; 31 Rect rect(x, y, w, h); 32 Mat rectImag = grayImg(rect); 33 std::vector<Point2f> points; 34 35 // 处理前要先截取图片,大图片很耗费时间 36 // 0.09比最小可接受质量corner大,可以过滤掉不需要的corner 37 goodFeaturesToTrack(rectImag, points, 2, 0.09, 10); 38 for (int i =0; i < points.size(); i++) 39 qDebug()<<"亚像素处理前: "<<points[i].x<<points[i].y; 40 41 for (int i =0; i < points.size(); i++) 42 { 43 circle(img, Point(points[i].x + x, points[i].y + y), 3, Scalar(0, 0, 255), FILLED); 44 } 45 //[0] 46 qDebug()<<time.elapsed(); // 3ms 47 48 //[1] 找到最小可接受质量corner 49 Mat dst(grayImg.rows, grayImg.cols, CV_32FC1); 50 cornerMinEigenVal(rectImag, dst, 3); 51 float bastCorner = 0; 52 for (int i =0; i < dst.rows; i++) 53 { 54 for (int j =0; j < dst.cols; j++) 55 { 56 if(dst.at<float>(i, j) > bastCorner) 57 bastCorner = dst.at<float>(i, j); // 记录最小可接受质量corner 58 } 59 } 60 61 qDebug()<<bastCorner; // 最小可接受质量corner为0.0342 62 //[1] 63 64 //[2] 亚像素级的角点检测 65 time.start(); 66 cornerSubPix(rectImag, points, Size(3, 3), Size(-1, -1), 67 TermCriteria(TermCriteria::COUNT|TermCriteria::EPS, 20, 0.01)); 68 for (int i =0; i < points.size(); i++) 69 qDebug()<<"亚像素处理后: "<<points[i].x<<points[i].y; 70 qDebug()<<time.elapsed(); // 0ms 71 //[2] 72 73 imshow("rectImag", rectImag); 74 imshow("img", img); 75 }
原图
rectImg
注意事项:
1、千万别用Harris!千万别用Harris!千万别用Harris!难调又难用!Shi-Tomas是Harris改良版。
2、goodFeaturesToTrack()算子处理的图片一定要截图,千万不要完整图片,加掩膜也没用,灰度原图(985*756)耗时150ms+,截图后才3ms。
3、goodFeaturesToTrack()算子处理前先运行cornerMinEigenVal()算子,将最小可接受质量的corner找到,才能写入合适的qualityLevel。
4、找角点还有另一种方法,通过两直线相交或者直线与圆相交的方法,但是找两条直线起码也要15ms起步,不如直接找角点快。
5、cornerSubPix()算子基本不耗时(本程序),观测结果可见至多能修正0.5个像素(±0.5取上下限),对于精度要求高的项目很有必要。
6、TermCriteria::COUNT:迭代次数或元素最大数目 TermCriteria::EPS:迭代算法终止所需精度条件。