提高检测精准度
理论与现实总是不一致的,实际情况下几乎所有的角点不会是一个真正的准确像素点。 检测出的点(100, 5) 实际上可能是(100.234, 5.789),可以使用亚像素定位确定准确位置
- 跟踪
- 三维重建
- 相机校正
亚像素定位方法
- 插值方法
- 基于图像矩计算
- 曲线拟合方法 -(高斯曲面(最常用)、多项式、椭圆曲面)
代码
#include "../common/common.hpp"
static Mat src, gray;
static const char title[] = "subpixel";
static int subpixel_corners = 20; // 亚像素定位,浮点数运算,比较耗时
static int subpixel_max = 50;
static RNG rng(12345);
static void subpixel(int, void*);
void main(int argc, char** argv)
{
src = imread(getCVImagesPath("images/home.jpg"), IMREAD_COLOR);
imshow("src2-8", src);
cvtColor(src, gray, COLOR_BGR2GRAY);
namedWindow(title, CV_WINDOW_AUTOSIZE);
createTrackbar("subpixel:", title, &subpixel_corners, subpixel_max, subpixel);
subpixel(0, 0);
waitKey(0);
}
void subpixel(int, void*)
{
if (subpixel_corners < 5) subpixel_corners = 5;
vector<Point2f> corners;
double qualityLevel = 0.01;
double minDistance = 10;
int blockSize = 3;
double k = 0.04;
goodFeaturesToTrack(gray, corners, subpixel_corners, qualityLevel, minDistance, Mat(), blockSize, false, k);
cout << "tomasi corners.size=" << corners.size() << endl;
Mat retImg = gray.clone();
cvtColor(retImg, retImg, CV_GRAY2BGR);
for (int i = 0; i < corners.size(); i++)
{
cout << i << ".point[x,y]=" << corners[i].x << "," << corners[i].y << endl; // 整数值
circle(retImg, corners[i], 2, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 2, 8, 0);
}
imshow(title, retImg);
Size winSize = Size(5, 5); // 窗口不要太大,不然亚像素可能会被干扰
Size zerozone = Size(-1, -1); // 拟合时使用 零区域
//TermCriteria类是用来作为迭代算法的终止条件的,参数:类型(EPS表示迭代到阈值终止),第二个参数为迭代的最大次数,最后一个是特定的阈值
TermCriteria tc = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001);
cornerSubPix(gray, corners, winSize, zerozone, tc);// 亚像素定位,为后续计算提供更高精确度的值
cout << "subpixel corners.size=" << corners.size() << endl;
for (size_t i = 0; i < corners.size(); i++)
{
cout << i << ".point[x,y]=" << corners[i].x << "," << corners[i].y << endl; // 亚像素定位出来的,精确度较高,浮点值
}
}
效果图