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
相关产品推荐
相关产品推荐

