Search code examples
pythonopencvimage-processingwatershed

how to mark the labels on image using watershed opencv


As this is the output from the watershed and I want to mark the labels like 1,2,3 etc on the regions identified. I have tried to use cv2.puttext as well by using cv2.boudingrect but the labels are not coming in the center of the region identified

1

for i in range(2, ret3+1):
    a=0
    b=0
    mask = np.where(markers==i, np.uint8(255), np.uint8(0))
    x,y,w,h = cv2.boundingRect(mask)
    area = cv2.countNonZero(mask[y:y+h,x:x+w])
    print ("Label %d at (%d, %d) size (%d x %d) area %d pixels" % (i,x,y,w,h,area))

    # Visualize
    color = np.uint8(np.random.random_integers(0, 0, 3)).tolist()
    output[mask!=0] = color
    
    
    
    cv2.putText(img2,'%d'%i,(int(x), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 3.9, color, 15, cv2.LINE_AA)



plt.imshow(img2, cmap='jet')
plt.show()

Through the above code the generated labels are as follows

2

What i want is that to mark the labels 3,4,5 etc in the center of the objects identified by watershed.


Solution

  • You can find the center of each region like this:

    markers = cv2.watershed(img, markers)
    
    labels = np.unique(markers)
    for label in labels:
        y, x = np.nonzero(markers == label)
        cx = int(np.mean(x))
        cy = int(np.mean(y))
    

    The result:

    enter image description here

    Complete example:

    import cv2
    import numpy as np
    
    img = cv2.imread("water_coins.jpg")
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    
    # noise removal
    kernel = np.ones((3, 3), np.uint8)
    opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
    # sure background area
    sure_bg = cv2.dilate(opening, kernel, iterations=3)
    # Finding sure foreground area
    dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
    ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
    # Finding unknown region
    sure_fg = np.uint8(sure_fg)
    unknown = cv2.subtract(sure_bg, sure_fg)
    
    
    # Marker labelling
    ret, markers = cv2.connectedComponents(sure_fg)
    # Add one to all labels so that sure background is not 0, but 1
    markers = markers + 1
    # Now, mark the region of unknown with zero
    markers[unknown == 255] = 0
    
    markers = cv2.watershed(img, markers)
    
    labels = np.unique(markers)
    for label in labels:
        y, x = np.nonzero(markers == label)
        cx = int(np.mean(x))
        cy = int(np.mean(y))
        color = (255, 255, 255)
        img[markers == label] = np.random.randint(0, 255, size=3)
        cv2.circle(img, (cx, cy), 2, color=color, thickness=-1)
        cv2.putText(img, f"{label}", (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.35, color, 1, cv2.LINE_AA)
    
    
    cv2.imwrite("out.jpg", img)