I’m trying to separate the dust particles in a picture. To do so, I was thinking of using the watershed algorithm (it’s the first time for me using it).
The picture I’m working with is the following:
Following the tutorial on the OpenCV documentation named “Image Segmentation with Distance Transform and Watershed Algorithm” (I can’t add the direct link), I wrote the following python code:
img = cv2.imread(img_path)
# sharpen the image to acute the edges of the foreground objects
kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]], dtype=np.float32)
imgLaplacian = cv2.filter2D(img, cv2.CV_32F, kernel)
sharp = np.float32(img)
imgResult = sharp - imgLaplacian
# Binarization
gray = cv2.cvtColor(imgResult, cv2.COLOR_BGR2GRAY)
_, img_bin = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
dist = cv2.distanceTransform(img_bin, cv2.DIST_L2, 5)
# Normalize the distance image for range = {0.0, 1.0}
# so we can visualize and threshold it
cv2.normalize(dist, dist, 0, 1.0, cv2.NORM_MINMAX)
# Threshold to obtain the peaks
# This will be the markers for the foreground objects
_, dist = cv2.threshold(dist, min_norm, max_norm, cv2.THRESH_BINARY)
# Dilate a bit the dist image
dist = cv2.dilate(dist, np.ones((3,3), dtype=np.uint8))
# Create the CV_8U version of the distance image
# It is needed for findContours()
dist_8u = dist.astype('uint8')
# Find total markers
contours, _ = cv2.findContours(dist_8u, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Create the marker image for the watershed algorithm
markers = np.zeros(dist.shape, dtype=np.int32)
# Draw the foreground markers
for i in range(len(contours)):
cv2.drawContours(markers, contours, i, (i+1), -1)
cv2.watershed(imgResult, markers)
imgResult[markers == -1] = [255,0,0] # Red border around the identified particles
ImgResult
is the visualized as following:
(I’m sorry, but I cannot add more than one media to the post)
As you can see in the picture, many of the bigger particles are still considered as just one particle, while some of the smaller particles are not even considered.
I’m sure there’s something I’m missing, but I can’t figure out what.
L3t me know if something is not clear or if the pictures are not understandable
P.S.
I also tried to follow “Image Segmentation with Watershed Algorithm” tutorial from OpenCV docs. The results are a little bit better for the bigger particles (they get separated), but it doesn’t identify many particles (I assume due to the morphological operations). The picture follows.
P.P.S.
In both cases, the algorithm generates a weird border around the whole picture