4
votes

The OpenCV library provides a function that returns a set of contours for a binary (thresholded) image. The contourArea() can be applied to find associated areas.

Is the list of contours out outputted by findContours() ordered in terms of area by default? If not, does anyone know of a cv2 function that orders a list of contours by area?

Please provide responses in Python, not C.

2
This can be helful. You just need to change the greater function to compare areas. - Miki
To partially address my question, the findContours() apparently outputs a list topologically ordered in terms of (x,y) coordinates (source: stackoverflow.com/questions/28693312/…). The second, bold part of the question still stands. - David Shaked
I was addressing the bold part. You just need to sort your contours using a custom sorting function. I can't give you Python code, but it's pretty straightforward to modify greater comparing contourArea() of the two contours. - Miki
The last part of the post was meant for clarification, not to knock your answer. Hoping for an answer that allows for a comparison of the entire array, rather than a pair of contours, although I suppose the leap from comparison to a sorting function that uses the comparison isn't terribly difficult. My apologies if I'm missing something here. - David Shaked
my response was for clarification, too :D - Miki

2 Answers

11
votes

Use sorted and sort by the area key:

cnts = cv2.findContours(boolImage.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]  
cntsSorted = sorted(cnts, key=lambda x: cv2.contourArea(x))
4
votes
image, cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = sorted(cnts, key=cv2.contourArea)

cnt gives you an ordered list of contours in increasing order w.r.t area.

You can find the area of contour by index:

area = cv2.contourArea(cnt[index])

index can be 1,2,3.....,len(cnts)

For accessing the largest area contour:

cnt[reverse_index]

give reverse_index as -1

For second largest give reverse_index as -2 and so on.

The above can also be achieved with:

cnt = sorted(cnts, key=cv2.contourArea, reverse=True)

so cnt[1] gives the largest contour cnt[2] second largest and so on.