所以我有一段细菌细胞移动的视频,我将其转换为帧。现在我想找到每个细菌细胞的瞬时速度。为此,我有兴趣了解细菌细胞移动的程度,但我不知道如何告诉我的程序准确识别这种特定细菌的移动。例如,假设我只有两张图像。对于每个图像,我都有每个细菌的 COM 坐标。现在我如何关联这些数据。我如何要求我的程序准确识别出这种特定细菌的 COM 变化。我已附上两张图像以供参考。
我认为的一种方法是为每个轮廓赋予一个唯一的 id,并将该轮廓的特征与该唯一的 id 相关联。例如它的长轴和短轴长度。这样我就可以关联轮廓的初始和最终 COM。但这个想法假设所有细菌细胞都是唯一的,并且我的代码能够准确、精确地识别每个细菌细胞的轮廓,但事实并非如此。我还附上了用于查找每个细菌细胞轮廓的代码,以防万一您感兴趣。有人可以提出一些更好的想法吗?太感谢了。
import cv2 as cv
import numpy as np
from numpy.typing import NDArray
import math
def gaussian_filter_multiscale_retinex(image: NDArray, sigmas: list[float], weights: list[float]) -> NDArray:
img32 = image.astype('float32') / 255
img32_log = cv.log(img32 + 1)
msr = np.zeros(image.shape, np.float32)
for sigma, weight in zip(sigmas, weights):
blur = cv.GaussianBlur(img32, ksize=(0, 0), sigmaX=sigma)
blur_log = cv.log(blur + 1)
ssr = cv.subtract(img32_log, blur_log)
ssr = cv.multiply(ssr, weight)
msr = cv.add(msr, ssr)
msr = cv.divide(msr, sum(weights))
msr = cv.normalize(msr, None, 0, 255, cv.NORM_MINMAX, cv.CV_8U)
return msr
def calculate_ellipse_area(ellipse):
(cx, cy), (a, b), angle = ellipse
semi_major_axis = a / 2
semi_minor_axis = b / 2
area = math.pi * semi_major_axis * semi_minor_axis
return area,angle
def process_image(img, size_threshold):
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
rtnx = gaussian_filter_multiscale_retinex(gray, sigmas=[15, 55, 185], weights=[10, 5, 1])
thresholded = cv.adaptiveThreshold(rtnx, 255, adaptiveMethod=cv.ADAPTIVE_THRESH_GAUSSIAN_C,
thresholdType=cv.THRESH_BINARY, blockSize=7, C=-7)
nb_components, output, stats, _ = cv.connectedComponentsWithStats(thresholded, connectivity=8)
sizes = stats[1:, -1]
new_img = np.zeros_like(thresholded)
for i in range(0, nb_components - 1):
if sizes[i] >= size_threshold:
new_img[output == i + 1] = 255
connected_components = cv.connectedComponentsWithStats(new_img)
(numLabels, labels, stats, centroids) = connected_components
result_image = np.ones_like(img) * 255
for i in range(1, numLabels):
componentMask = (labels == i).astype('uint8')
contours, _ = cv.findContours(componentMask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
if len(contours) > 0:
cnt = contours[0]
if len(cnt) >= 5:
ellipse = cv.fitEllipse(cnt)
area, angle = calculate_ellipse_area(ellipse)
if area < 250:
cv.ellipse(result_image, ellipse, (0, 0, 0), 1) # Draw black contours on white background
return result_image
img1path = "/Users/yahya2/Desktop/1.png"
img = cv.imread(img1path)
size_threshold = 16
result_image = process_image(img, size_threshold)
cv.imshow('Contours', result_image)
cv.waitKey(0)
cv.destroyAllWindows()
跟踪视频中细菌的运动并找到其瞬时速度的一种常见方法是使用 物体跟踪 算法。物体跟踪算法在连续帧中建立对应关系,使能够跟踪单个细菌随时间的推移。
以下是可以调整的方法的步骤:
-
预处理: 当前的预处理步骤(多尺度 Retinex 和自适应阈值)是一个良好的开端。这有助于增强图像并分割细菌。
-
轮廓检测和过滤: 已经正确地找到了轮廓。除了大小过滤之外,还可以使用其他基于形态学特征的标准(例如,圆度、纵横比)来消除误报。
-
物体跟踪:
- 为每个检测到的细菌分配唯一的 ID: 从第一帧开始。为检测到的每个细菌分配一个唯一的 ID。
-
在后续帧中预测位置:
可以使用几种跟踪算法。一些流行的选择包括:
- 质心距离: 此简单算法计算当前帧和前一帧中物体质心之间的距离。它将具有最接近质心的物体分配给同一 ID。
- 卡尔曼滤波: 这是一种更强大的跟踪方法,它可以使用有关物体运动的信息(例如,速度和加速度)来预测其未来位置。
- 匈牙利算法: 这是一种用于基于成本函数(例如,质心距离或重叠区域)在连续帧中找到物体之间最佳匹配的算法。
-
ID 更新: 随着帧的推移,跟踪算法会将相同的 ID 分配给代表同一细菌的检测到的物体。
-
计算瞬时速度: 一旦跟踪了细菌,就可以通过在连续帧中找到其质心的位移来轻松计算其瞬时速度。速度可以计算为每单位时间内行进的距离。
代码示例(使用 OpenCV 中的质心距离):
import cv2
import numpy as np
# 预处理参数(根据的图像调整)
size_threshold = 16
# 跟踪参数
max_distance = 10 # 用于将物体关联到下一帧的最大质心距离
def process_image(img):
# ... (现有的预处理和轮廓检测代码) ...
return centroids
# 加载视频
cap = cv2.VideoCapture('bacteria_video.avi')
# 初始化跟踪
ret, frame1 = cap.read()
prev_centroids = process_image(frame1)
track_ids = np.arange(len(prev_centroids)) # 为初始质心分配唯一的 ID
while True:
ret, frame2 = cap.read()
if not ret:
break
# 处理当前帧
curr_centroids = process_image(frame2)
# 质心距离跟踪
distances = np.linalg.norm(prev_centroids[:, np.newaxis, :] - curr_centroids[np.newaxis, :, :], axis=2)
row_ind, col_ind = linear_sum_assignment(distances) # 使用匈牙利算法进行最佳匹配
# 更新跟踪 ID 和计算速度
velocities = []
for i, j in zip(row_ind, col_ind):
if distances[i, j] < max_distance:
track_ids[j] = track_ids[i] # 将 ID 从前一帧传输到当前帧
velocity = np.linalg.norm(curr_centroids[j] - prev_centroids[i]) # 计算速度
velocities.append(velocity)
# ...(在图像上可视化跟踪结果和速度)...
# 更新
prev_centroids = curr_centroids
track_ids = track_ids[col_ind] # 保持跟踪的 ID
# 退出条件
if cv2.waitKey(30) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
其他提示:
- 尝试不同的物体跟踪算法以找到最适合的数据的算法。
-
调整跟踪参数(例如,
max_distance
)以获得最佳结果。 - 考虑使用轨迹平滑技术来减少跟踪结果中的噪声。
- 如果的视频具有明显的变化照明条件,可能需要使用更强大的跟踪算法或实施照明不变性技术。
通过实施这些步骤,应该能够跟踪细菌的运动并准确地确定其瞬时速度。
标签:python,opencv,machine-learning,computer-vision,artificial-intelligence From: 78790401