角点检测
执行角点检测并在可能的角点周围画一个圆
对图像中的角点位置进行检测和细化
Shi-Tomasi方法检测图像角点
1. cornerDetector_Demo.cpp 角点检测
/**
* @function cornerDetector_Demo.cpp
* @brief Demo code for detecting corners using OpenCV built-in functions
* 使用 OpenCV 内置函数进行角点检测的示例代码
* @author OpenCV team
*/
#include "opencv2/highgui.hpp" // 包含OpenCV图形界面高级操作的头文件
#include "opencv2/imgproc.hpp" // 包含OpenCV图像处理的头文件
#include <iostream> // 包含标准输入输出流的头文件
using namespace cv; // 使用cv命名空间
using namespace std; // 使用std命名空间
/// 全局变量定义
Mat src, src_gray; // 原图和转换为灰度图的图像
Mat myHarris_dst, myHarris_copy, Mc; // Harris算法结果、副本和M矩阵
Mat myShiTomasi_dst, myShiTomasi_copy; // Shi-Tomasi算法结果和副本
int myShiTomasi_qualityLevel = 50; // Shi-Tomasi算法质量等级
int myHarris_qualityLevel = 50; // Harris算法质量等级
int max_qualityLevel = 100; // 最大质量等级
double myHarris_minVal, myHarris_maxVal; // Harris算法最小和最大值
double myShiTomasi_minVal, myShiTomasi_maxVal; // Shi-Tomasi算法最小和最大值
RNG rng(12345); // 随机数生成器,用于产生颜色
const char* myHarris_window = "My Harris corner detector"; // Harris检测器窗口名称
const char* myShiTomasi_window = "My Shi Tomasi corner detector"; // Shi-Tomasi检测器窗口名称
/// 函数头定义
void myShiTomasi_function( int, void* ); // Shi-Tomasi算法函数
void myHarris_function( int, void* ); // Harris算法函数
/**
* @function main
*/
int main( int argc, char** argv )
{
/// 加载源图像并将其转换为灰度图
CommandLineParser parser( argc, argv, "{@input | building.jpg | input image}" );
src = imread( samples::findFile( parser.get<String>( "@input" ) ) );
if ( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
cvtColor( src, src_gray, COLOR_BGR2GRAY );
/// 设置一些参数
int blockSize = 3, apertureSize = 3; // 定义Harris矩阵和Shi-Tomasi矩阵的块大小和孔径大小
/// 使用cornerEigenValsAndVecs计算Harris矩阵
cornerEigenValsAndVecs( src_gray, myHarris_dst, blockSize, apertureSize );
/* 计算 Harris 响应函数Mc */
Mc = Mat( src_gray.size(), CV_32FC1 ); // 初始化Mc矩阵,大小与灰度图一致
for( int i = 0; i < src_gray.rows; i++ ) // 遍历图像的每一行
{
for( int j = 0; j < src_gray.cols; j++ ) // 遍历图像的每一列
{
float lambda_1 = myHarris_dst.at<Vec6f>(i, j)[0]; // 获取第一个特征值lambda_1
float lambda_2 = myHarris_dst.at<Vec6f>(i, j)[1]; // 获取第二个特征值lambda_2
Mc.at<float>(i, j) = lambda_1*lambda_2 - 0.04f * ((lambda_1 + lambda_2) * (lambda_1 + lambda_2)); // 计算Mc中每个像素的Harris响应值
}
}
minMaxLoc( Mc, &myHarris_minVal, &myHarris_maxVal ); // 寻找Mc中的最小值和最大值
/* 创建窗口和滑动条 */
namedWindow( myHarris_window ); // 创建一个名为"My Harris corner detector"的窗口
createTrackbar( "Quality Level:", myHarris_window, &myHarris_qualityLevel, max_qualityLevel, myHarris_function ); // 创建一个滑动条以调整Harris检测器的质量等级
myHarris_function( 0, 0 ); // 调用Harris检测器函数
/// 使用cornerMinEigenVal计算Shi-Tomasi矩阵
cornerMinEigenVal( src_gray, myShiTomasi_dst, blockSize, apertureSize ); // 直接计算灰度图的Shi-Tomasi响应值
minMaxLoc( myShiTomasi_dst, &myShiTomasi_minVal, &myShiTomasi_maxVal ); // 寻找Shi-Tomasi响应值矩阵中的最小值和最大值
/* 创建窗口和滑动条 */
namedWindow( myShiTomasi_window ); // 创建一个名为"My Shi Tomasi corner detector"的窗口
createTrackbar( "Quality Level:", myShiTomasi_window, &myShiTomasi_qualityLevel, max_qualityLevel, myShiToma