首页 > 编程问答 >如何跟踪之前图像的轮廓?

如何跟踪之前图像的轮廓?

时间:2024-07-25 04:12:59浏览次数:7  
标签:python opencv machine-learning computer-vision artificial-intelligence

所以我有一段细菌细胞移动的视频,我将其转换为帧。现在我想找到每个细菌细胞的瞬时速度。为此,我有兴趣了解细菌细胞移动的程度,但我不知道如何告诉我的程序准确识别这种特定细菌的移动。例如,假设我只有两张图像。对于每个图像,我都有每个细菌的 COM 坐标。现在我如何关联这些数据。我如何要求我的程序准确识别出这种特定细菌的 COM 变化。我已附上两张图像以供参考。

sample image 1 sample image 2

我认为的一种方法是为每个轮廓赋予一个唯一的 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()

跟踪视频中细菌的运动并找到其瞬时速度的一种常见方法是使用 物体跟踪 算法。物体跟踪算法在连续帧中建立对应关系,使能够跟踪单个细菌随时间的推移。

以下是可以调整的方法的步骤:

  1. 预处理: 当前的预处理步骤(多尺度 Retinex 和自适应阈值)是一个良好的开端。这有助于增强图像并分割细菌。

  2. 轮廓检测和过滤: 已经正确地找到了轮廓。除了大小过滤之外,还可以使用其他基于形态学特征的标准(例如,圆度、纵横比)来消除误报。

  3. 物体跟踪:

  4. 为每个检测到的细菌分配唯一的 ID: 从第一帧开始。为检测到的每个细菌分配一个唯一的 ID。
  5. 在后续帧中预测位置: 可以使用几种跟踪算法。一些流行的选择包括:
    • 质心距离: 此简单算法计算当前帧和前一帧中物体质心之间的距离。它将具有最接近质心的物体分配给同一 ID。
    • 卡尔曼滤波: 这是一种更强大的跟踪方法,它可以使用有关物体运动的信息(例如,速度和加速度)来预测其未来位置。
    • 匈牙利算法: 这是一种用于基于成本函数(例如,质心距离或重叠区域)在连续帧中找到物体之间最佳匹配的算法。
  6. ID 更新: 随着帧的推移,跟踪算法会将相同的 ID 分配给代表同一细菌的检测到的物体。

  7. 计算瞬时速度: 一旦跟踪了细菌,就可以通过在连续帧中找到其质心的位移来轻松计算其瞬时速度。速度可以计算为每单位时间内行进的距离。

代码示例(使用 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

相关文章

  • 使用OpenCV拼接2d直方图 - 合并cv2.detail.MatchesInfo
    我试图将多个二维直方图(二维数据数组)拼接在一起,其中直方图的水平轴和垂直轴是空间坐标,但不同直方图的原点可能会有所不同。因此,此任务需要在识别匹配特征后进行仿射变换,为此需要稍微修改OpenCV拼接管道(https://github.com/opencv/opencv/blob/4.x/samples/python/stitch......
  • a method to make some handy tools with python
    Inmyworkingofcomputer,therearealotofsimplejobsthatarefrequentlyrepeated.Itriedtofindawaytomakethesejobbeenprocessedeasily.Method1:Themethodiswritingascripttodothejob,andexecutingthescriptbyutoolsextensionuto......
  • Python网络爬虫详解:实战豆瓣电影信息采集
    文章目录前言一、爬虫是什么?二、常用库及其作用1.Requests2.BeautifulSoup3.lxml4.Scrapy5.Selenium6.PyQuery7.Pandas8.JSON9.Time三、实现步骤步骤一:环境准备步骤二:数据采集步骤三:数据处理步骤四:数据存储总结前言随着互联网的迅猛发展和数据分析需求的不......
  • python学习之内置函数
    Python拥有许多内置函数,这些函数是Python的一部分,不需要额外导入即可直接使用。这些函数提供了对Python解释器功能的直接访问,涵盖了从数学计算到类型检查、从内存管理到异常处理等各个方面。下面是一些常用的Python内置函数及其简要说明:一、Printprint函数大家都不会......
  • Python中以函数为作用域
    点击查看代码#第一题foriteminrange(10):#不报错,没有函数,所有操作在全局作用域里面执行,item最后赋值为:9,此时item在缩进与全局都可以使用passprint(item)#第二题item=10deffunc():foriteminrange(10):#优先在本地查找,找不到在到全局查找p......
  • 掌握IPython宏:%%macro命令的高效使用指南
    掌握IPython宏:%%macro命令的高效使用指南在编程中,宏是一种允许你定义可重用代码片段的强大工具。IPython,这个增强版的Python交互式环境,提供了一个名为%%macro的魔术命令,允许用户创建宏,从而提高代码的可重用性和效率。本文将详细介绍如何在IPython中使用%%macro命令创建宏,并......
  • 7月24号python:库存管理
    7月24号python:库存管理题目:​ 仓库管理员以数组stock形式记录商品库存表。stock[i]表示商品id,可能存在重复。原库存表按商品id升序排列。现因突发情况需要进行商品紧急调拨,管理员将这批商品id提前依次整理至库存表最后。请你找到并返回库存表中编号的最小的元素以便及......
  • IPython的Bash之舞:%%bash命令全解析
    IPython的Bash之舞:%%bash命令全解析IPython的%%bash魔术命令为JupyterNotebook用户提供了一种在单元格中直接执行Bash脚本的能力。这个特性特别适用于需要在Notebook中运行系统命令或Bash特定功能的场景。本文将详细介绍如何在IPython中使用%%bash命令,并提供实际的代码示......
  • Python数据分析与可视化大作业项目说明(含免费代码)
    题目:对全球和中国互联网用户的数据分析与可视化代码下载链接:https://download.csdn.net/download/s44359487yad/89574688一、项目概述1.1.项目背景:互联网是当今时代最重要和最有影响力的技术之一,它已经深刻地改变了人们的生活、工作、学习等方面。互联网用户数据是反映......
  • IPython的跨界魔术:%%javascript命令深度解析
    IPython的跨界魔术:%%javascript命令深度解析IPython,作为Python编程的强大交互式工具,提供了多种魔术命令来扩展其功能。其中,%%javascript魔术命令允许用户在IPythonNotebook中直接执行JavaScript代码,打通了Python和JavaScript两个世界,为数据可视化、Web内容操作等提供了便......