目标

在本教程中,您将学习:

  • 特征时什么,为什么他们很重要
  • 使用函数cv :: cornerHarris以及Harris-Stephens方法检测拐角。

理论

什么是特征?

  • 在计算机视觉中,通常我们需要找到环境的不同帧之间的匹配点。为什么?如果我们知道两个图像如何相互关联,我们可以使用这两个图像来提取它们的信息。
  • 当我们说匹配点时,一般指的是我们可以轻易识别的场景中的特征我们称这些为特征
  • 那么,特征应具备哪些特性呢?
    • 它必须是唯一可识别的

图像特征的类型

  • 边缘
  • 角落(也称为兴趣点)
  • 斑点(也称为感兴趣的区域)

在本教程中,我们将专门研究角落特征。

为什么角落如此特别?

  • 因为它是两条边的交点,所以它表示这两条边的方向改变的点因此,图像的梯度(在两个方向上)具有很高的变化,可用于检测它。

它是如何工作的?

  • 我们来找角落。由于角落代表图像中渐变的变化,我们将寻找这种“变化”。
  • 考虑一个灰度图像I我们要移动窗口,其中与在x方向位移为u和在y方向的位移为v,计算强度的变化。
E(u,v)=x,yw(x,y)[I(x+u,y+v)I(x,y)]2

其中:w(x,y)是位置(x,y)的窗口,I(x,y)是位置(x,y)的强度,I(x+u,y+v)是位置(x+u,y+v)处的的强度

  • 我们正在寻找有拐角的窗口,其强度变化很大。因此,我们必须最大化上面的等式:
x,y[I(x+u,y+v)I(x,y)]2

  • 使用泰勒展开
E(u,v)x,yu2I2x+2uvIxIy+v2I2y
  • 矩阵表示:
E(u,v)[uv](x,yw(x,y)[I2xIxIyIxIyI2y])[uv]
  • 也就是:
M=x,yw(x,y)[I2xIxIyIxIyI2y]
  • 也就是:
E(u,v)[uv]M[uv]
  • 计算每个窗口的分数,以确定它是否可能包含角点:
R=det(M)k(trace(M))2

其中:det(M) = λ1λ2 ,trace(M) = λ1+λ2

程序

#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 argc, char** argv )
{
    CommandLineParser parser( argc, argv, "{@input | building.jpg | input image}" );
    src = imread( 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 );
    namedWindow( source_window );
    createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo );
    imshow( source_window, src );
    cornerHarris_demo( 0, 0 );
    waitKey();
    return 0;
}
void cornerHarris_demo( int, void* )
{
    int blockSize = 2;
    int apertureSize = 3;
    double k = 0.04;
    Mat dst = Mat::zeros( src.size(), CV_32FC1 );
    //输入,输出,邻域大小,sobel算子大小,k
    cornerHarris( src_gray, dst, blockSize, apertureSize, k );
    Mat dst_norm, dst_norm_scaled;
    //输入,输出,最小值,最大值,归一化类型,类型,掩码
    normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
    //计算结果,并将结果转换为8位。输入,输出,alpha.
    convertScaleAbs( dst_norm, dst_norm_scaled );
    for( int i = 0; i < dst_norm.rows ; i++ )
    {
        for( int j = 0; j < dst_norm.cols; j++ )
        {
            if( (int) dst_norm.at<float>(i,j) > thresh )
            {
                circle( dst_norm_scaled, Point(j,i), 5,  Scalar(0), 2, 8, 0 );
            }
        }
    }
    namedWindow( corners_window );
    imshow( corners_window, dst_norm_scaled );

}

说明

结果

2D Features framework 1(Harris corner detector)

相关文章: