gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 11:51:54 29 4
gpt4 key购买 nike

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

Fig: example circle/contour

最佳答案

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

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

  • 了解轮廓层次结构

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

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

    我们可以通过 cv2.findContours函数调用中的层次结构数组获取有关轮廓层次结构的信息。假设我们这样调用函数:
    (_, contours, hierarchy) = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

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

    根据此方案,每一列都有一个四元素整数数组,表示其他轮廓的索引:
    [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, 1, -1]。这代表最外面的轮廓中的第一个;请注意,轮廓没有特定的顺序,例如默认情况下它们不会从左到右存储。该条目告诉我们,下一个骰子轮廓是索引为6的轮廓,列表中没有先前的轮廓,该轮廓内的第一个轮廓的索引为1,并且该轮廓没有父级(不包含轮廓这个)。我们可以将 hierarchy数组中的信息可视化为七棵树,图像中每个骰子一棵。

    enter image description here

    最外面的七个轮廓是所有没有父级的轮廓,即在其 -1条目的第四字段中具有 hierarchy值的轮廓。 “根”之一下方的每个子节点代表最外轮廓内部的轮廓。注意在图中轮廓13和14如何在轮廓12下方。这两个轮廓代表最里面的轮廓,可能是噪点或某一点的涂料丢失。一旦了解了轮廓是如何排列到层次结构中的,就可以执行更复杂的任务,例如计算形状中轮廓的数量以及图像中对象的数量。

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

    enter image description here

    结果

    enter image description here


    import cv2
    import numpy as np

    # Load image, grayscale, Otsu's threshold
    image = cv2.imread('1.png')
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

    # Filter using contour hierarchy
    cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    hierarchy = hierarchy[0]
    for component in zip(cnts, hierarchy):
    currentContour = component[0]
    currentHierarchy = component[1]
    x,y,w,h = cv2.boundingRect(currentContour)
    # Has inner contours which means it is unfilled
    if currentHierarchy[3] > 0:
    cv2.putText(image, 'Unfilled', (x,y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (36,255,12), 2)
    # No child which means it is filled
    elif currentHierarchy[2] == -1:
    cv2.putText(image, 'Filled', (x,y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (36,255,12), 2)

    cv2.imshow('image', image)
    cv2.waitKey()

    关于python - 如何在OpenCV中区分实心圆/轮廓和未实心圆/轮廓?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60095520/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com