Home > Mobile >  how to mark the labels on image using watershed opencv
how to mark the labels on image using watershed opencv

Time:09-13

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.

CodePudding user response:

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)

CodePudding user response:

Erode every region independently with a structuring element that has the size of the region label. Then use any remaining pixel.

In some cases (tiny regions), no pixel at all will remain. You have two options

  • use a pixel from the "ultimate eroded";

  • use some location near the region and a leader line (but avoiding collisions is uneasy).


You can also work with the inner distances of the regions and pick pixels with maximum distance.

  • Related