Python,OpenCV - 绘制重叠区域的轮廓时,部分像素被排除?

0 投票
1 回答
77 浏览
提问于 2025-04-14 16:20

我正在尝试使用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]

# these are 2 overlapping rectangular regions
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的时候,我发现重叠区域里有两个值仍然是0(img1[3][4]和img1[3][5])。这是什么原因呢?

补充:

我尝试分别使用这两个轮廓,结果是这样的(分别是第一个、第二个和两个轮廓的结果):

cnt1 cnt2 both

1 个回答

0

嗯,我试着搞清楚发生了什么,并在同一个例子上做了一些尝试,请按照这个方法来操作:

import cv2

import numpy as np


print('OpenCV version : ' , cv2.__version__)


def ResizeWithAspectRatio(image, width=None, height=None, inter=cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]

    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))

    return cv2.resize(image, dim, interpolation=inter)


draw_windows = True  ## change fo False for no windows only calc


def drawWindow(window_name, image):
    if draw_windows:
        
        resize = ResizeWithAspectRatio(image, width= 500)
        
        cv2.imshow(window_name, resize)
        
        cv2.moveWindow(window_name, 600, 200)
        
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
    pass

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



# these are 2 overlapping rectangular regions
cts1 = [
    [[1, 1], [6, 1], [6, 4], [1,4]],
    [[3, 2], [7, 2], [7, 7], [3,7]]
                ]


img1 = np.zeros((10,10))

xmin = np.min(fix_format(cts1)[0][:,0])

xmax = np.max(fix_format(cts1)[0][:,0])

ymin = np.min(fix_format(cts1)[0][:,1])

ymax = np.max(fix_format(cts1)[0][:,1])

print(xmin, xmax, ymin , ymax)


imga = img1.copy().astype(np.uint8)


imga[ymin:ymax , xmin:xmax] = 1


cnt_a, hier = cv2.findContours(imga, cv2.RETR_LIST  , cv2.CHAIN_APPROX_NONE )



print(cnt_a[0].shape)


# img1 = cv2.drawContours(img1, cnt_a, contourIdx = -1 , color = 1, thickness = cv2.FILLED)


drawWindow('imga', imga*255)


# drawWindow('img1', img1)


xmin = np.min(fix_format(cts1)[1][:,0])

xmax = np.max(fix_format(cts1)[1][:,0])

ymin = np.min(fix_format(cts1)[1][:,1])

ymax = np.max(fix_format(cts1)[1][:,1])

print(xmin, xmax, ymin , ymax)


imgb = img1.copy().astype(np.uint8)


imgb[ymin:ymax , xmin:xmax] = 1


cnt_b, hier = cv2.findContours(imgb, cv2.RETR_LIST  , cv2.CHAIN_APPROX_NONE )



print(cnt_b[0].shape)

drawWindow('imgb', imgb*255)


img1 = cv2.drawContours(img1, cnt_a, contourIdx = -1 , color = 1, thickness = cv2.FILLED)


img1 = cv2.drawContours(img1, cnt_b, contourIdx = -1 , color = 1, thickness = cv2.FILLED)


drawWindow('img1', img1)


print(cnt_a, cnt_a[0].shape)

print(cnt_b, cnt_b[0].shape)


cnt_ab = np.concatenate((cnt_a , cnt_b), axis=1)


print(cnt_ab , cnt_ab.shape)



imgx = cv2.drawContours(np.zeros([10, 10]), cnt_ab, contourIdx =-1 , color=1, thickness = cv2.FILLED)


drawWindow('imgx', imgx)

输出结果:

img1 :

这里输入图片描述

imga :

这里输入图片描述

imgb :

这里输入图片描述

img1 :

这里输入图片描述

imgX :

这里输入图片描述

更改:

cnt_a, hier = cv2.findContours(imga, cv2.RETR_LIST , cv2.CHAIN_APPROX_NONE )

cnt_b, hier = cv2.findContours(imgb, cv2.RETR_LIST , cv2.CHAIN_APPROX_NONE )

为:

cnt_a, hier = cv2.findContours(imga, cv2.RETR_LIST , cv2.CHAIN_APPROX_SIMPLE )

cnt_b, hier = cv2.findContours(imgb, cv2.RETR_LIST , cv2.CHAIN_APPROX_SIMPLE )

我得到了 imgX :

这里输入图片描述

撰写回答