理论与现实总是不一致的,实际情况下几乎所有角点都不是一个准确的像素点,因为图像的边缘不是之间有黑到白,而往往存在一个灰度的过度。(100,5)实际上
(100.234,5.789),而我们在跟踪、三维重建,相机校正等应用上又都需要精确的像素位置。有以下几种解决方法
1.插值法
通过周围四个点的变化情况,寻找拟合出哪一个焦点的精确位置,根据周围四个点的resp而不是真正的像素值
2.基于图像矩计算
3.曲线拟合的方式
高斯曲面(x,y,r),多项式,椭圆曲面
通过周围点的像素拟合出曲面,找到曲面的顶点,就是亚像素定位
Demo
#include"pch.h" #include<iostream> #include<opencv2/opencv.hpp> #include<math.h> using namespace std; using namespace cv; const char* output_title = "Sub-pixel CornerDetection Reslut"; double harris_mins_rsp; double harris_max_rsp; int qualityLevel = 30; int max_corners = 30; int max_count = 50; Mat src, gray_src; Mat harris_dst, harriRspImg; //Shi-Tomasi Mat ShiTomasiRspImg; double ShiTomasi_max_rsp; double ShiTomasi_min_rsp; int SM_QualityLevel = 30; void SubPixel_Demo(int,void*); int main(int argc, char** argv) { src = imread("1.jpg"); imshow("input img", src); int blocksize = 3; int ksize = 3; double k = 0.04; harriRspImg = Mat::zeros(src.size(), CV_32FC1); harris_dst = Mat::zeros(src.size(), CV_32FC(6)); namedWindow(output_title, CV_WINDOW_AUTOSIZE); cvtColor(src, gray_src, COLOR_BGR2GRAY); createTrackbar("Min Value:", output_title, &max_corners, max_count, SubPixel_Demo); SubPixel_Demo(0, 0); waitKey(); return 0; } void SubPixel_Demo(int, void*) { if (max_corners <5) qualityLevel = 5; vector<Point2f> corners; double qualityLevel = 0.05; 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 resultImg = src.clone(); for (size_t i = 0; i < corners.size(); ++i) { circle(resultImg, corners[i], 2, Scalar(0, 0, 255), 2, 8, 0); } imshow(output_title, resultImg); Size winSize = Size(5, 5); Size zerozone = Size(-1, -1); TermCriteria tc = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001); cornerSubPix(gray_src, corners, winSize, zerozone, tc); for (size_t i=0; i < corners.size(); ++i) { cout << (i + 1) << ".Point[x,y]=" << corners[i].x <<" ," << corners[i].y << endl; } return; }