OpenCV watershed on Grayscale image

346 Views Asked by At

I am ready to pull my hair out, I have no idea what is going on.

I am performing watershed on an image I have. I have created markers for the watershed. I can apply the watershed on my original, 3 channel color image. HOWEVER, I need to do some image analysis prior to the watershed (noise reduction, etc., etc.).

Thus, the watershed applied to my original image does not turn out properly. Instead, I want to apply the watershed to an image with a distanceTransform applied, with my markers.

The relevant code:

# Need to watershed this
filled_img = filled_img.astype(np.uint8)
dist = cv2.distanceTransform(filled_img, cv2.DIST_L2, 0)

dist *= (1/dist.max())

dist3d = cv2.cvtColor(dist, cv2.COLOR_GRAY2BGR)


watershed_markers = cv2.watershed(dist3d, markers)
#watershed_markers = watershed(-dist, markers, mask=filled_img)

fig = plt.figure(figsize = (15,15))
plt.imshow(watershed_markers)

watershed_img = crop_img
watershed_img[watershed_markers==-1] == [255,0,0]

plt.figure(figsize=(20,20))
plt.imshow(watershed_img, 'jet')

However, no matter what I try, I get this error:

error                                     Traceback (most recent call last)
new_BSA.ipynb Cell 12 in <cell line: 10>()
      5 dist *= (1/dist.max())
      7 dist3d = cv2.cvtColor(dist, cv2.COLOR_GRAY2BGR)
---> 10 watershed_markers = cv2.watershed(dist3d, markers)
     11 #watershed_markers = watershed(-dist, markers, mask=filled_img)
     13 fig = plt.figure(figsize = (15,15))

error: OpenCV(4.5.5) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\segmentation.cpp:161: error: (-215:Assertion failed) src.type() == CV_8UC3 && dst.type() == CV_32SC1 in function 'cv::watershed'

Does anyone have any idea how to resolve this?

It is frustrating because my original image and the 3d distance image are both 3 channel images, I don't know why this error is showing up.

Any help is greatly appreciated

EDIT:

For a minimum reproducible example, I will start with my processed binary image, as I can't perform the watershed on my original image, which is shown here:

Original image

After processing, I get two binary images:

closing, on the left, which I use to obtain my markers, and filled_img on the right, which I want to apply the watershed to.

Processed image

From here, I extract the markers:

# Get difference between the two images, closing and filled_img
closing = closing.astype(np.uint8)
filled_img = filled_img.astype(np.uint8)
markers = cv2.subtract(filled_img, closing)

Then, I create a sure background from the image (areas close to the objects I know are background) by using dilation. Then, I extract the unknown regions, by using the difference between the sure foreground and my markers:

# sure background area
kernal = np.ones((3,3), np.uint8)
sure_bg = cv2.dilate(filled_img, kernal, iterations=3)

# sure fg area
sure_fg = markers

# unknown region
unknown = cv2.subtract(sure_bg, markers)

Then, following this example: https://docs.opencv.org/4.x/d3/db4/tutorial_py_watershed.html

I label my regions, ensuring that the unknown region is = 0, where the watershed will be flooded:

ret, markers = cv2.connectedComponents(sure_fg)
markers = markers+1

markers[unknown==True]=0

Here is an image of what the markers now looks like:

markers

Finally, from my initial post, I apply the watershed, where the error is appearing:

# Need to watershed this
filled_img = filled_img.astype(np.uint8)
dist = cv2.distanceTransform(filled_img, cv2.DIST_L2, 0)

dist *= (1/dist.max())

dist3d = cv2.cvtColor(dist, cv2.COLOR_GRAY2BGR)


watershed_markers = cv2.watershed(dist3d, markers)
#watershed_markers = watershed(-dist, markers, mask=filled_img)

fig = plt.figure(figsize = (15,15))
plt.imshow(watershed_markers)

watershed_img = crop_img
watershed_img[watershed_markers==-1] == [255,0,0]
0

There are 0 best solutions below