Carlo
Carlo

Reputation: 1576

Python, OpenCV - drawContours of overlapping regions, some pixels are excluded?

I am experimenting with cv2.drawContours. I tried this:

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)

I assumed that, since I am using thickness=-1, contours would be filled, and since the areas are overlapping I would end up with the union of the areas delimited by the 2 contours in cts1.
However, when printing img1, I see there are 2 values that are still 0 in the overlapping area (img1[3][4] and img1[3][5]). Why is this happening?

EDIT:

I tried using the 2 contours separately, and this is what I get (for the first, second and both contours, respectively):

cnt1 cnt2 both

Upvotes: 0

Views: 135

Answers (1)

pippo1980
pippo1980

Reputation: 3096

mmmh I tried to figure out what is going on and tried some more on the same example , please follow this approach:

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)

output:

img1 :

enter image description here

imga :

enter image description here

imgb :

enter image description here

img1 :

enter image description here

imgX :

enter image description here

changing :

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

and

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

to

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

and

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

I get imgX :

enter image description here

Upvotes: 0

Related Questions