2016-08-01 274 views
2

我需要检索多个轮廓的最外轮廓,可能以顺时针或逆时针顺序存储轮廓坐标。从我读过的,这种结果可以通过使用OpenCV的Canny + findContours归档。不幸的是,我必须详细说明的大部分轮廓都是锯齿状的边缘或孔,因此“标准程序”无法正常工作。举例来说,如果我的形象是相当简单的,无孔,结果是完全一样的,我希望它(只是最外面的轮廓,并下令坐标): Cup example从轮廓中提取最外轮廓

在有孔的照片时,我得到一个分段的最外面的轮廓(不同的颜色,见附图),它仍然显示最终图像中的内孔。锯齿边缘我得到最坏的结果。显示孔并且轮廓高度分段(Cat)。 Holes and jagged edges

代码:

//add a small padding. Otherwise, in case of images where the border is partially cut out it won't be considered as a "closed" contour 
int topbottom = (int) (0.05*image.rows); 
int rightleft = (int) (0.05*image.cols); 
copyMakeBorder(image, image, topbottom, topbottom, rightleft, rightleft, BORDER_CONSTANT); 

//consider only alpha channel to create a silhouette 
Mat silhouette; 
vector<Mat> ch; 
split(image, ch); 

Canny(ch[3], silhouette, 100, 200); 

vector<vector<Point>> contours; 
vector<Vec4i> hierarchy; 

//find only the external contour 
findContours(silhouette, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 

RNG rng(12345); 
Mat drawing = Mat::zeros(silhouette.size(), CV_8UC3); 
for(int i = 0; i < contours.size(); i++) 
{ 
    Scalar colour = Scalar(rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255)); 
    drawContours(drawing, contours, i, colour, 1, 8, hierarchy, 0, Point()); 
} 

有没有办法避免分割和去除孔的轮廓?

+3

你可以只发布你想要得到轮廓的图像,而不需要额外的轮廓结果图像。 –

+0

当然!这些是其中的一些 [第一样品图片(床)](http://labelmaterial.s3.amazonaws.com/shapes/2KGnQ5RjIoXZXmoXr723dXz.png) [第二样品图片(猫)](http://labelmaterial.s3 .amazonaws.com/shapes/2NXvn0zPaDGXLIoQJ9LuyVT.png) – Izzy88

+0

您已经获得了良好的阈值图像(第2张图像为空洞和锯齿状边缘)。现在只需从所有轮廓中找出最大轮廓并绘制它即可。您只会获得一个外侧轮廓想。 –

回答

0

OpenCV有一个叫cv2.contourArea()的功能,它可以让你计算输入轮廓的面积。如果您有多个轮廓,请使用此功能查找所有轮廓的区域,并删除除最大轮廓以外的所有区域(其中一个轮廓最大,因为大轮廓内的轮廓不会有较大的区域)。之后,您将只剩下最大的外部轮廓。