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
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
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:
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.