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

OpenCV的drawContours为何填充内部轮廓?如何避免该问题?

OpenCV的drawContours为何填充内部轮廓?如何避免该问题?

嗨,这个问题我之前也碰到过,核心原因是你没利用好轮廓的层级关系!

你用cv2.RETR_TREE模式获取轮廓时,OpenCV会给外层轮廓和内部的“洞”轮廓标记出父子层级——简单说,洞的轮廓是外层轮廓的子轮廓。但你现在的代码是遍历所有轮廓直接填充,不管谁是谁的子级,结果就是外层和洞都被填上了同一种颜色,看起来洞就被“填满”了。

解决方法很简单,只要借助findContours返回的hier层级数组来区分外层轮廓和洞轮廓就行:

层级数组里每个元素的格式是[next, prev, child, parent],其中第4个值(索引3)代表当前轮廓的父轮廓索引,如果这个值是-1,说明这是最外层的顶层轮廓,没有父级;反之就是内部的洞轮廓。

修改你的代码循环部分如下:

for i, cnt in enumerate(contour):
    # 绘制轮廓线的话,所有轮廓都可以画,不影响
    cv2.drawContours(canvas, [cnt], 0, 255, 2)
    # 判断当前轮廓是否是顶层轮廓(无父级)
    if hier[0][i][3] == -1:
        # 只填充顶层轮廓为白色
        cv2.drawContours(canvas2, [cnt], 0, 255, -1)
    else:
        # 把内部洞轮廓填充为黑色(和画布底色一致,保留洞的形状)
        cv2.drawContours(canvas2, [cnt], 0, 0, -1)

这样修改后,canvas2里的顶层轮廓会被填充成白色,而内部的洞会被填充成黑色(和初始画布颜色一致),就能完美保留洞的形状,不会再出现被填满的情况啦。

另外补充一下,如果你不想处理层级,也可以改用cv2.RETR_EXTERNAL模式获取轮廓,这个模式只会返回最外层的顶层轮廓,直接填充就不会有洞的问题,但缺点是你会丢失内部洞的轮廓数据,如果之后需要用到洞的轮廓就不太方便了。

备注:内容来源于stack exchange,提问作者DozerD

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 08:49:31