Reputation: 2254
I want to perform edge detection with the following code. However I get an error because of the image color depth. This error in my eyes, makes no sense, as I convert the image properly to a gray-scale image, and in a subsequent step to a black and white image, which is definitely working correctly. When I call findContours
I get an error.
import cv2
def bw_scale(file_name, tresh_min, tresh_max):
image = cv2.imread(file_name)
image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
#(thresh, im_bw) = cv2.threshold(image, tresh_min, tresh_max, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
(thresh, im_bw) = cv2.threshold(image, tresh_min, tresh_max, 0)
cv2.imwrite('bw_'+file_name, im_bw)
return (thresh, im_bw)
def edge_detect(file_name, tresh_min, tresh_max):
(thresh, im_bw) = bw_scale(file_name, tresh_min, tresh_max)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if __name__ == '__main__':
edge_detect('test.jpg', 128, 255)
I get this error:
dgrat@linux-v3pk:~> python aoi.py
OpenCV Error: Unsupported format or combination of formats ([Start]FindContours support only 8uC1 and 32sC1 images) in cvStartFindContours, file /home/abuild/rpmbuild/BUILD/opencv-2.4.9/modules/imgproc/src/contours.cpp, line 196
Traceback (most recent call last):
File "aoi.py", line 25, in <module>
edge_detect('test.jpg', 128, 255)
File "aoi.py", line 19, in edge_detect
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.error: /home/abuild/rpmbuild/BUILD/opencv-2.4.9/modules/imgproc/src/contours.cpp:196: error: (-210) [Start]FindContours support only 8uC1 and 32sC1 images in function cvStartFindContours
Upvotes: 10
Views: 65362
Reputation: 1
Nowadays, findContours
is returning only contours and hierarchy.
Before you pass on the image as a param to the function, it must be a uint8
and must be grayscale. These worked when I used RETR_CCOM
as the mode.
Upvotes: 0
Reputation: 1036
I got the same error when trying with grayscale images, then i tried applying gaussian filter with average of 5X5 blocks with Canny edge detector to a cvtColor converted grayscaled image. Voila! contours on the pic.
Try this code
image = cv2.imread('testimage.jpeg')
im_bw = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
blur = cv2.GaussianBlur(im_bw, (5,5), 0)
im_bw = cv2.Canny(blur, 10, 90)
contours, hierarchy = cv2.findContours(im_bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(image, contours, -1, (0,255,0), 3)
plt.imshow(image)
plt.show()
Upvotes: 0
Reputation: 10096
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)
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
Upvotes: 13
Reputation: 11388
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.
Upvotes: 14