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

OpenCV drawContours绘制重叠区域时部分像素被排除?原因解析

cv2.drawContours填充重叠区域出现空白的原因及解决方法

我在测试cv2.drawContours函数时编写了如下代码:

import cv2
import numpy as np

def fix_format(cts):
    return [np.asarray(np.round(ct), np.int32)[:, :, np.newaxis] for ct in cts]

# 两个重叠的矩形轮廓
cts1 = [
    [[1, 1], [6, 1], [6, 4], [1,4]],
    [[3, 2], [7, 2], [7, 7], [3,7]]
]
img1 = cv2.drawContours(np.zeros([10, 10]), fix_format(cts1), contourIdx=-1, color=1, thickness=-1)

原本以为设置thickness=-1会填充轮廓,重叠区域会得到两个区域的并集,但打印img1时发现重叠区域的img1[3][4]和img1[3][5]仍为0值。

我分别单独测试两个轮廓,得到了对应结果:

  • 单独绘制第一个轮廓:重叠区域为填充状态
  • 单独绘制第二个轮廓:重叠区域为填充状态
  • 同时绘制两个轮廓:重叠区域变为空白

原因分析

cv2.drawContours在thickness=-1填充轮廓时,默认采用奇偶填充规则(Odd-Even Rule):
对于图像中的每个像素,统计穿过该像素的轮廓边数量,若为奇数则填充,偶数则不填充。当两个重叠轮廓覆盖同一像素时,该像素会被两次计数(偶数),因此不会被填充,最终值保持为0。

你的两个矩形轮廓重叠区域(x范围3-6,y范围2-4)内的像素,会被两个轮廓各填充一次,触发奇偶规则的抵消逻辑,所以这些像素最终为0。

解决方法

如果需要得到两个轮廓区域的并集,可以采用以下方式:

分别填充后按位或
先单独填充每个轮廓到不同的图像,再通过按位或操作合并结果,确保重叠区域保留填充状态:

import cv2
import numpy as np

def fix_format(cts):
    return [np.asarray(np.round(ct), np.int32)[:, :, np.newaxis] for ct in cts]

cts1 = [
    [[1, 1], [6, 1], [6, 4], [1,4]],
    [[3, 2], [7, 2], [7, 7], [3,7]]
]

img_base = np.zeros([10, 10], dtype=np.uint8)
# 单独填充第一个轮廓
img_cnt1 = cv2.drawContours(img_base.copy(), fix_format(cts1[:1]), -1, 1, -1)
# 单独填充第二个轮廓
img_cnt2 = cv2.drawContours(img_base.copy(), fix_format(cts1[1:]), -1, 1, -1)
# 按位或得到并集
img_union = cv2.bitwise_or(img_cnt1, img_cnt2)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:43:14