从 OpenCV Canny 边缘检测器获取角度

Posted

技术标签:

【中文标题】从 OpenCV Canny 边缘检测器获取角度【英文标题】:Get angle from OpenCV Canny edge detector 【发布时间】:2013-10-22 23:22:32 【问题描述】:

我想使用 OpenCV 的 Canny 边缘检测器,如 this question 中所述。例如:

cv::Canny(image,contours,10,350); 

但是,我不仅希望得到最终的阈值图像,还希望得到每个像素处检测到的边缘角度。这在 OpenCV 中可行吗?

【问题讨论】:

【参考方案1】:

canny 不会直接给你这个。 但是,您可以通过 canny() 内部使用的 Sobel 变换计算角度。

伪代码:

    cv::Canny(image,contours,10,350);
    cv::Sobel(image, dx, CV_64F, 1, 0, 3, 1, 0, cv::BORDER_REPLICATE);
    cv::Sobel(image, dy, CV_64F, 0, 1, 3, 1, 0, cv::BORDER_REPLICATE);

    cv::Mat angle(image.size(), CV_64F)

    foreach (i,j) such that contours[i, j] > 0
    
        angle[i, j] = atan2(dy[i,j], dx[i , j])
    

【讨论】:

Canny 在内部调用 Sobel,因此该解决方案可能效率低下。如果您从 opencv 获取代码,您可能会编写自己的 Canny 版本,该版本接受输入预先计算的 sobel 图像【参考方案2】:

除了使用 for 循环,您还可以将 dxdy 渐变提供给返回角度方向的灰度图像的 phase 函数,然后将其传递给 applyColorMap 函数,然后用边缘对其进行遮罩,因此背景是黑色的。

这是工作流程:

    获取角度

    Mat angles;
    phase(dx, dy, angles, true);
    

    true 参数表示角度以度数返回。

    将角度范围更改为 0-255,以便您可以转换为 CV_8U 而不会丢失数据

    angles = angles / 360 * 255;
    

    请注意,angles 仍然是 CV_64F 类型,因为它来自 Sobel 函数

    转换为CV_8U

    angles.convertTo(angles, CV_8U);
    

    应用您选择的颜色图

    applyColorMap(angles, angles, COLORMAP_HSV);
    

    在这种情况下,我选择 HSV 颜色图。有关更多信息,请参阅:https://www.learnopencv.com/applycolormap-for-pseudocoloring-in-opencv-c-python/

    应用边缘蒙版,使背景为黑色

    Mat colored;
    angles.copyTo(colored, contours);
    

    最后显示图片:D

    imshow("Colored angles", colored);
    

如果您的来源是视频或网络摄像头,在应用边缘遮罩之前,您还必须清除 colored 图像,以防止聚合:

colored.release();
angles.copyTo(colored, contours);

完整代码在这里:

Mat angles, colored;

phase(dx, dy, angles, true);
angles = angles / 360 * 255;
angles.convertTo(angles, CV_8U);
applyColorMap(angles, angles, COLORMAP_HSV);
colored.release();
angles.copyTo(colored, contours);
imshow("Colored angles", colored);

【讨论】:

我是否正确地说在这里只能覆盖 180 度的范围,因为从 180-359 的范围映射到 0-179? 不,这应该适用于 0-359 度的所有范围。颜色映射函数映射从 0 到 255 范围内的每个值,这就是我们将度数范围从 0-360 缩小到 0-255 的原因。所以现在 360deg 的值是 255,180deg 是 128 等等。

以上是关于从 OpenCV Canny 边缘检测器获取角度的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV | OpenCV实战从入门到精通系列三 --canny边缘检测

OpenCV:Canny 边缘检测器获取 minEnclosureCircle

OpenCV 边缘检测

边缘检测后获取边缘坐标(Canny)

Canny边缘检测算法(python 实现)

OpenCV入门指南第三篇Canny边缘检测