图像处理之角点检测与亚像素角点定位
角点是图像中亮度变化最强地方反映了图像的本质特征,提取图像中的角点可以有效提高图像处理速度与精准度。所以对于整张图像来说特别重要,角点检测与提取的越准确图像处理与分析结果就越接近真实。同时角点检测对真实环境下的对象识别、对象匹配都起到决定性作用。Harris角点检测是图像处理中角点提取的经典算法之一,应用范围广发,在经典的SIFT特征提取算法中Harris角点检测起到关键作用。通常对角点检测算法都有如下要求:
1. 基于灰度图像、能够自动调整运行稳定,检测出角点的数目。
2. 对噪声不敏感、有一定的噪声抑制,有较强的角点角点检测能力。
3. 准确性够高,能够正确发现角点位置
4. 算法尽可能的快与运行时间短
Harris角点检测基本上满足了上述四点要求,所以被广发应用,除了Harris角点检测,另外一种常见的角点检测算法-Shi-Tomasi角点检测也得到了广发应用,OpenCV中对这两种算法均有实现API可以调用。关于Harris角点检测原理可以看我之前写的博文:
http://blog.csdn.net/jia20003/article/details/16908661
关于Shi-Tomasi角点检测,与Harris角点检测唯一不同就是在计算角点响应值R上面。
然后根据输入的阈值T大于该阈值的R对应像素点即为图像中角点位置坐标。此刻坐标往往都是整数出现,而在真实的世界中坐标多数时候都不是整数,假设我们计算出来的角点位置P(34, 189)而实际上准确角点位置是P(34.278, 189.706)这样带小数的位置,而这样的准确位置寻找过程就叫做子像素定位或者亚像素定位。这一步在SURF与SIFT算法中都有应用而且非常重要。常见的亚像素级别精准定位方法有三类:
1. 基于插值方法
2. 基于几何矩寻找方法
3. 拟合方法 - 比较常用
拟合方法中根据使用的公式不同可以分为高斯曲面拟合与多项式拟合等等。以高斯拟合为例
这样就求出了亚像素的位置。使用亚像素位置进行计算得到结果将更加准确,对图像特征提取、匹配结果效果显著。OpenCV中已经对角点检测实现了亚像素级别的API可以调用。
代码演示OpenCV亚像素角点检测例子:
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; Mat src, gray_src; int max_corners = 10; int max_trackbar = 30; const char* output_title = "subpxiel-result"; void GoodFeature2Track_Demo(int, void*); int main(int argc, char** argv) { src = imread("D:/vcprojects/images/home.jpg"); if (src.empty()) { printf("could not load image...\n"); return -1; } cvtColor(src, gray_src, COLOR_BGR2GRAY); namedWindow("input", CV_WINDOW_AUTOSIZE); namedWindow(output_title, CV_WINDOW_AUTOSIZE); imshow("input", src); createTrackbar("Corners:", output_title, &max_corners, max_trackbar, GoodFeature2Track_Demo); GoodFeature2Track_Demo(0, 0); waitKey(0); return 0; } void GoodFeature2Track_Demo(int, void*) { if (max_corners < 1) { max_corners = 1; } vector<Point2f> corners; double qualityLevel = 0.01; double minDistance = 10; int blockSize = 3; double k = 0.04; goodFeaturesToTrack(gray_src, corners, max_corners, qualityLevel, minDistance, Mat(), blockSize, false, k); cout << "number of corners : " << corners.size() << endl; Mat copy = src.clone(); for (size_t t = 0; t < corners.size(); t++) { circle(copy, corners[t], 4, Scalar(255, 0, 0), 2, 8, 0); } imshow(output_title, copy); // locate corner point on sub pixel level Size winSize = Size(5, 5); Size zerozone = Size(-1, -1); TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001); cornerSubPix(gray_src, corners, winSize, zerozone, criteria); for (size_t t = 0; t < corners.size(); t++) { cout << (t+1) << ".point[x, y]=" << corners[t].x << "," << corners[t].y << endl; } return; }
原图如下:
运行结果:
转载请注明来自【jia20003】的博客!