OpenCv-C++-自定义角点检测器(harris自定义)

学习了前面的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, &current_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时,窗口就会出现未响应的状态,程序运行会很慢很卡:
在这里插入图片描述
就会出现这种状态,所以,个人认为,当一开始取值为某个值时,最好不要低于刚开始的取值。

猜你喜欢

转载自blog.csdn.net/Daker_Huang/article/details/84404147