阅读(653)
赞(0)
Harris corner检测器
2017-10-11 10:02:24 更新
目标
在本教程中,您将学习:
- 什么功能和为什么它们是重要的
- 使用函数cv :: cornerHarris使用Harris-Stephens方法检测corner。
理论
什么是功能?
- 在计算机视觉中,通常我们需要在环境的不同帧之间找到匹配点。为什么?如果我们知道两个图像如何相互关联,我们可以使用这两个图像来提取它们的信息。
- 当我们说匹配点时,我们在一般意义上指的是我们可以轻松识别的场景中的特征。我们称这些特征为特征。
- 那么功能有什么特点呢?它必须是唯一可识别的
图像特征的类型
提到几个:
- 边缘
- 角(也称为兴趣点)
- 斑点(也称为感兴趣区域)
在本教程中,我们将特别研究角落特征。
为什么角落如此特别?
- 因为它是两个边的交点,它代表这两个边的方向改变的点。因此,图像的梯度(两个方向)具有高的变化,可用于检测它。
它是如何工作的?
- 让我们来看看吧。由于角代表了图像中渐变的变化,我们将寻找这种“变化”。
- 考虑一个灰度图像I。我们要扫一个窗口w(x,y)(x位移u和y方向的v)I我将计算强度的变化。
where:
- w(x,y) is the window at position (x,y)
- I(x,y) is the intensity at (x,y)
- I(x+u,y+v) is the intensity at the moved window (x+u,y+v)
- 由于我们正在寻找具有角落的窗户,所以我们正在寻找强度变化很大的窗户。因此,我们必须最大化上述方程,特别是术语:
- 使用泰勒扩展:
- 扩大方程并正确取消:
- 其中可以以矩阵形式表示为:
- 可以表示为:
- 那么现在我们的方程是:
- 计算每个窗口的分数,以确定它是否可能包含一个角:
where:
- det(M) = λ1λ2
- trace(M) = λ1+λ2
窗口R得分大于某一值的被认为是“corner”
Code
本教程代码如下所示。您也可以从这里下载
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
Mat src, src_gray;
int thresh = 200;
int max_thresh = 255;
const char* source_window = "Source image";
const char* corners_window = "Corners detected";
void cornerHarris_demo( int, void* );
int main( int, char** argv )
{
src = imread( argv[1], IMREAD_COLOR );
cvtColor( src, src_gray, COLOR_BGR2GRAY );
namedWindow( source_window, WINDOW_AUTOSIZE );
createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo );
imshow( source_window, src );
cornerHarris_demo( 0, 0 );
waitKey(0);
return(0);
}
void cornerHarris_demo( int, void* )
{
Mat dst, dst_norm, dst_norm_scaled;
dst = Mat::zeros( src.size(), CV_32FC1 );
int blockSize = 2;
int apertureSize = 3;
double k = 0.04;
cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT );
normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
convertScaleAbs( dst_norm, dst_norm_scaled );
for( int j = 0; j < dst_norm.rows ; j++ )
{ for( int i = 0; i < dst_norm.cols; i++ )
{
if( (int) dst_norm.at<float>(j,i) > thresh )
{
circle( dst_norm_scaled, Point( i, j ), 5, Scalar(0), 2, 8, 0 );
}
}
}
namedWindow( corners_window, WINDOW_AUTOSIZE );
imshow( corners_window, dst_norm_scaled );
}
结果
原始图片:
检测到的角落被一个小的黑色圆圈包围