4

I am trying to apply the WaterShed algorithm to an image as per the tutorial: OpenCv WaterShed Docs . I have earlier applied Otsu's thresholding after Gaussian filtering and Morpholigical Transformations on a greyscale image to improve Image quality as per the code:

img = cv2.imread('Results\Feb_16-0.jpg',0)
kernel = np.ones((1,1),np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
blur = cv2.GaussianBlur(opening,(1,1),0)
ret3,th4 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

Applying the distance transform as the first stage of the watershed algorithm as per the code:

# sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=1)
# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,3)

creates the error:

error: (-215) src.type() == CV_8UC3 && dst.type() == CV_32SC1 in function cv::watershed

wherein the 8bit 3 channel image is being attempted to be converted to a 32bit single channel image. How do I prevent this and yet work with the Distance Transform?

Anindita Bhowmik
  • 808
  • 1
  • 9
  • 17

2 Answers2

1

This error arises when your input array into cv2.distanceTransform is not formatted properly. It should be a 2D array of type np.uint8 (not int8).

For example

import cv2 as cv
import numpy as np

testim = np.zeros((11,11), dtype = uint8)
testim[2:6,1:6] = 255
testim[3,3] = 0
print(testim)
dist = cv.distanceTransform(testim, cv.DIST_L2, 5)
print(testim)

If you are reading an image that is not in the right format, you must first convert it to gray (only one channel) and make sure it is in the uint8 format. This can be done with imagename.astype(np.uint8)

This was tested in opencv version 3.3.1, python 3.5.

gtcoder
  • 111
  • 1
  • 5
0

In function cv2.watershed(img,markers) your input parameter img must have 3 channels. Full working code:

#Load image in grayscale
img = cv2.imread('Results\Feb_16-0.jpg',0)

kernel = np.ones((1,1),np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
blur = cv2.GaussianBlur(opening,(1,1),0)
ret3,th4 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=1)
# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,3)

ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)

ret, markers = cv2.connectedComponents(sure_fg)
markers = markers+1
markers[unknown==255] = 0
markers = markers.astype('int32')

#now load same image as color image
img = cv2.imread('Results\Feb_16-0.jpg',1)

markers = cv2.watershed(img,markers)
img[markers == -1] = [255,0,0]
Alex
  • 26
  • 5