- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
Harris 角点检测器。
该函数在图像上运行 Harris 角点检测器。类似于 cornerMinEigenVal 和 cornerEigenValsAndVecs,对于每个像素 (x,y),它在一个 blockSize×blockSize 的邻域内计算一个 2×2 的梯度协方差矩阵 M(x,y)。然后,它计算以下特征值:
dst ( x , y ) = d e t M ( x , y ) − k ⋅ ( t r M ( x , y ) ) 2 \texttt{dst} (x,y) = \mathrm{det} M^{(x,y)} - k \cdot \left ( \mathrm{tr} M^{(x,y)} \right )^2 dst(x,y)=detM(x,y)−k⋅(trM(x,y))2
图像中的角点可以作为该响应图的局部最大值被找到。
cv::cornerHarris 是 OpenCV 库中的一个函数,用于检测图像中的角点。该函数基于 Harris 角点检测算法,该算法通过对图像中的每个像素计算一个响应函数来确定角点的位置。响应函数的值越大,表示该像素越有可能是角点。
函数原型
cpp
void cv::cornerHarris
(
InputArray src,
OutputArray dst,
int blockSize,
int ksize,
double k,
int borderType = BORDER_DEFAULT
)
参数
- 参数src 输入单通道 8 位或浮点图像。
- 参数dst 用于存储 Harris 检测器响应的图像。它具有类型 CV_32FC1 并且大小与 src 相同。
- 参数blockSize 邻域大小(参见 cornerEigenValsAndVecs 的详细信息)。
- 参数ksize Sobel 操作符的孔径参数。
- 参数k Harris 检测器的自由参数。参见上述公式。
- 参数borderType 像素外推方法。参见 BorderTypes。不支持 BORDER_WRAP。
代码示例
cpp
#include <iostream>
#include <opencv2/opencv.hpp>
int main()
{
// 加载图像
cv::Mat img = cv::imread( "/media/dingxin/data/study/OpenCV/sources/images/hawk.jpg", cv::IMREAD_GRAYSCALE );
if ( img.empty() )
{
std::cout << "Error opening image" << std::endl;
return -1;
}
// 计算 Harris 角点响应
cv::Mat harrisResponse;
int blockSize = 2; // 邻域大小
int ksize = 3; // Sobel 梯度算子的大小
double k = 0.04; // Harris 角点检测器中的自由参数
cv::cornerHarris( img, harrisResponse, blockSize, ksize, k );
// 显示 Harris 角点响应图像
cv::normalize( harrisResponse, harrisResponse, 0, 255, cv::NORM_MINMAX, CV_8U );
cv::namedWindow( "Harris Response", cv::WINDOW_NORMAL );
cv::imshow( "Harris Response", harrisResponse );
// 可选:标记最强的角点
double maxVal;
cv::minMaxLoc( harrisResponse, nullptr, &maxVal );
// 设置阈值
double threshold = maxVal * 0.5;
// 创建一个新的图像来标记角点
cv::Mat markedImg = img.clone();
// 标记角点
std::vector< cv::Point > corners;
cv::Mat_< uchar > responseMat = harrisResponse;
for ( int y = 0; y < responseMat.rows; ++y )
{
for ( int x = 0; x < responseMat.cols; ++x )
{
if ( responseMat( y, x ) > threshold )
{
corners.push_back( cv::Point( x, y ) );
}
}
}
// 在图像中标记角点
for ( const auto& corner : corners )
{
cv::circle( markedImg, corner, 2, cv::Scalar( 0, 0, 255 ), 2 ); // 画红色圆圈
}
// 显示标记角点的图像
cv::namedWindow( "Marked Corners", cv::WINDOW_NORMAL );
cv::imshow( "Marked Corners", markedImg );
cv::waitKey( 0 );
return 0;
}
运行结果
原始图:
Harris Response:
Marked Corners: