Py学习  »  Python

基于Python的OpenCV轮廓检测聚类

OpenCV学堂 • 2 年前 • 284 次点击  

点击上方↑↑↑OpenCV学堂”关注我

来源:公众号 小白学视觉 授权


简介


OpenCV的“findContours”功能经常被计算机视觉工程师用来检测物体。OpenCV的存在,使得我们只需要编写几行代码就可以检测轮廓(对象)。然而,OpenCV检测到的轮廓通常是分散的。例如,一个功能丰富的图像可能有数百到数千个轮廓,但这并不意味着图像中有那么多对象。一些属于同一对象的轮廓是单独检测的,因此我们感兴趣的是对它们进行分组,使一个轮廓对应一个对象。


实现思路


当我在项目中遇到这个问题时,我花了很多时间尝试使用不同的参数或不同的OpenCV函数来检测轮廓,但没有一个有效。然后,我做了更多的研究,在OpenCV的论坛上找到了一篇帖子,它提到了凝聚聚类。但是,没有给出源代码。我还发现sklearn支持聚合聚类,但我没有使用它,原因有两个:

  1. 这个功能对我来说似乎很复杂。我不知道如何输入正确的参数,我怀疑轮廓检测的数据类型是否适合该函数。
  2. 我需要使用python 2.7、OpenCV 3.3.1和Numpy 1.11.3。它们与sklearn的版本(0.20+)不兼容,后者支持聚类。



源代码


为了分享我编写的函数,我在Github中对其进行了开源,并将其作为要点发布在下面。以下版本适用于Python3,若需要要在Python2.7中使用它,只需将“range”更改为“xrange”。

#!/usr/bin/env python3
import osimport cv2import numpy
def calculate_contour_distance(contour1, contour2): x1, y1, w1, h1 = cv2.boundingRect(contour1) c_x1 = x1 + w1/2 c_y1 = y1 + h1/2
x2, y2, w2, h2 = cv2.boundingRect(contour2) c_x2 = x2 + w2/2 c_y2 = y2 + h2/2
return max(abs(c_x1 - c_x2) - (w1 + w2)/2, abs(c_y1 - c_y2) - (h1 + h2)/2)
def merge_contours(contour1, contour2): return numpy.concatenate((contour1, contour2), axis=0)
def agglomerative_cluster(contours, threshold_distance=40.0): current_contours = contours while len(current_contours) > 1: min_distance = None min_coordinate = None
for x in range(len(current_contours)-1): for y in range(x+1, len(current_contours)): distance = calculate_contour_distance(current_contours[x], current_contours[y]) if min_distance is None: min_distance = distance min_coordinate = (x, y) elif distance < min_distance: min_distance = distance min_coordinate = (x, y)
if min_distance < threshold_distance: index1, index2 = min_coordinate current_contours[index1] = merge_contours(current_contours[index1], current_contours[index2]) del current_contours[index2] else: break
return current_contours

注意:

  • “calculate_contour_distance”函数获取轮廓的边界框,并计算两个矩形之间的距离。

  • “merge_contours”函数,我们只需使用'numpy.concatenate'即可,因为每个轮廓只是一个点的numpy数组。

  • 使用聚类算法,我们不需要事先知道有多少个聚类。相反,可以向函数提供阈值距离,例如40个像素,因此如果所有轮廓中最近的距离大于阈值,则函数将停止处理。


结果


要可视化集群效果,请参见下面的两幅图像。第一幅图像显示最初检测到12个轮廓,聚类后只剩下4个轮廓,如第二幅图像所示。这两个小对象是由于噪声造成的,它们没有合并,因为与阈值距离相比,它们离太远。




GITHUB代码链接:

https://github.com/CullenSUN/fish_vision/blob/master/obstacle_detector_node/src/opencv_utils.py

扫码查看OpenCV+Pytorch系统化学习路线图


 推荐阅读 

CV全栈开发者说 - 从传统算法到深度学习怎么修炼

Pytorch轻松实现经典视觉任务

教程推荐 | Pytorch框架CV开发-从入门到实战

OpenCV4 C++学习 必备基础语法知识三

OpenCV4 C++学习 必备基础语法知识二

OpenCV4.5.4 人脸检测+五点landmark新功能测试

OpenCV4.5.4人脸识别详解与代码演示

OpenCV二值图象分析之Blob分析找圆



Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/126137
 
284 次点击