OpenCV:按面积对轮廓进行排序(Python)

6
OpenCV库提供了一个函数,用于返回二进制(阈值化)图像的轮廓集。 contourArea() 可以应用于查找相关区域。
findContours()输出的轮廓列表是否默认按面积排序?如果不是,有没有人知道一种按面积对轮廓列表进行排序的cv2函数?
请使用Python而不是C来提供答案。

1
这个可以很有帮助。你只需要改变greater函数来比较面积。 - Miki
为了部分回答我的问题,findContours() 显然会输出一个基于 (x,y) 坐标进行拓扑排序的列表(来源:http://stackoverflow.com/questions/28693312/opencv-findcontours-how-contours-are-ordered)。第二个加粗的问题仍然存在。 - David Shaked
帖子的最后一部分是为了澄清,而不是贬低你的回答。希望能得到一个允许对整个数组进行比较的答案,而不仅仅是一对轮廓,尽管我认为从比较到使用比较的排序函数并不是非常困难。如果我在这里漏掉了什么,请原谅我。 - David Shaked
我的回复是为了澄清,哈哈 :D - Miki
刚刚看到链接帖子底部应用了排序方法。看起来我已经找到了所需要的。 - David Shaked
显示剩余2条评论
2个回答

16

使用 sorted 并按照面积键进行排序:

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))

11
image, cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = sorted(cnts, key=cv2.contourArea)

cnt按面积递增的顺序给出轮廓的有序列表。

可以通过索引找到轮廓面积:

area = cv2.contourArea(cnt[index])

索引可以是1、2、3......直到cnts的长度

访问最大面积轮廓:

cnt[reverse_index]

将reverse_index设为-1即可找到最大值。

要找到第二大的值,将reverse_index设为-2,以此类推。

以上也可以通过以下方式实现:

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

所以 cnt[1] 给出最大的轮廓,cnt[2] 给出第二大的轮廓,以此类推。


如果我有两个或更多轮廓,并且我需要将它们相加。请问如何实现?例如:cnts = sorted(contours, key=cv2.contourArea, reverse=True)[:5] # 获取最大的五个轮廓面积 - Redhwan
1
面积= sum([cv2.contourArea(cnt) for cnt in sorted(cnts, key=cv2.contourArea, reverse=True)[:5]]) - Kanish Mathew
我尝试了类似于你的工作 {{{x,y,w,h = [cv2.boundingRect(n) for n in cnts]}}} 但是出现了错误:ValueError:无法解包太多的值。 - Redhwan
[cv2.boundingRect(n) for n in cnts] => 它会返回一个列表,其中包含 [(x,y,w,h), (x,y,w,h).....]。这就是为什么它显示错误的原因。 - Kanish Mathew
2
最大的应该是cnt[0],第二大的应该是cnt[1],因为我们是从0开始索引。如果不是,那么在索引0处是什么? - Prox
索引可以是1、2、3......len(cnts),这就是为什么是cnt[1],否则它将是cnt[0]。 - Kanish Mathew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接