找到许多明亮圆圈的质心

Find centroid of many bright circles

我正在使用 Python 找到下图中每个亮点的质心,以计算相邻点之间的平均距离。 scipy.ndimage.find_objects 和 scipy.ndimage.center_of_mass 看起来很有前途,但我不知道如何将所有内容放在一起。 我在哪里可以找到一些参考资料? 我已经使用 Tracker“手动”完成了任务,但我想使该过程自动化。 谢谢。

我们可能可以使用 scipy.ndimage.find_objects 解决它,但我更喜欢使用 cv2.connectedComponentsWithStats:

  • 以灰度模式读取图像。
  • 应用二进制阈值。
  • 使用统计信息查找连通分量。
  • 过滤面积小于4的成分,建立一个(x, y)质心列表。 (不包括非常小的组件,因为可能存在拆分组件)。
  • 画小十字进行测试。
  • 获得 (x, y) 质心列表后,计算邻居之间的平均距离。从 scipy.spatial.distance.
  • 开始计算 cdist

这是一个代码示例:

import numpy as np
import cv2
from scipy.spatial.distance import cdist

img = cv2.imread('spots.png', cv2.IMREAD_GRAYSCALE)  # Load image in Grayscale format.

# Convert to binary - use manual threshold
#_, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU) # Try automatic threshold
_, thresh = cv2.threshold(img, 10, 255, cv2.THRESH_BINARY) # Try manual threshold

# Find connected components with statistics
nlabel, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh, connectivity=8)

test_img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

coords = []  # List of filtered centroieds

# Draw a cross at the coordinates of the centroieds, for testing
for i in range(1, nlabel):
    if (stats[i, cv2.CC_STAT_AREA] > 4):    # Only if area is grater than 4 pixels
        coords.append(centroids[i])  # Create new list of centroids
        x, y = centroids[i]  # Get the coordinate of the centroied
        x, y = int(round(x)), int(round(y))  # Round and cast to int
        cv2.drawMarker(test_img, (x, y), (120, 157, 187), markerType=cv2.MARKER_CROSS, markerSize=5, thickness=1, line_type=cv2.LINE_8)  # Draw cross at the centroied


# Compute average distance between neighbors
################################################################################
# 
# Find euclidean distance from every centroied to every other centroied.
dist = cdist(coords, coords)

dist[dist == 0] = 1.0e9  # Exclude the distance from centroied to itself (replace with large number).

dist = np.sort(dist.ravel())  # Sort the distances

# Each distance is the sorted list is duplicated twice - for point A to point B and from point B to point A.
n_min_dists = len(coords)*2

# Average of centroid to its nearest neighbor.
avg_min_dist = np.average(dist[0:n_min_dists])

# Assume distance to all neighbors is no more than 1.2*"distance to nearest neighbor" (we also want to exclude diagonals)
neighbors_dists = dist[dist < avg_min_dist*1.2]

average_distance_between_neighbors = np.average(neighbors_dists)

print('average_distance_between_neighbors = ' + str(average_distance_between_neighbors))
################################################################################

# Show images for testing
cv2.imshow('thresh', thresh)
cv2.imshow('test_img', test_img)
cv2.waitKey()
cv2.destroyAllWindows()

测试图片:


average_distance_between_neighbors = 21.858534029025055