1. 程式人生 > >OpenCv-C++-自定義角點檢測器(harris自定義)

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時,視窗就會出現未響應的狀態,程式執行會很慢很卡:
在這裡插入圖片描述
就會出現這種狀態,所以,個人認為,當一開始取值為某個值時,最好不要低於剛開始的取值。