学习了前面的harris角点检测之后,现在利用harris原理来自定义角点检测器,主要使用cornerEigenValsAndVecs()函数。
参考:https://blog.csdn.net/weixin_41695564/article/details/79979784
该函数参数解释如下:
src:输入图像矩阵,即单通道8位或者浮点类型的图像。
dst:输出矩阵,即用来存储结果的图像,大小与输入图像一致并且为CV_32FC(6)类型。计算自相关矩阵M的特征值和特征向量,并将它们以(λ1, λ2, x1, y1, x2,y2)的形式存储在目标图像dst中。其中λ1, λ2是M未经过排序的特征值;x1, y1是对应于λ1的特征向量;x2, y2是对应于λ2的特征向量。因此是6通道的矩阵。
blockSize:邻域大小。
ksize:Sobel算子当中的核大小,只能取1、3、5、7。
borderType:像素扩展的方法。
现将代码放入:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
using namespace std;
Mat src, gray_src;
int current_value = 30;
int Max_value = 100;
double minVal;
double maxVal;
Mat harris_res, harris_src;
void custom_corner_harris(int, void*);
const char* output_title = "output title";
int main(int argc, char** argv)
{
src = imread("D:/test/大厦.jpg");
if (src.empty())
{
cout << "the image could not found..." << endl;
return -1;
}
cvtColor(src, gray_src, COLOR_BGR2GRAY);
harris_src = Mat::zeros(src.size(), CV_32FC(6));
harris_res = Mat::zeros(src.size(), CV_32FC1);
imshow("input title", src);
// 计算特征值
int blocksize = 3;
double k = 0.04;
int ksize = 3; //Sobel算子当中的核大小,只能取1、3、5、7
cornerEigenValsAndVecs(gray_src, harris_src, blocksize, ksize, BORDER_DEFAULT);
//计算响应
for (int row = 0; row < harris_src.rows; row++)
{
for (int col = 0; col < harris_src.cols; col++)
{
double lamda1 = harris_src.at<Vec6f>(row, col)[0];
double lamda2 = harris_src.at<Vec6f>(row, col)[1];
harris_res.at<float>(row, col) = static_cast<float>(lamda1 * lamda2 - k * pow((lamda1 + lamda2), 2));
}
}
minMaxLoc(harris_res, &minVal, &maxVal, 0, 0, Mat());
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
createTrackbar("custom bar", output_title, ¤t_value, Max_value, custom_corner_harris);
custom_corner_harris(0, 0);
waitKey(0);
return 0;
}
void custom_corner_harris(int, void*)
{
if (current_value < 10)
{
current_value = 10;
}
//cvtColor(gray_src, gray_src, COLOR_GRAY2BGR);
Mat resultImg = gray_src.clone();
cvtColor(resultImg, resultImg, COLOR_GRAY2BGR);
RNG rng(12345);
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
float t = static_cast<float>(minVal + (((double)current_value) / Max_value)*(maxVal - minVal));//阈值,如果大于某个百分比,则响应
for (int row = 0; row < src.rows; row++)
{
for (int col = 0; col < src.cols; col++)
{
float v = harris_res.at<float>(row, col);
if (v > t)
{
circle(resultImg, Point(col, row), 2, Scalar(rng.uniform(0,255), rng.uniform(0, 255), rng.uniform(0, 255)), 2, 8, 0);
}
}
}
printf("corner num:%d\n", current_value);
imshow(output_title, resultImg);
}
运行结果:
值为30:
当值大于30时:
当值小于30时,窗口就会出现未响应的状态,程序运行会很慢很卡:
就会出现这种状态,所以,个人认为,当一开始取值为某个值时,最好不要低于刚开始的取值。