如何使用python opencv提取内部轮廓(孔)?

mar*_*rco 1 python opencv

有没有一种简单直接的方法从opencv 3.1 python中提取图像的内部轮廓(孔)?

我知道我可以用"区域"作为条件.但是,如果我更改图像分辨率,则"区域"不一样.

例如,使用此图片: 在此输入图像描述 如何提取内部孔?

_, contours, hier_ = cv2.findContours(img,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
areas = [cv2.contourArea(c) for c in millCnts]
max_area = np.max(areas)
Mask = np.ones(img.shape[:2], dtype="uint8") * 255

   # I can do something like this (currently not working, just to show an example)
for c in contours:
    if(( cv2.contourArea(c) > 8) and (cv2.contourArea(c)< 100000)):
        cv2.drawContours(Mask ,[c],-1,0,1)
Run Code Online (Sandbox Code Playgroud)

api*_*i55 5

正如我在评论中解释的那样,您必须检查层次结构返回变量.找到轮廓后,您将获得轮廓(点列表列表)和层次结构(列表列表).

文档是非常清楚在此:

hierarchy - 可选输出向量,包含有关图像拓扑的信息.它具有与轮廓数量一样多的元素.对于每个第i个轮廓的轮廓[I],元素hierarchy[i][0], hiearchy[i][1],hiearchy[i][2],和hiearchy[i][3]在相同的层级,所述第一子轮廓和父轮廓分别设定为在下一个和先前轮廓的轮廓0为基础的指数.如果轮廓i没有下一个,前一个,父级或嵌套轮廓,则层次结构[i]的相应元素将为负数.

所以,这意味着每个countour[i]你应该得到一个hierarchy[i]包含4个变量的List:

  • hierarchy[i][0]:同一级别的下一个轮廓的索引
  • hierarchy[i][1]:同一级别的先前轮廓的索引
  • hierarchy[i][2]:第一个孩子的索引
  • hierarchy[i][3]:父级的索引

所以说,在你的情况下,应该有一个没有父母,你可以通过检查hierarchy[i][3]它是否为负来检查哪一个.

它应该是(未经测试的代码):

holes = [contours[i] for i in range(len(contours)) if hierarchy[i][3] >= 0]
Run Code Online (Sandbox Code Playgroud)

*更新:*

总结一下我们在聊天中讨论的内容,

  • 图像太大,轮廓有小孔:用膨胀解决并用75号内核腐蚀
  • 由于OpenCV期望扩张为黑色背景,因此需要反转图像
  • 该算法给出了两个大的轮廓,一个在外面(如预期的)和一个内部(几乎与外部轮廓相同),这可能是由于图像具有一些外部(和闭合)凸起.这是通过删除没有父母及其第一个孩子的轮廓来解决的.