为何需要进行亚像素定位?
数字图像通常是离散化成像素;每个像素对应一个整数坐标位置;整数坐标位置对于很多应用并不精确,比如跟踪、相机标定、图像配准、图像拼接以及三维重构;为达到有些应用的精确性,需要精确到浮点坐标位置;所以亚像素定位问题。亚像素定位就是计算特征所在图像中的真实位置,而真实位置有时候并不在像素所在整数坐标位置上,而是在像素的内部。
点的灰度分布特征跟二维高斯模型很相似,中心处最亮,离中心距离越远会随之变暗。所以这里的图像特征,我们用高斯模型进行描述。
利用高斯模型,我们可以构建点的最终模型函数M,如下:
上述表达式中的各个参数解释如下:
>M:代表对应像素位置上的强烈程度
>(x,y):图像中某个像素位置
>A:背景的强烈程度,比如上面的黑色区域
>B:亮区域中的强烈程度的峰值
>(u,v):亮区域中的峰值所在的位置
>sigma:高斯模型方差
即对应像素位置的强度与模型函数M估计出来的强度相同,那么我们认为用该模型匹配点区域的像素值是完美的,该模型是适合描述该区域的特征。事实上,在点区域里,保证不了左右两等式相等,我们只求左右两等式尽量逼近,求解模型的最佳参数,基本都是通过残差进行分析,如:
在进行残差计算前,首先使用一个简单算法粗定位一个位置,将窗口中心移动至该位置上,再进行残差计算。我们的目的是最小化误差
,即可获取亚像素位置坐标(u,v)。 亚像素定位方法可以直接对误差函数的每一个参数进行偏导求取,也可以使用梯度下降法进行求解,最终得到模型的相关参数(这里极有可能得到的解是局部最优解)。当然求解的方法很多,最好使用的方法能解出全局最优解,这样解的模型才是最优的。
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include
#include
#include
using namespace cv;
using namespace std;
#define WINDOW_NAME "Shi-Tomasi CornorDetect"
Mat src, gray;
vector corners;//声明为全局变量否则报错,圆心坐标
int maxCornerNum = 10;
int maxTrackbarNum = 300;
//滚动条回调函数
void cornersRefinement(int, void*){
Mat copy = src.clone();
if (maxCornerNum <= 1){
maxCornerNum = 1;
}
//角点检测参数准备
double qualityLevel = 0.2;//角点检测可接受的最小特征值0.01
double minDistance = 10;//角点之间的最小距离
int blockSize = 3;//计算导数自相关矩阵时的指定的领域范围
double k = 0.04;//权重系数
//进行Shi-Tomasi角点检测
goodFeaturesToTrack(gray,
corners,
maxCornerNum,
qualityLevel,
minDistance,
Mat(),
blockSize,
false,
k);
//像素级角点使用蓝色圆圈绘制
for (int i = 0; i
circle(copy, corners[i], 8, Scalar(255, 0, 0), 2, 8, 0);
}
/// 角点位置精准化参数
Size winSize = Size(5, 5);
Size zeroZone = Size(-1, -1);
//迭代的终止条件
TermCriteria criteria = TermCriteria(
CV_TERMCRIT_EPS + CV_TERMCRIT_ITER,
40, //maxCount=40
0.001); //epsilon=0.001
/// 计算精准化后的角点位置
cornerSubPix(gray, corners, winSize, zeroZone, criteria);
//亚像素级角点使用品红色圆圈绘制
for (int i = 0; i
circle(copy, corners[i], 4, Scalar(255, 0, 255), 2, 8, 0);
// 输出角点坐标
cout <
}
cout <
imshow(WINDOW_NAME, copy);
}
int main(){
src = imread("Goldhill.bmp", 1);
cvtColor(src, gray, CV_BGR2GRAY);
namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME, src);
createTrackbar("MaxNofCornor:", WINDOW_NAME, &maxCornerNum, maxTrackbarNum, cornersRefinement);
cornersRefinement(0, 0);
cvWaitKey(0);
return 0;
}
————————————————
版权声明:本文为CSDN博主「凡是坚持」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
#转载请注明出处 www.skcircle.com 《少有人走的路》勇哥的工业自动化技术网站。如果需要本贴图片源码等资源,请向勇哥索取。