Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 区别于;“边缘检测”;及;图像轮廓“;_C++_Image_Opencv_Image Processing_Artificial Intelligence - Fatal编程技术网

C++ 区别于;“边缘检测”;及;图像轮廓“;

C++ 区别于;“边缘检测”;及;图像轮廓“;,c++,image,opencv,image-processing,artificial-intelligence,C++,Image,Opencv,Image Processing,Artificial Intelligence,我正在编写以下代码: #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 ch

我正在编写以下代码:

#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);

}
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间cv;
Mat src,灰色;
int thresh=10;
const char*windowName=“等高线”;
空洞探测孔(int,void*);
int main()
{
src=imread(“C:/Users/Public/Pictures/Sample Pictures/Penguins.jpg”);
//转换为灰度
CVT颜色(src、灰色、CV_BGr2灰色);
//消除噪音
cv::高斯蓝(灰色,灰色,大小(3,3),0);
//创建窗口
namedWindow(windowName);
//显示原始图像
姓名(以下简称“原件”);
imshow(“原件”,src);
//创建轨迹栏
cv::createTrackbar(“阈值化”,windowName,&thresh,255,detectContours);
检测孔(0,0);
等待键(0);
返回0;
}
无效检测孔(int,void*)
{
Mat canny_输出、绘图;
矢量等值线;
矢量遗传;
//使用canny算法检测边缘
cv::Canny(灰色,Canny_输出,阈值,2*阈值);
namedWindow(“精明”);
imshow(“Canny”,Canny_输出);
//寻找轮廓
cv::findContours(canny_输出、轮廓、继承、cv_RETR_树、cv_链近似、点(0,0));
//将输出设置为黑色
drawing=Mat::zeros(canny_output.size(),CV_8UC3);
//画轮廓

对于(int i=0;i等高线实际上可以做的不仅仅是“仅”检测边缘。该算法确实可以找到图像的边缘,但也可以将它们放在一个层次结构中。这意味着您可以请求在图像中检测到的对象的外部边界。如果只检查边缘,则(直接)不可能做到这一点


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

查找边缘和计数之间的主要区别在于,如果运行查找边缘,输出的是新图像。在这张新(边缘图像)图像中,您将突出显示边缘。有许多用于检测边缘的算法

例如,Sobel运算符给出平滑的“模糊”结果。在您的特定情况下,关键是您使用的是Canny边缘检测器。此检测器比其他检测器更进一步。它实际上运行进一步的边缘细化步骤。因此,Canny检测器的输出是二值图像,用1像素宽的线代替边缘

另一方面,
等高线
算法处理任意二值图像。因此,如果您在黑色背景上放入白色填充正方形。运行
等高线
算法后,您将得到白色空白正方形,只有边框

轮廓检测的另一个额外好处是,它实际上返回一组点!这很好,因为您可以进一步使用这些点进行某些处理

在您的特殊情况下,两幅图像匹配只是巧合。这不是规则,在您的情况下,这是因为Canny算法的独特属性。

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

轮廓通常是从边缘获得的,但它们的目标是对象轮廓。 因此,它们需要是闭合曲线。 你可以把它们看作是边界(一些图像处理算法和图书馆这样称呼它们)。
从边缘获取轮廓时,需要连接边缘以获得闭合轮廓。

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

  • 不仅检测曲线,还检测边缘贴图上连接的任何东西。(连接组件分析)[1]
  • 适用于具有单峰颜色分布的对象(使用简单的阈值很容易找到前景遮罩)。您的示例图像不适用
  • [1] 数字化二进制文件的拓扑结构分析
    Satoshi Suzuki,1985年出版的《按边框排列的图像》。

    我建议在cv::Canny()之前使用cv::GaussianBlur()。这样可以在保留主边缘的同时去除大部分杂乱。因为findContours()用于二值图像,如果它使用Canny边缘检测器,我会非常惊讶。Sobel不是真正的边缘检测器,它只是提供梯度。Canny却找到了最大梯度,即梯度中的峰值。Canny()的OpenCV实现实际上使用了Sobel()在它的前端。非常感谢你的回复。我真的很感激:)那么,等高线总是在它们开始的地方结束?这有区别吗?是的,等高线是闭合的,而边可能是(多边形的)线条。那么,为什么这两个结果几乎相同?或者,这张图像在显示
    边缘
    轮廓
    之间的差异时不好吗?