0
votes

So, the issue here is that I am not getting why the findContours() function for python3 version of openCV returns a null hierarchy and, consequently, no contour is found.

A bit of context: I'm extracting shapes from images and, if a shape is too big (according to some features like Area, for instance) then I extract this shape and analyse it separately. This means I look for further contours that can be present in the "big" shape.

I need to be sure about this fact: If the hierarchy is Null, can I be there are no contours in the "big" image I'm working on?

A piece of code to clarify even more:

#bigSharpened is a binary image with little make-up
bigSharpened = cv.filter2D(bigOpened, -1, sharpkrnl)

###########################
#find and analyse contours#
###########################
h, w = sharpened.shape[:2]
_, bigContours0, bigHierarchy = cv.findContours(bigSharpened.copy(),cv.RETR_CCOMP, cv.CHAIN_APPROX_NONE)
bigContours = [cv.approxPolyDP(cnt, 3, True) for cnt in bigContours0]

print(len(bigHierarchy[0]))

and the error message I get when I run the code (which made me think that bigHierarchy is Null hence no contour is found).

Traceback (most recent call last):
  File "filename.py", line 164, in <module>
    print(len(bigHierarchy[0]))
TypeError: 'NoneType' object is not subscriptable

if I try to print the length of bigContours0 I get another error message:

Traceback (most recent call last):
  File "immunoistochemistry_quantification_analysis_with_GAPS.py", line 164, in <module>
    print(len(bigContours0[0]))
IndexError: list index out of range
2
IMHO you're confusing cause and effect -- findContours didn't find any contours, therefore there isn't any hierarchy (I would also expect an empty array rather than None, but alas, that's not the first little oddity I've seen in the Python bindings). What does bigSharpened look like just before that statement?Dan Mašek
added the missing piece of info. bigSharpened is a binary image with little make-up. what do you mean by findContours didn't find any contours?gabt
Well, what's len(bigContours0)? I bet it's 0. | "binary image with little make-up" doesn't tell us much -- save the image to file and attach it to your question. If we don't see the exact inputs, it's impossible to explain why exactly it's acting that way.Dan Mašek
If you feed it a completely black image, then there certainly won't be any contours for it to find (quite simple to reproduce, that was the first thing I tried and a reason why I'm asking these things). | Based on your edits, you didn't do len(bigContours0), but rather len(bigContours0[0]) -- that's a significant difference. If the list is empty (length of 0), then accessing the first element will fail, and that's why you get an error. | If you can't upload it, then at least save it and inspect it in detail yourself. Or just try to make some image that's safe, and causes same issue.Dan Mašek
you're perfectly right (I just tested it), which means that the algorithm is trying to find a contour but can't actually find one since there is nothing to find. You solved the issue without an actual answer!gabt

2 Answers

1
votes

Hopefully this will help someone. cv.findContours method does not find any contours if the image is a black image. Therefore check the image through imshow, bigSharpened.copy() in this case

cv.imshow("Image", bigSharpened.copy())

0
votes

As posted in the comments above this was the issue:

If you feed it a completely black image, then there certainly won't be any contours for it to find (quite simple to reproduce, that was the first thing I tried and a reason why I'm asking these things). | Based on your edits, you didn't do len(bigContours0), but rather len(bigContours0[0]) -- that's a significant difference. If the list is empty (length of 0), then accessing the first element will fail, and that's why you get an error. | If you can't upload it, then at least save it and inspect it in detail yourself. Or just try to make some image that's safe, and causes same issue.

the image is black hence it does not contains any contour. Then printing the wrong element (I'm not fluent in Python) returned the error I was encountering. That's basically it.