找到许多明亮圆圈的质心
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
我正在使用 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