Opencv特征提取与目标检测03

Opencv特征提取与目标检测03:自定义角点检测器

介绍

基于harris角点检测理论与ShiTomasi检点检测理论,我们可以通过获取矩阵M的两个特征值以及qualityLevel的值,动态设计计算阈值T的公式,来选择我们需要的有效角点。
Opencv特征提取与目标检测03_第1张图片

相关API

Opencv特征提取与目标检测03_第2张图片参数说明基本与我上一篇博客讲的参数意义相同,这里讲一下两个API output的图像。

第一个API
基于harris角点检测理论的,输出的图像dst必须定义为CV_32FC1等类型,且:矩阵的每个特征值由下式求得。

doulbe λ1 = dst.at(row,col)[0];
doulbe λ2 = dst.at(row,col)[1];

R=λ1× λ2 -k×(λ1+λ2)^2
计算出的每一个角度响应R保存为图片result的像素值。(float型)
然后在result上寻找最大最小响应,设计出选择的阈值T。
我的一部分代码如下

//在result上寻找最大最小响应R
	minMaxLoc(result, &min_harris_rsp, &max_harris_rsp, 0, 0, Mat());
	
//根据lambda1,lambda2计算阈值t
	float t = min_harris_rsp + (((double)qualityLevel) / max_count)*(max_harris_rsp -min_harris_rsp);

第二个API
基于Shi-Tomasi角点检测理论的,输出的图像corner已经保存了所有的角度响应值R,等同于上面的result,然后在result上寻找最大最小响应,设计出选择的阈值T。我的一部分代码如下

//找出最大最小的响应R
	minMaxLoc(shitomasi_corner, &min_shitomasi_rsp, &max_shitomasi_rsp, 0, 0, Mat());


//根据响应R计算阈值t
	float t = min_shitomasi_rsp + (((double)sm_qualityLevel) / max_count)*(max_shitomasi_rsp - min_shitomasi_rsp);

代码演示

// Opencv 文件.cpp :
#include "pch.h"
#include
#include
#include 
using namespace cv;
using namespace std;
Mat harris_rsp;
Mat result;//存储响应的R
int blocksize = 3;//矩阵M的大小
double k = 0.04;//响应系数
int ksize = 3;//窗口
int qualityLevel = 30;
int max_count = 100;
double min_harris_rsp;
double max_harris_rsp;

double min_shitomasi_rsp;
double max_shitomasi_rsp;
int sm_qualityLevel=30;
void cornerShit_tomasi_demo(int, void*);
void cornerharris_demo(int, void*);
Mat gray;
Mat src1;
Mat  shitomasi_corner;
char OUTPUT_WIN[] = "corner_harris_demo";
char OUTPUT_shitomasi_WIN[] = "corner_shitomasi_demo";
int main()
{
	src1 = imread("E:\\360downloads\\core.jpg");
	if (!src1.data) {//!src.data与src.empty()一样;
		printf("failure to load the image1 ");
		return -1;
	}
	namedWindow(OUTPUT_WIN, WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_shitomasi_WIN, WINDOW_AUTOSIZE);
	imshow("src1", src1);
	cvtColor(src1, gray, COLOR_BGR2GRAY);


	//定义 自定义角点harris检测器的输出图片
	harris_rsp = Mat::zeros(src1.size(), CV_32FC(6));//注意是cv_32FC(6);
	//获取lambda1,2,计算角点响应
	cornerEigenValsAndVecs(gray, harris_rsp, blocksize, ksize, 4);
	result = Mat::zeros(src1.size(), CV_32FC1);//注意这里必须是32位浮点型
	for (int row = 0; row < harris_rsp.rows; row++) {
		for (int col = 0; col < harris_rsp.cols; col++) {
			double lambda1 = harris_rsp.at(row, col)[0];//注意这里是Vec6f;
			double lambda2 = harris_rsp.at(row, col)[1];
			result.at(row, col) = lambda1 * lambda2 - k * pow((lambda1 + lambda2), 2);//这里是浮点型
		}
	}
	//在result上寻找最大最小响应
	minMaxLoc(result, &min_harris_rsp, &max_harris_rsp, 0, 0, Mat());
	//printf("%d,%d\n", min_harris_rsp, max_harris_rsp);


	//自定义角点检测shitomasi器;区别就是shitomasi得到的输出shitomasi_corner直接包含了响应R,不用再自己获取lambda1,2;
	cornerMinEigenVal(gray, shitomasi_corner,blocksize, ksize, 4);
	minMaxLoc(shitomasi_corner, &min_shitomasi_rsp, &max_shitomasi_rsp, 0, 0, Mat());

	//创建滑动条事件
	createTrackbar("qualityLevel:", OUTPUT_WIN, &qualityLevel, max_count, cornerharris_demo);
	createTrackbar("shitomasi_qualityLevel:", OUTPUT_shitomasi_WIN, &sm_qualityLevel, max_count, cornerShit_tomasi_demo);
	cornerharris_demo(0, 0);
	cornerShit_tomasi_demo(0, 0);
	waitKey(0);



	return 0;
}
//harris
void cornerharris_demo(int, void*) {
	if (qualityLevel < 10) {
		qualityLevel = 10;
	}
	Mat resultImage = src1.clone();
	//根据lambda1,lambda2计算阈值t
	float t = min_harris_rsp + (((double)qualityLevel) / max_count)*(max_harris_rsp - min_harris_rsp);
	printf("%.6f\n", t);//0.0012左右
	for (int row = 0; row < src1.rows; row++) {
		for (int col = 0; col < src1.cols; col++) {
			float v = result.at(row, col);
			//printf("%f\n", v);基本是0;
			if (v > t) {
				circle(resultImage, Point(row, col), 2, Scalar(0, 0, 255), 2);
			}
			//else printf("error\n");

		}
	}
	imshow(OUTPUT_WIN, resultImage);
}
//shitomasi
void cornerShit_tomasi_demo(int, void*) {
	if (qualityLevel < 20) {
		qualityLevel = 20;
	}
	Mat resultImage = src1.clone();
	//根据响应R计算阈值t
	float t = min_shitomasi_rsp + (((double)sm_qualityLevel) / max_count)*(max_shitomasi_rsp - min_shitomasi_rsp);
	printf("%.5f\n", t);//0.0012左右
	for (int row = 0; row < src1.rows; row++) {
		for (int col = 0; col < src1.cols; col++) {
			float v = shitomasi_corner.at(row, col);
			//printf("%f\n", v);基本是0;
			if (v > t) {
				circle(resultImage, Point(row, col), 2, Scalar(0, 0, 255), 2);
			}
			//else printf("error\n");

		}
	}
	imshow(OUTPUT_shitomasi_WIN, resultImage);

}







右边是ShiTomasi检测器,左边是Harris检测器,可能图片不太适合展示这两个函数的效果,角点检测不是很正

你可能感兴趣的:(#,Opencv进阶特征提取)