计算机视觉攻略 笔记5 (检测图像中的角点)

检测图像中的角点

参考博客

文献1
文献2

代码程序

#include <iostream>
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

class HarrisDetector{
private:
    // 32位浮点数型的角点强度图像
    cv::Mat cornerStrength;
    // 32位浮点数型的阈值化角点图像
    cv::Mat cornerTh;
    // 局部最大值图像(内部)
    cv::Mat localMax;
    // 平滑导数的领域尺寸
    int neighborhood;
    // 梯度计算的口径
    int aperture;
    // Harris 参数
    double k;
    // 阈值计算的最大强度
    double maxStrength;
    // 计算得到的阈值(内部)
    double threshold;
    // 非最大抑制的领域尺寸
    int nonMaxSize;
    // 非最大值抑制的内核
    cv::Mat kernel;

public:
    HarrisDetector():neighborhood(3),aperture(3),
                    k(0.01), maxStrength(0.0),
                    threshold(0.01), nonMaxSize(3){
    }
    // 创建用于非最大值抑制的内核
    void setLocalMaxWindowsize(int nonMaxSize){
        this->nonMaxSize = nonMaxSize;
    };
    // 检测Harris角点需要两个步骤。首先是计算每个像素的Harris值
    void detect(const cv::Mat& image){
        // 计算Harris
        cv::cornerHarris(image, cornerStrength,
                         neighborhood,
                         aperture,
                         k);
        // 计算内部阈值
        cv::minMaxLoc(cornerStrength,0,&maxStrength);
        // 检测局部最大值
        cv::Mat dilated;      // 临时图像
        cv::dilate(cornerStrength,dilated, cv::Mat());
        cv::compare(cornerStrength,dilated,localMax,cv::CMP_EQ);
    }
    // 然后,用指定的阈值获得特征点。因为Harris值的可选范围取决于选择的参数,所以阈值被作为质量等级,用最大Harris值的一个比例表示
    // 用Harris值得到角点分布图
    cv::Mat getCornerMap(double qualityLevel){
        cv::Mat cornerMap;
        // 对角点强度阈值化
        threshold = qualityLevel * maxStrength;
        cv::threshold(cornerStrength, cornerTh, threshold,255, cv::THRESH_BINARY);
        // 转换成8位图像
        cornerTh.convertTo(cornerMap, CV_8U);
        // 非最大值抑制
        cv::bitwise_and(cornerMap,localMax,cornerMap);
        return cornerMap;
    }
    // 用角点分布得到特征点
    void getCorners(std::vector<cv::Point> &points,
                    const cv::Mat& cornerMap){
        // 迭代遍历像素,得到所有特征点
        for (int y = 0; y < cornerMap.rows; y++){
            const uchar* rowPty = cornerMap.ptr<uchar>(y);
            for (int x = 0; x < cornerMap.cols; x++){
                // 如果它是一个特征点
                if (rowPty[x]){
                    points.push_back(cv::Point(x, y));
                }
            }
        }
    }
    // 用Harris值得到特征点
    void getCorners(std::vector<cv::Point> &points, double qualityLevel){
        // 获得角点分布图
        cv::Mat cornerMap = getCornerMap(qualityLevel);
        // 获得角点
        getCorners(points, cornerMap);
    }

    // 这个类通过增加非最大值抑制步骤,也改进了Harris角点的检测过程
    // 现在使用cv::circle函数画出检测到的特征点
    // 在特征点的位置画圆形
    void drawOnImage(cv::Mat &image,
                     const std::vector<cv::Point> &points,
                     cv::Scalar color = cv::Scalar(255, 255, 255),
                     int radius = 3, int thickness = 1){
        std::vector<cv::Point>::const_iterator it = points.begin();
        // 针对所有角点
        while(it != points.end()){
            // 在每个角点位置画一个园
            cv::circle(image, *it, radius, color, thickness);
            ++it;
        }
    }
};

int main(int argc, char** argv) {
    if(argc != 2)
    {
        std::cerr << "don't get the image" << std::endl;
        return -1;
    }
    cv::Mat image = cv::imread(argv[1],cv::IMREAD_GRAYSCALE);
    if(image.empty())
    {
        std::cout << "don't get the data of image" << std::endl;
        return -1;
    }
    cv::imshow("Original", image);
//     检测Harris角点
//    cv::Mat cornerStrength;
//    cv::cornerHarris(image,                 //input image   单通道8位
//                     cornerStrength,        // output image
//                     3,            // 邻域尺寸
//                     3,                // 口径尺寸
//                     0.01);             // Harris 参数
//    // 对角点强度阈值化
//    cv::Mat harrisCorners;
//    double threshold = 0.0001;
//    cv::threshold(cornerStrength, harrisCorners,
//                  threshold, 255, cv::THRESH_BINARY_INV);
//    cv::imshow("Harris", harrisCorners);
//    cv::waitKey(0);
//    return 0;
    // 创建Harris检测器实力
    HarrisDetector harris;
    // 计算Harris值
    harris.detect(image);
    // 检测Harris角点
    std::vector<cv::Point> pts;
    harris.getCorners(pts, 0.02);
    // 画出Harris角点
    harris.drawOnImage(image, pts);
    cv::imshow("Corners", image);
    cv::waitKey(0);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值