请查看以下代码
#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
轮廓图像
好的,现在,正如你所看到的,没有区别!那么,这两者之间的实际差异是什么?在OpenCV教程中,只给出了代码。我找到了关于什么是Contours
的解释,但它没有解决这个问题。
请帮忙!
答案 0 :(得分:46)
边缘被计算为在渐变方向上为图像渐变的极值的点。 如果有帮助,您可以将它们视为一维函数中的最小和最大点。 关键是,边缘像素是一个局部概念:它们只是指出了相邻像素之间的显着差异。
轮廓通常从边缘获得,但它们的目标是对象轮廓。 因此,它们需要是闭合曲线。 您可以将它们视为边界(某些图像处理算法和图书馆会像这样称呼它们)。 当从边缘获得它们时,您需要连接边缘以获得闭合轮廓。
答案 1 :(得分:6)
查找边和计数之间的主要区别在于,如果运行查找边,则输出为新图像。在这个新的(边缘图像)图像中,您将突出显示边缘。有许多算法可用于检测边look at wiki see also。
例如,Sobel算子可以提供平滑的&#34;模糊&#34;结果。在您的特定情况下,问题在于您正在使用Canny边缘检测器。这个比其他探测器更进一步。它实际上运行了进一步的边缘细化步骤。 Canny探测器的输出因此是二进制图像,用1 px宽线代替边缘。
另一方面,Contours
算法处理任意二进制图像。所以,如果你把黑色背景上的白色填充正方形。运行Contours
算法后,您将获得白色空方块,只有边框。
轮廓检测的其他额外好处是,它实际上返回了一组点!这太棒了,因为你可以进一步使用这些点进行一些处理。
在您的特定情况下,两个图像匹配只是巧合。它不是规则,在你的情况下,它是因为Canny算法的独特属性。
答案 2 :(得分:4)
轮廓实际上可以比“仅”检测边缘更多。该算法确实找到了图像的边缘,但也将它们放在层次结构中。这意味着您可以请求在图像中检测到的对象的外边框。如果你只检查边缘,这样的事情就不会(直接)。
正如在文档中可以看到的,轮廓主要用于对象识别,其中精确边缘检测器是更“全局”的操作。如果轮廓算法使用某种canny边缘检测,我不会感到惊讶。
答案 3 :(得分:2)
轮廓的概念用作处理边缘数据的工具。并非所有边缘都相同。但在许多情况下,例如具有单峰颜色分布的物体(即一种颜色),边缘是实际的轮廓(轮廓,形状)。
[1]数字二进制的拓扑结构分析 边境图像以下是Satoshi Suzuki,1985年。