使用亚像素级别角点检测,返回角点的浮点数值,它的精度比整数像素更准确。可以用cornerSubPix()函数将角点定位到子像素,从而取得亚像素级别的角点检测效果。
使用函数:
void cv::cornerSubPix ( InputArray image,
InputOutputArray corners,
Size winSize,
Size zeroZone,
TermCriteria criteria
)
参考:https://blog.csdn.net/holybin/article/details/41122493
函数参数说明如下:
image:输入图像
corners:输入角点的初始坐标以及精准化后的坐标用于输出。
winSize:搜索窗口边长的一半,例如如果winSize=Size(5,5),则一个大小为的搜索窗口将被使用。
zeroZone:搜索区域中间的dead region边长的一半,有时用于避免自相关矩阵的奇异性。如果值设为(-1,-1)则表示没有这个区域。
criteria:角点精准化迭代过程的终止条件。也就是当迭代次数超过criteria.maxCount,或者角点位置变化小于criteria.epsilon时,停止迭代过程。
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace std;
using namespace cv;
Mat src,gray_src;
int maxCorner = 20;
int max_value = 200;
const char* output_title = "subpixel window";
void subpixel(int,void*);
int main(int argc, char** argv)
{
src = imread("D:/test/大厦.jpg");
if (!src.data)
{
cout << "图片未找到" << endl;
return -1;
}
cvtColor(src, gray_src, CV_BGR2GRAY);
imshow("input title", src);
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
createTrackbar("subpixel num", output_title, &maxCorner, max_value, subpixel);
subpixel(0, 0);
waitKey(0);
return 0;
}
void subpixel(int, void *)
{
if (maxCorner < 5)
{
maxCorner = 5;
}
vector<Point2f>corners;
goodFeaturesToTrack(gray_src, corners,maxCorner, 0.01, 10, Mat(), 3, false, 0.04);
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);
}
cout << "corner num: " << corners.size() << endl;
imshow(output_title, resultImg);
Size size = Size(5, 5);//最多只能取到5
//迭代算法的终止准则,该类变量需要3个参数,一个是类型,第二个参数为迭代的最大次数,最后一个是特定的阈值
TermCriteria tc = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.01);
cornerSubPix(gray_src, corners, size, Size(-1, -1), tc);
//这里的corner重新变了,变成cornerSubPix里的corners了
for (size_t t = 0; t < corners.size(); t++)
{
cout << t + 1 << ".pixel[x,y]= " << corners[t].x <<","<< corners[t].y << endl;
}
return;
}
可以看到,像素坐标返回的是一个浮点数,比原来的整数值更加精准。