OpenCV findContours() complains if used with black-white image
The problem in your code is that you're misusing the return values of cv2.threshold()
.
cv2.threshold returns 2 parameters:
retval
is used when thresholding using the OTSU method (returning the optimal threshold value) otherwise it returns the same threshold value you passed to the function, 128.0 in your case.
dst
is the thresholded result image
In your code thresh
is a float not a Mat.
Change:
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
to
contours, hierarchy = cv2.findContours(im_bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
EDIT
Below find a refactored and simplified version of your original code using the following test image.
import cv2
def edge_detect(file_name, tresh_min, tresh_max):
image = cv2.imread(file_name)
im_bw = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
(thresh, im_bw) = cv2.threshold(im_bw, tresh_min, tresh_max, 0)
cv2.imwrite('bw_'+file_name, im_bw)
contours, hierarchy = cv2.findContours(im_bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(image, contours, -1, (0,255,0), 3)
cv2.imwrite('cnt_'+file_name, image)
if __name__ == '__main__':
edge_detect('test.jpg', 128, 255)
This produces the following bw_test.jpg
With the following contours highlighted in cnt_test.jpg
UPDATE
Considering that you already convert you image to gray scale, the problem should be with the channel range. FindContours
support only 32s
and 8u
. You could use image.dtype
to make sure that you get something like uint8
. If not cv2.convertScaleAbs(image)
should solve your problem.
ORIGINAL ANSWER
As the error mentions FindContours support only 8uC1 and 32sC1 images
. So might want to use something like cv.CvtColor
to convert your image to a supported color space.