You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何追踪图像轮廓并关联细菌细胞质心以计算瞬时速度?

细菌细胞瞬时速度计算的帧间匹配问题

我将细菌细胞运动的视频转换为帧图像,想要计算每个细菌的瞬时速度,需要确定每个细菌的位移,但无法让程序准确识别前后帧中的同一个细菌。目前已获取每帧中每个细菌的质心(COM)坐标,但不知道如何关联这些数据来确定特定细菌的质心变化量。附上两张示例帧图像供参考。

我曾尝试为每个轮廓分配唯一ID,并关联其长轴、短轴长度等特征来匹配初始与最终质心,但该方法假设所有细菌细胞特征唯一且轮廓识别精准,而我的代码无法满足这一前提。

附上用于识别细菌细胞轮廓的代码:

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()

解决方案

1. 基于匈牙利算法的质心匹配

针对帧间质心的关联问题,最直接的方法是用匈牙利算法解决分配问题:

  • 构建代价矩阵:矩阵元素为前帧每个质心到后帧每个质心的欧氏距离,也可以结合特征加权(比如质心距离+面积差异+角度差异的加权和)
  • 用匈牙利算法找到代价最小的匹配,确保每个前帧质心对应唯一后帧质心,反之亦然
  • 设定距离阈值,超过阈值的匹配视为无效(对应细菌移出视野或新细菌进入的情况)

示例代码片段(依赖scipy库):

from scipy.optimize import linear_sum_assignment
import numpy as np

def match_centroids(prev_centroids, curr_centroids, max_dist=30):
    # 构建代价矩阵
    cost_matrix = np.zeros((len(prev_centroids), len(curr_centroids)))
    for i, prev in enumerate(prev_centroids):
        for j, curr in enumerate(curr_centroids):
            cost_matrix[i,j] = np.linalg.norm(prev - curr)
    
    # 匈牙利算法求解最优匹配
    row_ind, col_ind = linear_sum_assignment(cost_matrix)
    
    # 过滤超出距离阈值的无效匹配
    valid_matches = []
    for r, c in zip(row_ind, col_ind):
        if cost_matrix[r,c] <= max_dist:
            valid_matches.append((r, c))
    
    return valid_matches

2. 卡尔曼滤波预测+匹配

对于连续帧的跟踪,结合卡尔曼滤波预测细菌下一帧位置,再和检测到的质心匹配:

  • 对每个已跟踪的细菌,用卡尔曼滤波预测其在下一帧的位置
  • 将预测位置与当前帧检测到的质心计算距离,优先匹配距离最近的目标
  • 单独处理新出现的细菌(无对应预测轨迹)和消失的细菌(无对应检测结果)

3. 稀疏光流法直接跟踪

如果细菌运动速度不快、帧间隔小,可以用Lucas-Kanade稀疏光流法直接跟踪特征点:

  • 在第一帧检测细菌的质心或轮廓特征点
  • 用cv.calcOpticalFlowPyrLK跟踪这些特征点到后续帧
  • 过滤掉跟踪失败的点,保留有效轨迹用于计算位移

4. 优化当前轮廓检测稳定性

先提升轮廓识别的准确性,减少匹配难度:

  • 调整自适应阈值的blockSize和C参数,减少误检和漏检
  • 修改process_image函数,返回每帧细菌的完整特征列表(包含质心、面积、角度等),而不仅仅是绘图结果
  • 加入形态学操作(比如开运算去除噪点、闭运算填补轮廓缺口),让细菌轮廓更清晰

整合思路

  1. 修改process_image函数,输出每帧的细菌特征集合(质心、面积、角度等)
  2. 对连续两帧,先用卡尔曼滤波预测前帧细菌的位置
  3. 用匈牙利算法结合预测位置与当前帧特征的加权距离完成匹配
  4. 维护全局跟踪ID,处理新出现和消失的细菌

内容的提问来源于stack exchange,提问作者yahya ashraf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 10:27:04