I've ran into very strange behavior with cv2.findContours
where it both fails and succeeds executing code on two arrays which are identical.
First, I do some arbitrary image processing on an image and then receive my output, which is in grayscale. We assign the output to the variable estimate
. estimate.shape = (512, 640)
, as it is a grayscale image. I then proceed to save this image to disk with cv2.imwrite('estimate.png', estimate)
, and this is where my code stars misbehaving.
First of all, I try to read the image from disk and process it using cv2.findContours()
according to the documentation on OpenCV. The code looks as follows,and it executes successfully:
im = cv2.imread('estimate.png')
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
This is working as expected. But now, let's try cv2.findContours()
directly on the variable estimate
, without needlessly saving to disk and reading from it:
ret, thresh = cv2.threshold(estimate, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
>>> error: OpenCV(4.6.0) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\thresh.cpp:1659: error: (-210:Unsupported format or combination of formats) in function 'cv::threshold'
Okay, the natural assumption here is that imgray
is different from estimate
. Let us check the data:
type(imgray)
>>> numpy.ndarray
type(estimate)
>>> numpy.ndarray
imgray.shape
>>> (512, 640)
estimate.shape
>>> (512, 640)
np.all(estimate == imgray)
>>> True
Okay, so the arrays are identical in shape and values. What is happening here? We're applying cv2.findContours()
to the exact same numpy.ndarray. It fails when the array is created directly, and it succeeds if it is created via cv2.imread
?
I'm using opencv-python=4.6.0.66 and python=3.9.12
CodePudding user response:
Finally solved this. Turns out, despite looking the same, the problem was in the actual types of arrays.
cv2.findContours()
takes an unsigned 8-bit integer array. Therefore, estimate needs to be converted: estimate = estimate.astype(np.uint8)
.
This can be checked using estimate.dtype
and imgray.dtype
.