其他分享
首页 > 其他分享> > Harris角点检测

Harris角点检测

作者:互联网

Harris角点提取算法:Harris 角点提取算法是Chris Harris 和Mike Stephens 在H.Moravec 算法的基础上发展出的通过自相关矩阵的角点提取算法,又称Plessey算法。Harris角点提取算法这种算子受信号处理中自相关面数的启发,给出与自相关函数相联系的矩阵M。M 阵的特征值是自相关函数的一阶曲率,如果两个曲率值都高,那么就认为该点是角点特征。

 

我的理解是角点作为一种图像特征,常常描述图像中的拐角,边界点等信息,使用滑动窗口的方式来进行识别,原理类似于边缘检测,检测窗口内的灰度突变。如果滑动窗口在各个方向滑动时都发生了灰度突变,则认为出现了角点,如果只有一个方向出现了突变,认为是遇到了直线线段。

 

 

 窗口平移产生的灰度变化计算如下

 

 

 其中窗口的权重可以采用边缘检测类似的01权重也可以采用高斯分布,越靠近中心像素点权重越高

 

 

 将公式平移,做泰勒展开

 

 

 

 

 

 因为Ο(u2,v2)近似为0,所以这个展开式可以进一步简化,uv是局部微小移动量,因此可以将余项忽略,得到一个二项式函数

 

 

 

 

 

 M由图像求导计算得出

 

 

 

其中M=W*MI,MI又等于

 

 

 该卷积的目的是得到MI在周围像素上的局部平均。矩阵M又称为Harris矩阵。W 的宽度决定了在像素x 周围的感兴趣区域,即邻域大小。

像这样在区域附近对矩阵M取平均的原因是,特征值会依赖于局部图像特性而变化。如果图像的梯度在该区域变化,那么MI 的第二个特征值将不再为0。如果图像的梯度没有变化,M的特征值也不会变化。

              忽略余项之后的表达式为一个二项式函数,然而二项式函数的本质上就是一个椭圆函数,椭圆的扁率和尺寸是由M(x,y)的特征值λ1、λ2决定的,椭圆的方向是由M(x,y)的特征矢量决定的,如下图所示,椭圆方程为:

 

 

 

椭圆函数特征值与图像中的角点、直线(边缘)和平面之间的关系如下图所示。共可分为三种情况:

           a. 图像中的直线。一个特征值大,另一个特征值小,λ1>λ2或λ2>λ1。自相关函数值在某一方向上大,在其他方向上小。

           b. 图像中的平面。两个特征值都小,且近似相等;自相关函数数值在各个方向上都小。

           c. 图像中的角点。两个特征值都大,且近似相等,自相关函数在所有方向都增大。

通过M的两个特征值λ1和λ2的大小对图像点进行分类:

 

 

 

 如果λ1和λ2都很小,图像窗口在所有方向上移动都无明显灰度变化。

       由于我们是通过M的两个特征值的大小对图像进行分类,所以,定义角点相应函数R:

                                     

                                      

                                        

        

        其中k为经验常数,一般取k=0.04~0.06。为了去除加权常数κ,我们通常使用商数detM/(traceM)2作为指示器。:所以,上图可以转化为:

 

 

 

 其中:

               •  R 只与M的特征值有关

               • 角点:R 为大数值正数

               • 边缘:R 为大数值负数

               • 平坦区:R 为小数值

         在判断角点的时候,–对角点响应函数R进行阈值处理:R > threshold,提取R的局部极大值。

 

API

void cv::cornerHarris(

InputArray src,//灰度图像

OutputArray dst,

int BlockSize,    // 计算λ1λ2时候的矩阵大小,常为2

int ksize,      // 窗口大小,一般为3

double k,      // 表示计算角度响应时候的参数大小,一般取0.04~0.06

int borderType=BORDERDEFAULT

)

 

demo

#include"pch.h"
#include<iostream>
#include<opencv2/opencv.hpp>
#include<math.h>
using namespace std;
using namespace cv;


const char* output_title = "HarrisCornerDetection Reslut";
int thresh = 130;
int max_count = 255;
Mat src, gray_src;
void Harris_Demo(int, void*);

int main(int argc, char** argv)
{
    src = imread("1.jpg");
    imshow("input img", src);

    namedWindow(output_title, CV_WINDOW_AUTOSIZE);
    cvtColor(src, gray_src, COLOR_BGR2GRAY);

    createTrackbar("Threshold:", output_title, &thresh, max_count, Harris_Demo);
    Harris_Demo(0, 0);
    waitKey();
    return 0;
}

void Harris_Demo(int, void*)
{
    Mat dst, norm_dst, normScaleDst;
    dst = Mat::zeros(gray_src.size(), CV_32FC1);

    int blocksize = 2;
    int ksize = 3;
    double k = 0.04;
    cornerHarris(gray_src, dst, blocksize, ksize, k, BORDER_DEFAULT);
    //按照最大最小值进行归一化
    normalize(dst, norm_dst, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
    convertScaleAbs(norm_dst, normScaleDst);

    Mat resultImg = src.clone();
    for (int row=0;row<resultImg.rows;++row)
    {
        uchar* currentRow = normScaleDst.ptr(row);//拿出一整行数据,另一种按像素操作图像的方法
        for (int col = 0; col < resultImg.cols; ++col)
        {
            int value = (int)*currentRow;
            if (value > thresh)
            {
                circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0);
            }
            currentRow++;
        }
    }
    imshow(output_title, resultImg);
}

 

标签:src,特征值,int,检测,角点,Harris,图像
来源: https://blog.51cto.com/u_12870633/2812921