从轮廓中提取最外层轮廓
Posted
技术标签:
【中文标题】从轮廓中提取最外层轮廓【英文标题】:Outermost contour extraction from silhouette 【发布时间】:2016-08-01 11:51:04 【问题描述】:我需要检索几个轮廓的最外层轮廓,可能以顺时针或逆时针顺序存储轮廓坐标。根据我的阅读,这种结果可以通过使用 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());
有没有办法避免分割和去除孔的轮廓?
【问题讨论】:
您能否只发布您想要从中获取轮廓的图像,而不是轮廓结果的额外图像。 当然!这些是其中一些First sample pic (Bed)Second sample pic (Cat) 您已经获得了良好的阈值图像(孔中的第二张图像和锯齿状边缘)。现在只需从所有轮廓中找到最大的轮廓并绘制它。您只会得到一个您想要的外侧轮廓。跨度> @Sagar Patel 在两张图片中,最终段的不同颜色代表从 findContours 派生的所有不同段。因此,特别是如果您考虑 Cat 示例,最大的轮廓(骨形项圈)并不总是与外部轮廓一致:( 为什么要用canny edge?只需将图像 255 分割为属于对象的区域,否则为 0,而不是使用 findContours(silhouette,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,Point(0,0)); 【参考方案1】:OpenCV 有一个名为cv2.contourArea()
的函数,它允许您计算输入轮廓的面积。如果您有多个轮廓,请使用此功能查找所有轮廓的区域并删除除最大轮廓之外的所有轮廓(面积最大的轮廓,因为该大轮廓内的轮廓不会有更大的区域)。之后,您将只剩下最大的外部轮廓。
【讨论】:
以上是关于从轮廓中提取最外层轮廓的主要内容,如果未能解决你的问题,请参考以下文章