For the counting of round objects in an image I want to use the watershed algorithm. In order to learn how it works and how I can use it for my needs, I have searched some working examples in python (https://docs.opencv.org/3.1.0/d3/db4/tutorial_py_watershed.html ; http://scikit-image.org/docs/dev/auto_examples/segmentation/plot_label.html)
I finaly found a working solution, which works more or less out-of-the-box for my own purposes (How to define the markers for Watershed in OpenCV?)
With this code I get nice results, both with the example file as with my own images. I do get a strange behavior though after the watershed analysis. For some reason, the watershed step also adds a border around the image. So next to the objects that are detected, also the whole edge of the image gets detected and colored.
My guess is that I should change a parameters in the code to stop this from happening, but so far I'm unable to find what I should do.
this is the code:
import cv2
import numpy as np
from scipy.ndimage import label
def segment_on_dt(a, img):
border = cv2.dilate(img, None, iterations=3)
border = border - cv2.erode(border, None)
dt = cv2.distanceTransform(img, cv2.DIST_L2, 3)
dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(np.uint8)
_, dt = cv2.threshold(dt, 200, 255, cv2.THRESH_BINARY)
lbl, ncc = label(dt)
# Completing the markers now.
lbl[border == 255] = 255
lbl = lbl.astype(np.int32)
cv2.watershed(a, lbl)
lbl[lbl == -1] = 0
lbl = lbl.astype(np.uint8)
return 255 - lbl
# Load image file
img = cv2.imread('coins.jpg')
# Pre-processing.
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gray = cv2.GaussianBlur(img_gray,(5,5),0)
width, height = img_gray.shape
_, img_bin = cv2.threshold(img_gray, 0, 255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
img_bin = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN,np.ones((5, 5), dtype=int))
result = segment_on_dt(img, img_bin)
result[result != 255] = 0
result = cv2.dilate(result, None)
img[result == 255] = (0, 0, 255)
cv2.imwrite('Img_output.png',img)
Running this code will give this result (at least on my pc)
The result for detecting the coins is good enough for my purposes, but I'm a bit puzzled about the image edge that is also detected. From what I see during debugging, the watershed adds this edge, but it is unclear to me why this happens.