如何在OpenCV中区分实心圆/轮廓和未实心圆/轮廓?

问题描述 投票:2回答:1

我无法区分以下两个轮廓。 cv2.contourArea两者的值相同。在Python中有什么功能可以区分它们吗?

Fig: example circle/contour

python image opencv image-processing computer-vision
1个回答
2
投票

为了区分填充轮廓和未填充轮廓,在使用cv2.findContours查找轮廓时可以使用轮廓层次。具体来说,您可以选择cv2.findContours以有选择地返回包含有关图像拓扑信息的输出向量。有四种可能的模式:

  • contour retrieval mode-仅检索极端的外部轮廓(无层次)
  • cv2.RETR_EXTERNAL-在不建立任何层次关系的情况下检索所有轮廓
  • cv2.RETR_LIST-检索所有轮廓并将它们组织为两级层次结构。在顶层,组件具有外部边界。在第二层,有孔的边界。如果所连接组件的孔内还有其他轮廓,则仍将其放在顶层]
  • cv2.RETR_CCOMP-检索所有轮廓并重建嵌套轮廓的完整层次结构
  • 了解轮廓层次结构

因此,有了此信息,我们可以使用cv2.RETR_TREEcv2.RETR_CCOMP返回层次结构列表。以这张图片为例:

[当我们使用cv2.RETR_TREE参数时,轮廓按层次结构排列,每个对象的最外轮廓在顶部。在层次结构中向下移动,每个新的轮廓级别代表每个对象的下一个最里面的轮廓。在上图中,图像中的轮廓被着色以表示返回轮廓数据的层次结构。最外面的轮廓是红色的,它们在层次结构的顶部。接下来的最里面的轮廓-在这种情况下是骰子点-是绿色的。

我们可以从cv2.RETR_TREE函数调用中通过层次结构数组获取有关轮廓层次结构的信息。假设我们这样调用函数:

cv2.findContours

第三个返回值,保存在此代码的(_, contours, hierarchy) = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 变量中,是三维NumPy数组,具有一行,hierarchy列和“深度”为4。X列对应于该功能找到的轮廓数量。 X参数使函数查找每个对象的内部轮廓和最外面的轮廓。零列对应于第一个轮廓,一列对应第二个轮廓,依此类推。

每个列都有一个四元素整数数组,根据此方案,它表示其他轮廓的索引:

cv2.RETR_TREE

<< next >>索引引用此轮廓的层次结构级别中的下一个轮廓,而previous

索引引用此轮廓的层次结构级别中的上一个轮廓。 first child索引是指包含在该轮廓内部的第一个轮廓。 parent索引是指包含该轮廓的轮廓。在所有情况下,值[next, previous, first child, parent] 均表示没有<,<>,第一个孩子轮廓。对于更具体的示例,下面是一些-1值示例。值在方括号中,轮廓索引在每个条目之前。如果您打印出层次结构数组,您将获得类似以下内容的信息hierarchy第一个轮廓的输入为0: [ 6 -1 1 -1] 18: [19 -1 -1 17] 1: [ 2 -1 -1 0] 19: [20 18 -1 17] 2: [ 3 1 -1 0] 20: [21 19 -1 17] 3: [ 4 2 -1 0] 21: [22 20 -1 17] 4: [ 5 3 -1 0] 22: [-1 21 -1 17] 5: [-1 4 -1 0] 23: [27 17 24 -1] 6: [11 0 7 -1] 24: [25 -1 -1 23] 7: [ 8 -1 -1 6] 25: [26 24 -1 23] 8: [ 9 7 -1 6] 26: [-1 25 -1 23] 9: [10 8 -1 6] 27: [32 23 28 -1] 10: [-1 9 -1 6] 28: [29 -1 -1 27] 11: [17 6 12 -1] 29: [30 28 -1 27] 12: [15 -1 13 11] 30: [31 29 -1 27] 13: [14 -1 -1 12] 31: [-1 30 -1 27] 14: [-1 13 -1 12] 32: [-1 27 33 -1] 15: [16 12 -1 11] 33: [34 -1 -1 32] 16: [-1 15 -1 11] 34: [35 33 -1 32] 17: [23 11 18 -1] 35: [-1 34 -1 32] 。这代表最外面的轮廓中的第一个;请注意,轮廓没有特定的顺序,例如默认情况下它们不会从左到右存储。该条目告诉我们,下一个骰子轮廓是索引为6的轮廓,列表中没有先前的轮廓,该轮廓内的第一个轮廓的索引为1,并且该轮廓没有父级(不包含任何轮廓这个)。我们可以将[6, -1, 1, -1]数组中的信息可视化为七棵树,图像中每个骰子都一棵。hierarchy
七个最外面的轮廓是所有没有父级的轮廓,即,在其enter image description here条目的第四字段中值为-1的轮廓。 “根”之一下方的每个子节点代表最外轮廓内部的轮廓。注意在图中轮廓13和14如何在轮廓12下方。这两个轮廓代表最里面的轮廓,可能是噪点或某一点的涂料丢失。一旦了解了轮廓是如何排列到层次结构中的,就可以执行更复杂的任务,例如计算形状中轮廓的数量以及图像中对象的数量。 

回到您的问题,我们可以使用层次结构来区分内部轮廓和外部轮廓,以确定轮廓是已填充还是未填充。我们可以将填充轮廓定义为没有子轮廓,而将未填充轮廓定义为至少一个子轮廓。因此,使用此输入图像的屏幕截图(已删除框):

hierarchy


结果

enter image description here

代码

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.