• opencv —— Harris 角点检测


    Harris 角点检测原理

    人眼对角点的识别通常是在一个局部区域(小窗口)内完成的。主要有三种情况:

    1. 小窗口在各个方向上移动,窗口内区域的灰度均发生较大的变化,那么就认为在窗口内遇到了角点。
    2. 小窗口在各个方向上移动,窗口内区域的灰度没有发生变化,那么就认为窗口内就不存在角点。
    3. 小窗口在各个方向上移动,仅在某一个方向移动时,窗口内区域的灰度才会发生较大的变化,那么就认为窗口内的图像可能是一条直线。如下图:

    Harris 角点检测是一种直接基于灰度图像的角点提取算法。对于每个像素(x,y)在 blockSize×blockSize 邻域内,计算 2×2 梯度的协方差矩阵M(x,y),接着计算如下式子

    就可以找出输出图中的局部最大值,即找出了角点。

    实现 Harris 角点检测:

    1.计算图像 I(x,y) 在 x 和 y 两个方向的梯度 Ix Iy

    2.计算图像两个方向梯度的乘积。   

    3.计算中心点为 (x,y) 的窗口 w 对应的协方差矩阵 M。

     

            

        其中 w(x,y) 是窗口函数,最简单情形就是窗口 w 内的所有像素所对应的权重系数均为1,但有时候,我们会将 w(x,y) 函数设置为以窗口 w 中心为原点的二元高斯函数。

        如果窗口 w 中心点是角点时,移动前与移动后,该点在灰度变化贡献最大;而离窗口 w 中心(角点)较远的点,这些点的灰度变化几近平缓,这些点的权重系数,可以设定小值,以示该点对灰度变化贡献较小,那么我们自然而然想到使用二元高斯函数来表示窗口函数。

    4.计算每个像素点的 Harris 响应值 R。

    • M 的对角线元素之和称为 M 的迹,记为 trace(M) , 即 tr(A) = m11 + m22 + ... + mnn;
    • 所有取自不同行不同列的 n 个元素的乘积之和称为 M 的行列式,记为 det(M) 。

    5.过滤大于某一阈值 t 的 R 值。

     

    void cornerHarris(InputArray src, OutputArray dst, int blockSize, int ksize, double k, int borderType = BORDER_DEFAULT);

    •  src,输入图像,即源图像。填 Mat 类的对象即可,且需为单通道 8 位或浮点型图像。
    • dst,这个参数存放 Harris 角点检测的输出结果,和源图像有一样的尺寸和类型。
    • blockSize,窗口大小。
    • ksize,Sobel 算子的孔径大小,用于计算 x,y 方向的导数。
    • k,R 计算公式中的 k 值,经验常数,一般取 k = 0.04~0.06。
    • borderType,有默认值,详解见 https://www.cnblogs.com/bjxqmy/p/12306276.html

     

    代码示例:

    #include<opencv.hpp>
    #include<iostream>
    #include<string>
    using namespace std;
    using namespace cv;
    Mat src, cornerImg;
    int thre = 180;
    void ChangeThresh(int, void*) {
        Mat dst = src.clone();
        for (int i = 0; i < cornerImg.rows; i++) {
            for (int j = 0; j < cornerImg.cols; j++) {
                //注意是 (j,i)
                if (cornerImg.at<uchar>(i, j) > thre) {
                    circle(dst, Point(j, i), 3, Scalar(0, 0, 255), -1);
                }
            }
        }
        imshow("dst", dst);
    }
    int main() {
        src = imread("C:/Users/齐明洋/Desktop/示例图片/8.jpg");
        imshow("src", src);
    
        //转换为灰度图像
        Mat grayImg;
        cvtColor(src, grayImg, COLOR_BGR2GRAY);
    
        //计算角点
        cornerHarris(grayImg, cornerImg, 2, 3, 0.04);
        //归一化到[0,255],详解 https://www.cnblogs.com/bjxqmy/p/12292421.html
        normalize(cornerImg, cornerImg, 0, 255, NORM_MINMAX, CV_32FC1);
        //因为可能为负值,统一变换成 8 位无符号整型
        convertScaleAbs(cornerImg, cornerImg);
        imshow("cornerImg", cornerImg);
    
        namedWindow("dst");
        createTrackbar("thresh", "dst", &thre, 255, ChangeThresh);
        ChangeThresh(0, 0);
    
    
        waitKey(0);
    }

    效果演示:

     

    借鉴博客:https://www.cnblogs.com/zyly/p/9508131.html

    https://www.cnblogs.com/Jack-Elvis/p/11640931.html

    https://baike.baidu.com/item/TR/3776614?fr=aladdin

    https://baike.baidu.com/item/n%E9%98%B6%E8%A1%8C%E5%88%97%E5%BC%8F/3705756

     

  • 相关阅读:
    UUID设主键让后续的开发工作更加方便
    S2SH整合FreeMarker
    轮询技术
    使DreamWeaver支持tml扩展名
    Editplus 的Record功能
    从注册表删除sqlserver注册
    ie8的新功能
    使用editplus 与 dreamweaver 协作开发
    安装SQL SERVER时提示"以前的某个程序安装已在安装计算机上创建挂起的文件操作 "解决方法
    选中文件夹设定为IIS站点主目录的批处理bat
  • 原文地址:https://www.cnblogs.com/bjxqmy/p/12456331.html
Copyright © 2020-2023  润新知