前言
亚像素级角点检测的位置在摄像机标定,跟踪并重建摄像机的轨迹,或者重建被跟踪目标的三维结构时,是一个基本的测量值;
这就需要比较高的精度,而前面我们提到的goodFeaturesToTrack()函数只能提供简单的像素坐标(因为有时候我们需要的是实数坐标而不是整数坐标)
关于亚像素级角点检测的算法
本人能力有限无法清晰的阐述,所以有兴趣的小伙伴可以访问
正文
opencv中提供了 cornerSubPix(),函数用于寻找亚像素焦点位置(浮点型)
API:
void cornerSubPix( InputArray image,
InputOutputArray corners,
Size winSize,
Size zeroZone,
TermCriteria criteria
);
- 第一个参数,源图像
- 第二个参数,类型corners ,verctor< Point2f >提供输入角点的初始坐标和精确的输出坐标(既是输入又是输出)
- 第三个参数,搜索窗口一半的尺寸。若winSize=Size(5,5),那么搜索窗口大小为(52 + 1)(5*2 + 1) = 11 * 11 大小的搜索窗口
- 第四个参数,表示死区的一尺寸半,作用用来规避自相关矩阵出现某些可能的奇异性,(-1,-1)表示没有死区
- 第五个参数,TermCriteria类型的criteria,求角点的迭代过程的终止条件。
关于TermCriteria构造函数
转载于:https://blog.csdn.net/ilyhlf5201314/article/details/8232746
CvTermCriteria
迭代算法的终止准则
#define CV_TERMCRIT_ITER 1
#define CV_TERMCRIT_NUMBER CV_TERMCRIT_ITER
#define CV_TERMCRIT_EPS 2
typedef struct TermCriteria
{
int type; /* CV_TERMCRIT_ITER 和CV_TERMCRIT_EPS二值之一,或者二者的组合 */
int max_iter; /* 最大迭代次数 */
double epsilon; /* 结果的精确性 */
}
CvTermCriteria;
/* 构造函数 */
inline CvTermCriteria cvTermCriteria( int type, int max_iter, double epsilon );
/* 在满足max_iter和epsilon的条件下检查终止准则并将其转换使得type=CV_TERMCRIT_ITER+CV_TERMCRIT_EPS */
CvTermCriteria cvCheckTermCriteria( CvTermCriteria criteria,
double default_eps,
int default_max_iters
);
代码:
# include <opencv2\opencv.hpp>
# include <iostream>
using namespace std;
using namespace cv;
Mat src, dst, gray_src;
int max_corners = 30;
int max_count = 50;
const char *output_tittle = "Subpixel Result";
void Subpixel_Demo(int, void *);
int main(int argc, char**argv) {
src = imread("H:\\tuku\\city.jpg");
if (!src.data)
{
cout << "can't find the picture...";
return -1;
}
imshow("in put", src);
cvtColor(src, gray_src, COLOR_BGR2GRAY);
namedWindow(output_tittle, 1);
createTrackbar("Corners:", output_tittle, &max_corners, max_count, Subpixel_Demo);
Subpixel_Demo(0, 0);
waitKey(0);
return 0;
}
void Subpixel_Demo(int, void*) {
if (max_corners < 5) {
max_corners = 5;
}
vector<Point2f> corners;
double quality_level = 0.01;
double minDistance = 10;
int BlockSize = 3;
int ksize = 3;
double k = 0.04;
goodFeaturesToTrack(gray_src, corners, max_corners, quality_level, minDistance, Mat(), BlockSize, false, k);
cout << "number of corners:" << corners.size()<<endl;
Mat ResultImag = src.clone();
for (size_t i = 0; i < corners.size(); i++) {
circle(ResultImag, corners[i], 2, Scalar(0, 0, 255), 2, 8, 0);
}
//建立goodTeaturesToTrack()目的 获取corners来输出精确坐标
imshow(output_tittle, ResultImag);
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 t = 0; t < corners.size(); t++) {
cout << t + 1 << ",Point[x,y]=" << corners[t].x << "," << corners[t].y << endl;
}
}