基于harris角点检测理论与ShiTomasi检点检测理论,我们可以通过获取矩阵M的两个特征值以及qualityLevel的值,动态设计计算阈值T的公式,来选择我们需要的有效角点。
参数说明基本与我上一篇博客讲的参数意义相同,这里讲一下两个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检测器,可能图片不太适合展示这两个函数的效果,角点检测不是很正