You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Python的OpenCV中为已排序的轮廓匹配关联的层级结构

解决轮廓层级与排序匹配的问题

嘿,我来帮你搞定这个关联轮廓层级并排序的问题!结合你用的OpenCV 3.4.0.12和Python 3.6.3,我一步步给你讲清楚怎么做:

先补全核心代码(获取完整层级结构)

首先,你的cv2.findContours必须用cv2.RETR_TREE模式,这个模式会保留所有轮廓的完整层级关系,否则拿不到父子轮廓的关联信息。补全后的代码片段:

import copy
import cv2

BLACK_THRESHOLD = 200
THIN_THRESHOLD = 10
ANNOTATION_COLOUR = (0, 0, 255)

img = cv2.imread('input.png')
orig = copy.copy(img)
# 把数字6换成可读性更好的枚举常量
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, thresh=BLACK_THRESHOLD, maxval=255, type=cv2.THRESH_BINARY_INV)[1]

# 关键:用RETR_TREE获取完整层级结构
_, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

理解Hierarchy层级结构

OpenCV返回的hierarchy是一个形状为(1, N, 4)的数组(N是轮廓总数),每个轮廓对应的层级条目是[next, prev, first_child, parent]:

  • next:同一层级下的下一个轮廓索引,-1表示没有
  • prev:同一层级下的上一个轮廓索引,-1表示没有
  • first_child:当前轮廓的第一个子轮廓索引,-1表示没有子轮廓
  • parent:当前轮廓的父轮廓索引,-1表示没有父轮廓(最外层轮廓)

关联轮廓与层级并按嵌套深度排序

我们可以给每个轮廓计算嵌套深度(比如最外层深度为0,它的子轮廓深度为1,以此类推,最内层深度最大),然后按深度排序:

1. 计算轮廓的嵌套深度

写一个小函数来迭代计算每个轮廓的深度:

def get_contour_depth(contour_idx, hierarchy):
    """计算指定索引轮廓的嵌套深度"""
    depth = 0
    parent_idx = hierarchy[0][contour_idx][3]
    # 一直向上找父轮廓,直到没有父轮廓为止
    while parent_idx != -1:
        depth += 1
        parent_idx = hierarchy[0][parent_idx][3]
    return depth

2. 关联轮廓与层级信息

把每个轮廓的深度、索引、轮廓本身、层级数据打包在一起:

contour_info_list = []
for idx, (cnt, hier_entry) in enumerate(zip(contours, hierarchy[0])):
    depth = get_contour_depth(idx, hierarchy)
    # 打包成(深度,轮廓索引,轮廓对象,层级条目)
    contour_info_list.append( (depth, idx, cnt, hier_entry) )

3. 按嵌套深度排序

按深度降序排列,这样最内层(深度最大)的轮廓会排在最前面:

# 按深度从大到小排序
sorted_contours = sorted(contour_info_list, key=lambda x: -x[0])

提取最内层轮廓

如果你的最终目标是提取最内层轮廓,直接筛选深度最大的那些即可:

# 获取最大深度值
max_depth = max(info[0] for info in contour_info_list)
# 筛选所有深度等于最大深度的轮廓(就是最内层)
innermost_contours = [info[2] for info in contour_info_list if info[0] == max_depth]

# 可视化验证:在原图上画出最内层轮廓
for cnt in innermost_contours:
    cv2.drawContours(orig, [cnt], -1, ANNOTATION_COLOUR, 2)
cv2.imwrite('innermost_output.png', orig)

额外说明

  • 如果你只是想找没有子轮廓的轮廓(不一定是最内层,但通常最内层都没有子轮廓),可以直接筛选hier_entry[2] == -1的轮廓,但这种方法可能会误判(比如某些中间层轮廓也没有子轮廓),所以用深度排序更准确。
  • 注意OpenCV 3.x和4.x的findContours返回值不同,你用的3.x版本返回三个值,代码是适配的。

内容的提问来源于stack exchange,提问作者Aadit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:43:22