【问题标题】:finding clusters in a picture opencv/python在图片opencv/python中查找簇
【发布时间】:2021-12-31 09:34:44
【问题描述】:

试图在图像中找到“簇”/“圆”/“椭圆”等的中心点。

示例图片:

很明显,有 3 个集群。我正在寻找集群的中心点,以及定义 - 矩形、圆(带半径)或椭圆,但是要描述它。

理想情况下,扩展为以下几种情况:

  1. 如果需要,为简单起见,集群数量未知(假设最少 1 个,最多 10 个)。

这张图片是一张较大图片的一部分,该图片利用精明的边缘检测、阈值处理和轮廓来找到我感兴趣的区域。不幸的是,我需要它......更精致(或更好的参数,但我找不到任何有用的东西)

我尝试过的事情:

我尝试过使用 kmeans 分割,但它们主要用于颜色分割。对于颜色给我们的所有信息,此图像可能是黑白的。 opencv 中的 HughCircles 并不是我真正想要的圆圈,因为它们给了我太多匹配“边缘”的圆圈 通过 opencv 进行模板匹配也不起作用,因为它太受限制,而且这些不能完全匹配。

欢迎提出任何建议/检查途径!
我还尝试了一些基本的散点图 k-means 聚类(好像这是数据),但到目前为止还没有得到好的结果。

选择的语言:python,但适应性强。

【问题讨论】:

  • 我可能会在图像的二进制副本上尝试一些dilations followed by erosions 来填充这些簇的孔并使其彼此分开。然后我会运行blob detector
  • 请注意,您需要在膨胀/腐蚀之前进行反转,因为 OpenCV 需要黑色背景和白色对象/前景。
  • 您需要定义一些领域知识。你可以很容易地说这整个事情只是一个单一的集群或许多非常小的集群。只是观点问题。我将从阈值和距离变换开始,然后尝试找到集群中元素的平均距离(这里的领域知识可以帮助简化或跳过该步骤)。然后找到离下一个掩码像素更远的点,并找到“大”(再次是领域知识)这些区域,并将它们视为可能是集群之间的分隔符。但我没有尝试过,所以可能效果很好。
  • 你说你用过 Canny。这是一个危险信号。呈现数据之前 Canny。

标签: python opencv image-processing


【解决方案1】:

我对此进行了尝试,它可能会为您提供一些关于如何进行的想法 - 即使只是通过查看它无法正常工作的地方。我想在问题获得第三次近距离投票之前发布它。

#!/usr/bin/env python3

import cv2
import numpy as np

# Load image and make greyscale version too
im = cv2.imread('dl9Vx.png')
grey = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)

# Threshold (in case we do morphology) and invert
_, thresh = cv2.threshold(grey, 254, 255, cv2.THRESH_BINARY_INV)
cv2.imwrite('DEBUG-thresh.png', thresh)

# Prepare to do some K-means
# https://docs.opencv.org/4.x/d1/d5c/tutorial_py_kmeans_opencv.html
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
# Find x,y coordinates of all non-white pixels in original image
Y, X = np.where(thresh==255)
Z = np.column_stack((X,Y)).astype(np.float32)

nClusters = 3
ret,label,center=cv2.kmeans(Z,nClusters,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)

# Mark and display cluster centres 
for x,y in center:
    print(f'Cluster centre: [{int(x)},{int(y)}]')
    cv2.drawMarker(im, (int(x), int(y)), [0,0,255])

cv2.imwrite('result.png', im)

输出

Cluster centre: [103,65]
Cluster centre: [50,93]
Cluster centre: [60,29]


注意事项:

注意 1:我要求它搜索 3 个集群,因为这是您建议的数字。有一些方法可以自动确定集群的数量 - 例如,搜索 “Elbow Method”

注意 2:如果您想对间隙进行形态闭合,以使簇更牢固,您可以在 cv2.threshold() 之后添加此代码:

kernel = np.ones((3,3),np.uint8)
thresh = cv2.dilate(thresh, kernel, iterations=1)

它会使阈值图像看起来像这样:

注3

您可以删除阈值调用并将np.where() 行更改为:

Y, X = np.where(im!=255)

【讨论】:

    猜你喜欢
    • 2020-11-14
    • 2020-10-15
    • 2013-03-15
    • 2022-08-12
    • 1970-01-01
    • 2021-04-22
    • 2015-01-21
    • 2015-05-16
    • 2019-02-04
    相关资源
    最近更新 更多