首页 文章

“边缘检测”与“图像轮廓”之间的区别

提问于
浏览
24

请查看以下代码

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

using namespace std;
using namespace cv;

Mat src, grey;
int thresh = 10;

const char* windowName = "Contours";

void detectContours(int,void*);

int main()
{
    src = imread("C:/Users/Public/Pictures/Sample Pictures/Penguins.jpg");

    //Convert to grey scale
    cvtColor(src,grey,CV_BGR2GRAY);

    //Remove the noise
    cv::GaussianBlur(grey,grey,Size(3,3),0);

    //Create the window
    namedWindow(windowName);

    //Display the original image
    namedWindow("Original");
    imshow("Original",src);

    //Create the trackbar
    cv::createTrackbar("Thresholding",windowName,&thresh,255,detectContours);

    detectContours(0,0);
    waitKey(0);
    return 0;

}

void detectContours(int,void*)
{
    Mat canny_output,drawing;

    vector<vector<Point>> contours;
    vector<Vec4i>heirachy;

    //Detect edges using canny
    cv::Canny(grey,canny_output,thresh,2*thresh);

    namedWindow("Canny");
    imshow("Canny",canny_output);

    //Find contours
    cv::findContours(canny_output,contours,heirachy,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE,Point(0,0));

    //Setup the output into black
    drawing = Mat::zeros(canny_output.size(),CV_8UC3);



    //Draw contours
    for(int i=0;i<contours.size();i++)
    {
        cv::drawContours(drawing,contours,i,Scalar(255,255,255),1,8,heirachy,0,Point());
    }

    imshow(windowName,drawing);

}

从理论上讲, Contours 意味着检测曲线 . Edge detection 表示检测边缘 . 在上面的代码中,我使用 Canny 进行了边缘检测,并通过 findContours() 进行了曲线检测 . 以下是生成的图像

Canny Image

enter image description here

Contours Image

enter image description here

好的,现在,正如你所看到的,没有区别!那么,这两者之间的实际差异是什么?在OpenCV教程中,只给出了代码 . 我找到了关于什么是 Contours 的解释,但它没有解决这个问题 .

请帮忙!

4 回答

  • 43

    边缘被计算为在梯度方向上的图像梯度的极值的点 . 如果有帮助,您可以将它们视为一维函数中的最小和最大点 . 关键是,边缘像素是局部概念:它们只是指出相邻像素之间的显着差异 .

    轮廓通常从边缘获得,但它们旨在成为对象轮廓 . 因此,它们需要是闭合曲线 . 您可以将它们视为边界(一些图像处理算法和图书馆会像这样称呼它们) . 从边缘获取它们时,需要连接边缘以获得闭合轮廓 .

  • 2

    查找边和计数之间的主要区别在于,如果运行查找边,则输出为新图像 . 在这个新的(边缘图像)图像中,您将突出显示边缘 . 有许多用于检测边缘的算法look at wiki see also .

    例如,Sobel算子给出了平滑的“模糊”结果 . 在您的特定情况下,问题在于您正在使用Canny边缘检测器 . 这个比其他探测器更进一步 . 它实际上运行了进一步的边缘细化步骤 . Canny探测器的输出因此是二进制图像,具有1px宽线代替边缘 .

    另一方面, Contours 算法处理任意二进制图像 . 所以,如果你把黑色背景上的白色填充正方形 . 运行 Contours 算法后,您将获得白色空方块,只有边框 .

    轮廓检测的其他额外好处是,它实际上返回了一组点!这很好,因为你可以进一步使用这些点进行一些处理 .

    在您的特定情况下,两个图像匹配只是巧合 . 它不是规则,在你的情况下,这是因为Canny算法的独特属性 .

  • 3

    轮廓实际上可以比“仅”检测边缘更多 . 该算法确实找到了图像的边缘,但也将它们放在层次结构中 . 这意味着您可以请求在图像中检测到的对象的外边框 . 如果你只检查边缘,这样的事情就不会(直接)成为可能 .

    从文档中可以看出,轮廓主要用于对象识别,其中canny边缘检测器是更“全局”的操作 . 如果轮廓算法使用某种canny边缘检测,我不会感到惊讶 .

  • 6

    轮廓的概念用作处理边缘数据的工具 . 并非所有边缘都相同 . 但在许多情况下,例如具有单峰颜色分布的对象(即一种颜色),边缘是实际轮廓(轮廓,形状) .

    • 不仅检测曲线,还检测边缘图上连接的任何内容 . (连通成分分析)[1]

    • 对于具有单峰颜色分布的对象很有用(使用简单的阈值很容易找到前景蒙版) . 您的样本图片不合适 .

    [1]边界数字化二值图像的拓扑结构分析Satoshi Suzuki,1985 .

相关问题