zoukankan      html  css  js  c++  java
  • 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);
    }

  • 相关阅读:
    不能以根用户身份运行 Google Chrome 浏览器
    Ubuntu 10.04 10.10 11.04 9.10 9.04 中文字体美化——安装雅黑字体
    笔记一:文本属性
    ubuntu下使用 android adb命令
    css常用技巧
    PHP max_execution_time 超时
    PHP判断文件夹是否存在和创建文件夹的方法
    javascript之HTML(select option)详解
    查询HTML标签select中options的值并定位其位置
    PHP网页进度条
  • 原文地址:https://www.cnblogs.com/wangtianning1223/p/13499660.html
Copyright © 2011-2022 走看看