Home > OS >  label associated to findcontour with opencv
label associated to findcontour with opencv

Time:02-11

I have a mask from which I get the contours information using

contours, hierarchy = cv2.findContours(mask.astype('uint8'),cv2.RETR_CCOMP,cv2.CHAIN_APPROX_NONE)

How do I get the corresponding label array i.e. an array the same size of mask where values are the indices of contours and located on points of mask which are inside corresponding contours ? I found a way using matplotlib.contains_points function but it is very slow. I'm sure there is another way but strangely I can't find it...here is the version with contains_points :

points = np.vstack((Xm.flatten(),Ym.flatten())).T 
labels = -np.ones((mask.shape[0]*mask.shape[1],1))
for ic,contour in enumerate(contours):
    px = contour[:,0,0];
    py = contour[:,0,1];
    p = Path(list(zip(px,py))) # make a polygon
    Inpoints = p.contains_points(points)
    labels[Inpoints] = ic

I'm also trying using cv2.connectedComponents but I can't find a way to get the proper indices as connectedComponents is independent from findcontours...EDIT : here is the piece of code:

# labels of objects
_, labels_obj = cv2.connectedComponents(mask.astype('uint8'))
labels_obj = labels_obj - 1 # remove background
tmp = np.copy(labels_obj)
for ir,iro in enumerate(reg_objects):
    tmp[labels_obj==ir] = iro   1
tmp[tmp<0]=0
labels_obj = tmp
# labels of holes present in objects
_, labels_hol = cv2.connectedComponents((1-mask).astype('uint8'))
labels_hol = labels_hol - 2 # remove background (objects are 0 and background is 1 so -2)
tmp = np.copy(labels_hol)
for ir,irh in enumerate(reg_holes):
    tmp[labels_hol==ir] = irh   1
tmp[tmp<0]=0
labels_hol = tmp
# merge
labels = labels_obj   labels_hol - 1

labels is then an array the same size of maks for which values point to the different objects and holes of mask. The problem is that labels==0 will not point to the same object/hole than contours[0] ... EDIT : the label array is to be used in skimage.measure.regionprops

CodePudding user response:

As suggested in the comments, you can create this mask by drawing contours onto a blank image :

label_map = np.zeros_like(mask, dtype = 'uint8')
contours, hierarchy = cv2.findContours(mask.astype('uint8'),cv2.RETR_CCOMP,cv2.CHAIN_APPROX_NONE)

for i, contour in enumerate(contours):
    label_map = cv2.drawContours(label_map, [contour], -1, (255/(i 1)), -1)#draw and fill the contour with color (255/(1 1)).

Note that the argument (255/(i 1)) is only a way of generating a set of len(contours) different grayscales, you may change it with a set of colors.

  • Related