OpenCV之图像特征提取与检测(三) Harris角点检测

根据矩阵M的特征值,对于图像上的每个像素点来说, 边缘  平坦区域  角点 各有不同的特征值
    每个像素点不是边缘就是平坦区域或角点

这里写图片描述

这里写图片描述

void cornerHarris ( // harris角点检测
    InputArray src, // 彩色图与灰度图都可以,最好是灰度图
    OutputArray dst, // 输出图像,计算出来的值可能正负,可能有小数,所以输入图像深度最好为 CV_32F,输出图形深度与输入一致
    int blockSize, // -blockSize – 计算 λ1 λ2 时候的矩阵大小   2
    int ksize, // -Ksize 窗口大小
    double k, // -K表示计算角度响应时候的参数大小 默认在0.04~0.06   
    int borderType = BORDER_DEFAULT 
);

代码

    #include "../common/common.hpp"

    static Mat src, gray;
    static const char title[] = "harrisCorner";
    static int thresh_v = 130;
    static int thresh_max = 255;

    static void m_harris(int, void*);

    void main(int argc, char** argv)
    {
        src = imread(getCVImagesPath("images/home.jpg"), IMREAD_COLOR);
        imshow("src2-3", src);

        cvtColor(src, gray, CV_BGR2GRAY);
        namedWindow(title, CV_WINDOW_AUTOSIZE);
        createTrackbar("thresh:", title, &thresh_v, thresh_max, m_harris);
        m_harris(0, 0);

        waitKey(0);
    }

    void m_harris(int, void*)
    {
        Mat dst, norm, scaleDst;
        dst = Mat::zeros(gray.size(), CV_32FC1);

        int blockSize = 2;
        int ksize = 3;
        double k = 0.04;
        cornerHarris(gray, dst, blockSize, ksize, k, BORDER_DEFAULT); // 角点检测
        printf("dst depth=%d, type=%d\n", dst.depth(), dst.type()); // dst depth=5, type=5  CV_32F
        for (int row = 0; row < dst.rows; row++)
        {
            for (int col = 0; col < dst.cols; col++)
            {
                printf("%f, ", dst.at<float>(row, col)); // 值很微小,小数点后有几个0
            }
        }
        normalize(dst, norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat()); // 检测出的元素值范围不确定,而且有正有负,归一化一下
        printf("norm depth=%d, type=%d\n", norm.depth(), norm.type()); // norm depth=5, type=5  CV_32F
        convertScaleAbs(norm, scaleDst, 1, 0); // 将元素值取绝对值,且将输出图像深度变为 CV_8U    公式:dst(I)=abs(src(I)*scale + shift)
        printf("scaleDst depth=%d, type=%d\n", scaleDst.depth(), scaleDst.type()); // scaleDst depth=0, type=0  CV_8U

        Mat retImg = src.clone(); // 深拷贝
        for (int row = 0; row < retImg.rows; row++)
        {
            uchar * curRow = scaleDst.ptr(row);
            for (int col = 0; col < retImg.cols; col++)
            {
                int value = (int)*curRow;
                if (value > thresh_v) // 过滤,角点响应值 大于 阈值才显示
                {
                    circle(retImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0);
                }
                curRow++; // scaleDst的深度是CV_8U , 所以用 ++ 指针步长没有问题
            }
        }

        imshow(title, retImg);
    }

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/81261258