应用:连续的图像移动或图像拼接场景中,确定图像中某一对象的位置。
1、角点检测原理
1.1、角点定义
在x方向和y方向都有最大梯度变化的像素点,衡量这个变化的计算式如下,为xx,xy,yx,yy四个方向的梯度sum值组成的2×2矩阵:
1.2、角点确定
a)在实际过程中,会在计算梯度时,乘以一个对应位置的权重 w(x, y),u,v为沿着对应方向移动的距离。
b)在经过转换后得到新的E(u, v)式子:
其中:
k = 0.04~0.6
c)最后解出矩阵特征值和
,再根据下图和获取的
和
来判断出该像素点是否为角点。
shi-tomasi角点检测:求min(,
) 所处区域,从而确定角点。
2、API
harris角点检测:
void cv::cornerHarris ( InputArray src,
OutputArray dst,
int blockSize,
int ksize,
double k,
int borderType = BORDER_DEFAULT
)
blockSize ——计算角点时,覆盖像素点的窗口大小,即上文中的u、v值
ksize——Sobel算子应用的卷积核大小
k ——Harris detector free parameter. See the formula below.
3、代码
void QuickDemo::harris(Mat& image)
{
//灰度图
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
//harris检测
Mat dst;
cornerHarris(gray, dst, 2, 3, 0.04);
//归一化
Mat dst_norm = Mat::zeros(dst.size(), dst.type());
normalize(dst, dst_norm, 0, 255, NORM_MINMAX, -1, Mat());
//绝对值化
convertScaleAbs(dst_norm, dst_norm);
//绘制角点
RNG rng(12345);
for (int row = 0; row < image.rows; ++row) {
for (int col = 0; col < image.cols; ++col) {
int rsp = dst_norm.at<uchar>(row, col);//取出对应像素坐标的检测值
//限制
if (rsp > 150) {
int b = rng.uniform(0, 255);
int g = rng.uniform(0, 255);
int r = rng.uniform(0, 255);
circle(image, Point(col, row), 3, Scalar(b, g, r), 1, 8);
}
}
}
namedWindow("result", WINDOW_FREERATIO);
imshow("result", image);
}