Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV findContours() complains if used with black-white image

Tags:

python

opencv

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
like image 777
dgrat Avatar asked Jun 10 '15 13:06

dgrat


1 Answers

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.

enter image description here

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

enter image description here

With the following contours highlighted in cnt_test.jpg

enter image description here

like image 92
Tomas Camin Avatar answered Sep 20 '22 13:09

Tomas Camin