之前的角点检测器主要都是通过固定方法的API来实现的,而我们也可以用不同角点检测方法的原理和需求去制作角点检测的函数
相关函数的介绍
1.cornerEigenValsAndVecs()函数
该函数用来求解输入图像矩阵的特征向量和特征值
主要用来模拟Harris角点检测
2.cornMinEigenVal()函数
与第一个函数相似,但是它只计算相关矩阵的最小特征值,主要用来模拟Shi-Tomasi角点检测
3.minMaxLoc()函数
寻找输入矩阵中的最小值和最大值,并可以获得对应点的位置
代码:
#include<opencv2/opencv.hpp>
#include<math.h>
#include<iostream>
using namespace cv;
using namespace std;
const char* harris_win = "Custion Harris Corners Detector";
const char* shitomasi_win = "Custon Shi-Tomasi Corners Detector";
int qualityLevel = 30;
int max_count = 100;
int sm_qualityLevel = 30;
int sm_max_count = 100;
double harris_min_rsp;
double harris_max_rsp;
Mat harris_dst, harrisRspImg;
Mat shiTomasiRsp;
double shitomasi_min_rsp;
double shitomasi_max_rsp;
void CustomHarris_Demo(int, void*);
void CustomShiTomasi_Demo(int, void*);
Mat src, gray_src;
void Tomasi_Demo(int, void*);
int main(int argc, char** argv) {
src = imread("C:/Users/18929/Desktop/博客项目/项目图片/18.jpg");
if (src.empty()) {
printf("could not load image");
return -1;
}
imshow("input_img", src);
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
//首先转换为灰度图像
cvtColor(src, gray_src, COLOR_BGR2GRAY);
//计算特征值
int blockSize = 3;
int ksize = 3;
double k = 0.04;
harris_dst = Mat::zeros(src.size(), CV_32FC(6));//CV_32FC(6)--float数据类型图片
harrisRspImg = Mat::zeros(src.size(), CV_32FC1);
//计算图像的特征值和特征向量用于计算--输出为double型数据
cornerEigenValsAndVecs(gray_src, harris_dst, blockSize, ksiaze, 4);
//计算响应值
//harris形式
for (int row = 0; row < harris_dst.rows; row++)
{
for (int col = 0; col < harris_dst.cols; col++) {
//0,1分别为两个特征值
double lambda1 = harris_dst.at<Vec6f>(row, col)[0];
double lambda2 = harris_dst.at<Vec6f>(row, col)[1];
//Harris : M = lambda1*lambda2 - k(lambda1+lambda2)^2
harrisRspImg.at<float>(row, col) = lambda1 * lambda2 - k * pow((lambda1 + lambda2), 2);
}
}
//找出全局最小值和最大值备用
minMaxLoc(harrisRspImg, &harris_min_rsp, &harris_max_rsp, 0, 0, Mat());
createTrackbar("Threshold:", harris_win, &qualityLevel, max_count, CustomHarris_Demo);
CustomHarris_Demo(0,0);
//shi-Tomasi
//计算最小特征值
Mat shiTomasiRsp = Mat::zeros(src.size(), CV_32FC1);
cornerMinEigenVal(gray_src, shiTomasiRsp, blocksize, ksize, 4);
minMaxLoc(shiTomasiRsp, &shitomasi_min_rsp, &shitomasi_max_rsp, 0, 0, Mat());
namedWindow(shitomasi_win, CV_WINDOW_AUTOSIZE);
createTrackbar("Quality:", shitomasi_win, &sm_qualityLevel, sm_max_count, CustomShiTomasi_Demo);
CustomShiTomasi_Demo(0, 0);
waitKey(0);
return 0;
}
void CustomHarris_Demo(int, char*) {
if (qualityLevel<10)
{
qualityLevel = 10;
}
Mat resultImg = src.clone();
//定义最小阈值
float t = harris_min_rsp + (((double)qualityLevel) / max_count) * (harris_max_rsp - harris_min_rsp);
for (int row = 0; row < src.rows; row++)
{
for (int col = 0; col < src.cols; col++)
{
float v = harrosRspImg.at(row, col);
//比阈值大的点作为角点并画出来
if (v>t)
{
circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0);
}
}
}
imshow(harris_win, resultImg);
}
void CustomShiTomasi_Demo(int, char*) {
if (sm_qualityLevel < 20) {
sm_qualityLevel = 20;
}
Mat resultImg = src.clone();
float t = shitomasi_min_rsp + (((double)sm_qualityLevel) / max_count) * (shitomasi_max_rsp - shitomasi_min_rsp);
for (int row = 0; row < src.rows; row++)
{
for (int col = 0; col < src.cols; col++) {
float v = shiTomasiRsp.at<float>(row, col);
if (v > t) {
circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0);
}
}
}
imshow(shitomasi_win, resultImg);
}