Harris 角点检测子
理论
有哪些特征?
在计算机视觉中,我们通常需要寻找两张图上的匹配关键点。为什么?因为一旦我们知道了两张图是相关联的,我们就可以使用 *both 图像来提取它们中的信息。
是指
- 匹配关键点 是指在场景中可以很容易识别出来的 特性 . 这些特性就是这里所说的 特征 。
- 因此,特征应该有什么样的特性呢?
- 应该具有 可识别的独一无二性
图像特征类型
图像特征类型:
- 边缘
- 角点 (感兴趣关键点)
- 斑点(Blobs) (感兴趣区域)
本教程涉及 角点 特征。
为什么角点是特殊的?
- 因为角点是两个边缘的连接点,它代表了两个边缘变化的方向上的点。图像梯度有很高的变化。这种变化是可以用来帮助检测角点的。
如何工作?
-
由于角点代表了图像像素梯度变化,我们将寻找这个”变化”。
-
考虑到一个灰度图像 . 划动窗口 (with displacements 在x方向和 方向) 计算像素灰度变化。
其中:
- is the window at position
- is the intensity at
- is the intensity at the moved window
-
为了寻找带角点的窗口,我们搜索像素灰度变化较大的窗口。于是, 我们期望最大化以下式子:
-
使用 泰勒(Taylor)展开式:
-
式子可以展开为:
-
一个举证表达式可以写为:
-
表示为:
-
因此我们有等式:
-
每个窗口中计算得到一个值。这个值决定了这个窗口中是否包含了角点:
其中:
- det(M) =
- trace(M) =
一个窗口,它的分数 大于一个特定值,这个窗口就可以被认为是”角点”
代码
这个教程的代码如下所示。还可以通过 这个链接下载到源代码
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
/// Global variables
Mat src, src_gray;
int thresh = 200;
int max_thresh = 255;
char* source_window = "Source image";
char* corners_window = "Corners detected";
/// Function header
void cornerHarris_demo( int, void* );
/** @function main */
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], 1 );
cvtColor( src, src_gray, CV_BGR2GRAY );
/// Create a window and a trackbar
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo );
imshow( source_window, src );
cornerHarris_demo( 0, 0 );
waitKey(0);
return(0);
}
/** @function cornerHarris_demo */
void cornerHarris_demo( int, void* )
{
Mat dst, dst_norm, dst_norm_scaled;
dst = Mat::zeros( src.size(), CV_32FC1 );
/// Detector parameters
int blockSize = 2;
int apertureSize = 3;
double k = 0.04;
/// Detecting corners
cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT );
/// Normalizing
normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
convertScaleAbs( dst_norm, dst_norm_scaled );
/// Drawing a circle around corners
for( int j = 0; j < dst_norm.rows ; j++ )
{ for( int i = 0; i < dst_norm.cols; i++ )
{
if