cv::cornerSubPix()亚像素角点检测

转自https://blog.csdn.net/guduruyu/article/details/69537083
cv::goodFeaturesToTrack()提取到的角点只能达到像素级别,在很多情况下并不能满足实际的需求,这时,我们则需要使用cv::cornerSubPix()对检测到的角点作进一步的优化计算,可使角点的精度达到亚像素级别。

具体调用形式如下:
    void cv::cornerSubPix(
        cv::InputArray image, // 输入图像
        cv::InputOutputArray corners, // 角点(既作为输入也作为输出)
        cv::Size winSize, // 区域大小为 NXN; N=(winSize*2+1)
        cv::Size zeroZone, // 类似于winSize,但是总具有较小的范围,Size(-1,-1)表示忽略
        cv::TermCriteria criteria // 停止优化的标准
    );

第一个参数是输入图像,和cv::goodFeaturesToTrack()中的输入图像是同一个图像。
第二个参数是检测到的角点,即是输入也是输出。

第三个参数是计算亚像素角点时考虑的区域的大小,大小为NXN; N=(winSize*2+1)。

第四个参数作用类似于winSize,但是总是具有较小的范围,通常忽略(即Size(-1, -1))。

第五个参数用于表示计算亚像素时停止迭代的标准,可选的值有cv::TermCriteria::MAX_ITER 、cv::TermCriteria::EPS(可以是两者其一,或两者均选),前者表示迭代次数达到了最大次数时停止,后者表示角点位置变化的最小值已经达到最小时停止迭代。二者均使用cv::TermCriteria()构造函数进行指定。

下面就通过一个示例看看cv::cornerSubPix()亚像素角点检测的具体效果。


    cv::Mat image_color = cv::imread("image.jpg", cv::IMREAD_COLOR);
 
    //用于绘制亚像素角点
    cv::Mat image_copy = image_color.clone();
    //使用灰度图像进行角点检测
    cv::Mat image_gray;
    cv::cvtColor(image_color, image_gray, cv::COLOR_BGR2GRAY);
 
    //设置角点检测参数
    std::vector<cv::Point2f> corners;
    int max_corners = 100;
    double quality_level = 0.01;
    double min_distance = 10;
    int block_size = 3;
    bool use_harris = false;
    double k = 0.04;
 
    //角点检测
    cv::goodFeaturesToTrack(image_gray,
        corners,
        max_corners,
        quality_level,
        min_distance,
        cv::Mat(),
        block_size,
        use_harris,
        k);
 
    //将检测到的角点绘制到原图上
    for (int i = 0; i < corners.size(); i++)
    {
        cv::circle(image_color, corners[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);
    }
 
    //指定亚像素计算迭代标注
    cv::TermCriteria criteria = cv::TermCriteria(
                    cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS,
                    40,
                    0.01);
 
    //亚像素检测
    cv::cornerSubPix(image_gray, corners, cv::Size(5, 5), cv::Size(-1, -1), criteria);
 
    //将检测到的亚像素角点绘制到原图上
    for (int i = 0; i < corners.size(); i++)
    {
        cv::circle(image_copy, corners[i], 5, cv::Scalar(0, 255, 0), 2, 8, 0);
    }
 
    cv::imshow("corner", image_color);
    cv::imshow("sub pixel corner", image_copy);
 
    cv::imwrite("corner.jpg", image_color);
    cv::imwrite("corner_sub.jpg", image_copy);
    cv::waitKey(0);
    return;


直接角点检测和亚像素角点检测的结果分别如下,从检测的效果来看,使用亚像素角点检测后角点的精细度确实得到了显著的提升。

猜你喜欢

转载自blog.csdn.net/originalcandy/article/details/84838549
今日推荐