社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

基于Python的OpenCV轮廓检测聚类

OpenCV学堂 • 3 年前 • 459 次点击  

点击上方↑↑↑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
 
459 次点击