精华内容
下载资源
问答
  • 多目标跟踪算法c代码
    2022-03-17 13:30:28

    KCF跟踪算法/目标跟踪算法KCF案例程序源码

    1、KCF跟踪算法c++

    2、目标跟踪算法KCF的代码,C语言,方便移植

    程序员帮帮

    3、KCF代码运行流程图

    4、kcf与笔记本摄像类调试,测试算法速度,在debug下可运行,

    配置下opencv就可以用了

    5、c++用KCF的追踪过程代替TLD的追踪过程,保留了TLD的检测和学习过

    程,但是没有加入旋转的特征学习

    6、多尺度的KCF的代码

    7、kef与dsst视觉跟踪qt源码,解决了不能动态选框的问题

    8、kef目标跟踪代码et+(直接在vs2010+openev3上面运行就可以),不是

    调用opencv里面现成的函数

    9、KCF,DSST,EOOHC,SAMF,Staple,LMCF,LCT,SRDCF,SRDCFdecon,BACF十个

    目标跟踪算法在OTB100的TRE,SRE矩阵结果,其中包括了OTB50和OTB

    2013(,mat)

    10、KCF跟踪domo1

    11、KCFMatlab源码

    12、KCFdemo实现目标选取,跟踪c++

    13、目标实时跟踪DSST方法c++

    14、实时视频拼接与目标跟踪,附使用说明,只给了release版本

    15、KCFC++demo代码

    16、KCF单目标跟踪

    17、KCF相关滤波跟踪器python寄要numpy,opencv-python库

    18、KCF(KernelizedCorrelationFilters)Matlab源码

    19、DSST相比KCF多目标跟踪,在目标检测多尺度变化(横向车辆,行人,

    及速度较快)修正有很好的矫正,用于配合提高深度学习检测加速有很好

    的提升

    更多相关内容
  • 视频演示算法包括: 1. 静态背景下的背景预测法目标检测 2. 静态背景下帧间差分法目标检测...4. 重心多目标跟踪方法 该框架支持的视频只限于RGB非压缩Windows AVI格式,可以通过“文件”菜单下打开视频来打开视频文件。
  • 基于CSK的目标跟踪算法,原理很简单,速度超快,但此版本窗口固定、抗遮挡能力不强、且波门有滑移。值得研究和试用。泊来品,只是增加了注释,以助理解,共同学习。
  • 17种视觉目标跟踪算法(含相关滤波和深度学习2大派系)的代码(含matlab、Python和c的实现)、论文以及自己学习心得和网上权威原理解读,自己上研究生区间实验室师兄弟专业整理,大部分代码均能调通。【BACF、C-COT...
  • 假mhtmat算法实验室代码多重假设追踪 ...假设跟踪是一种常用的多目标跟踪算法,用于计算机视觉和雷达信号处理。 其性能优于传统的多目标跟踪算法,如JPDA(联合概率数据关联)和GNN(门控最近邻域)。 纸张可在 。
  • 文件夹中为2018年及以前的几种实时并且准确度高的目标跟踪算法源码合集,大部分为matlab编程。部分算法为matlab C++混合编程。 bacf_toupload BACF算法 DSST-master DSST算法 ECO-master ECO-HC算法 fDSST_code ...
  • 多目标跟踪算法解读

    万次阅读 多人点赞 2020-09-28 14:29:43
    一、多目标跟踪背景介绍 1.问题定义 2.难点 3.应用场景 二、相关方法 1.Model free 方法 2. Tracking by detection 方法 1)离线方法 2)在线方法 三、基准 多目标跟踪背景介绍 问题定义 多目标跟踪是将视频...
    目录
    一、多目标跟踪背景介绍
            1.问题定义
            2.难点
            3.应用场景
    二、相关方法
            1.Model free 方法
            2. Tracking by detection 方法
                 1)离线方法
                  2)在线方法
    三、基准
    

    多目标跟踪背景介绍

    问题定义

    多目标跟踪是将视频中每一帧的物体都赋予一个id,并且得到每个id的行为轨迹,如图1所示。
    从代码的层次考虑,其输入为视频序列,输出为物体的行为轨迹和id。从是否有模型上考虑,可以分为model free的方法和tracking by detection的方法,其中后者又可以分为离线学习的方法和在线学习的方法。
    有多目标跟踪算法就有单目标跟踪方法,不同之处就在于匹配问题,举例说明,如果在前一帧检测到两个物体a,b,在后一帧检测到两个物体c,d,怎么知道前一帧的a在后一帧所对应的是c或者d的哪一个物体呢?匹配问题在单目标跟踪领域就不存在,因为前后两帧只存在一个目标。
    在这里插入图片描述

    难点

    多目标跟踪的难点在于ID switch, 如图2所示,当骑自行车的人与步行的人相遇的时候,步行的人发生了遮挡,这是对于电脑来说,认为是此id的跟踪已经结束,过了一段时间,步行的人重新出现在了视野,但是电脑会认为是一个新的物体出现,因此赋予一个新的id,这种情况下,就发生了id交换,同理当物体被其他物体例如电线杆遮挡时也是一样。因此针对这种id交换的情况,学术界提出了很多的解决方案,这个我们后面再看。
    在这里插入图片描述

    应用场景

    多目标跟踪是一种通用的算法,几乎应用在视觉领域的各个方面,例如安防领域、自动驾驶领域以及医疗领域。如图3,4,5所示,在安防领域,我们通常需要跟踪来得到在特定区域的人数统计。在自动驾驶领域,我们通常需要跟踪来预估行人或者车辆的轨迹。在医疗领域,我们通常需要跟踪来得到细胞的运动情况。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    相关方法

    多目标的跟踪方法在这里我们分为两类,model-free的方法和tracking by detection的方法。

    model-free的方法

    model-free的方法核心思想是在第一帧给定初始的检测框,在后续帧中跟踪这些框,这种方法是早期的算法,缺点是如果有些目标在后续帧中才出现,这些目标并不会被跟踪。如图6所示。
    在这里插入图片描述

    tracking by detection的方法

    离线学习

    离线学习的方法缺点在于无法实时处理视频,通过比较相邻帧之间的相似度生成短的轨迹,之后再将短的轨迹合成长的轨迹。如图7所示。
    在这里插入图片描述

    在线学习

    Learning to Track: Online Multi-Object Tracking by Decision Making (2015,ICCV)
    该论文第一次将强化学习加入到跟踪这个领域,将目标的跟踪周期建模成马尔可夫过程进行优化。如图8所示。当物体被检测到之后,被认为是active的状态。在active的状态下如果下一帧也检测到了,状态由active转换为tracked,如果没有检测到,状态转换为inactive状态。在tracked状态下如果如果继续检测到该目标,则持续为tracked状态,如果没检测到,则状态转换为lost。在lost状态下如果被检测到了,则状态恢复为tracked,如果持续没检测到,则还保持lost状态,当lost的时间超过了一定的阈值后,状态切换为inactive,inactive状态下的目标会保持inactive直到视频结束。
    在这里插入图片描述
    Online Multi-Object Tracking via Structural Constraint Event Aggregation (2016,CVPR)
    该论文将目标跟踪中的匹配问题加入了结构约束,举个例子,前一帧如果检测到的目标连结起来呈现的是三角形,那么通过速度预测每个目标的位置,从而调整三角形的形态,并且认为后面的帧就是呈现这样的结构。如图9所示
    在这里插入图片描述
    Tracking The Untrackable: Learning to Track Multiple Cues with Long-Term Dependencies (2017, ICCV)
    该论文首次将深度学习加入到跟踪中,通过神经网络提取三种特征,外表特征、运动特征、交互特征,将三种特征连接到一起,再经过全连接层,得到相似度分数。相邻帧得到相似分数后,利用匈牙利匹配得到最大匹配。匈牙利匹配的概念见《带你入门多目标跟踪(三)匈牙利算法&KM算法》
    在这里插入图片描述
    Simple Online and Real-time Tracking with a D eep Association Metric
    这个系列有两个算法,sort和deep sort,这里先介绍sort。sort的思路很简单,首先通过检测器例如faster rcnn把每一帧的物体检测出来,之后通过卡尔曼滤波器预测物体在下一帧的位置,将预测的位置与下一帧实际检测到的位置做IOU的计算,得到相邻两帧物体的相似度,最后利用匈牙利匹配得到相邻帧的对应id。由于这里只是计算框的重叠面积,因此如果两个物体发生遮挡,会出现id交换的情况,所以作者为了降低id交换,提出了deep sort算法。deep sort之所以可以把id交换降低45%,是因为它将面积匹配修改为了特征匹配。在匹配之前作者利用resnet50先将特征里取出来,由于一般情况下很少会遇到外观特征完全相同的两个物体,因此这种改进是有效的。deep dort由于很简单,因此没有在顶会上发表成功,但是由于其可以保证在高速度的情况下的高准确度,所以广泛应用在了工程实践的过程中。相关的demo
    在这里插入图片描述
    Chained-Tracker: Chaining Paired Attentive Regression Results for End-to-End Joint Multiple-Object Detection and Tracking
    论文有两个贡献1)提出了一种链式跟踪算法,业内首创将相邻两帧输入网络,可以将目标检测、特征提取、数据关联三个模块集成到单个网络中,实现端到端联合检测跟踪。2)相邻帧检测框对回归。论文将数据关联问题转换为相邻帧中检测框对的回归问题。这两个贡献主要是针对现存的两个问题:1)算法不能端到端的优化。2)过度依赖于检测的质量

    在这里插入图片描述

    基准

    目前在MOT7数据集上所能达到的效果如下图所示。MOTbenchmark
    在这里插入图片描述
    参考:高旭 《多目标跟踪》

    展开全文
  • 多目标跟踪算法 | DeepSort

    万次阅读 2022-02-08 16:54:59
    前言 论文名称:(ICIP2017)Single-Simple Online and Realtime ...一、多目标跟踪的工作流程(常规) (1)给定视频的原始帧; (2)运行对象检测器以获得对象的边界框; (3)对于每个检测到的物体,计算出不同的特征.

    前言

    本文分享多目标跟踪算法的经典算法DeepSort,它是一个两阶段的算法,达到实时跟踪效果,曾被应用于工业开发。DeepSort是基于Sort目标跟踪进行的改进,它引入深度学习模型,在实时目标跟踪过程中,提取目标的外观特征进行最近邻近匹配。

    目的:改善有遮挡情况下的目标追踪效果;同时,也减少了目标ID跳变的问题。

    核心思想:使用递归的卡尔曼滤波和逐帧的匈牙利数据关联。

    论文名称:(ICIP2017Single-Simple Online and Realtime Tracking with a Deep Association Metric

    论文地址:https://arxiv.org/abs/1703.07402

    开源地址:https://github.com/nwojke/deep_sort

    目录

    一、通常的多目标跟踪工作流程

    二、前提知识:Sort 多目标跟踪

    三、DeepSort 多目标跟踪

    四、卡尔曼滤波器——跟踪场景定义

    4.1 卡尔曼滤波器——预测阶段

    4.2 卡尔曼滤波器——更新阶段

    五、匈牙利匹配——跟踪场景定义

    5.1、匈牙利匹配——马氏距离 关联 运动状态

    5.2、匈牙利匹配——余弦距离 关联 外观特征

    5.3、匈牙利匹配——相互补充

    六、级联匹配——跟踪场景

    七、IOU匹配——跟踪场景

    八、实验结果

    九、Deep Sort开源代码

    本文参考


    一、通常的多目标跟踪工作流程

    (1)给定视频的原始帧;

    (2)运行对象检测器以获得对象的边界框;

    (3)对于每个检测到的物体,计算出不同的特征,通常是视觉和运动特征;

    (4)之后,相似度计算步骤计算两个对象属于同一目标的概率;

    (5)最后,关联步骤为每个对象分配数字ID

    二、前提知识:Sort 多目标跟踪

    四个核心步骤

    1. 获取目标检测框,( 检测器: Faster R-CNN YOLO )。
    2. 卡尔曼滤波器预测当前位置 ,获得预测框。
    3. 进行相似度计算,计算 前面的帧和当前帧目标 之间的匹配程度。(只考虑运动信息)
    4. 通过匈牙利算法进行 数据关联,为每个对象分配目标的 ID

     它以“每个检测框”与“现有目标的所有预测框”之间的IOU作为前后帧之间目标关系的度量指标。

    算法核心

    • 卡尔曼滤波的预测和更新过程。
    • 匹配的过程。

    其中,卡尔曼滤波可以基于目标前面时刻的位置,来预测当前时刻的位置。匈牙利算法可以告诉我们当前帧的某个目标,是否与前面帧的某个目标相同。

    优点:Sort目标跟踪算法速度很快;在没有遮挡的情况下准确度很高。

    缺点:它对物体遮挡几乎没有处理,导致ID switch 次数很高;在有遮挡情况下,准确度很低。

    三、DeepSort 多目标跟踪

    背景:DeepSort是基于Sort目标跟踪进行的改进,它引入深度学习模型,在实时目标跟踪过程中,提取目标的外观特征进行最近邻近匹配。

    目的:改善有遮挡情况下的目标追踪效果;同时,也减少了目标ID跳变的问题。

    核心思想:使用递归的卡尔曼滤波和逐帧的匈牙利数据关联。

    四、卡尔曼滤波器——跟踪场景定义

     假定跟踪场景是定义在 8 维状态空间(u, v, γ, h, ẋ, ẏ, γ̇, ḣ)中, 边框中心(u, v),宽高比 γ,高度 h 和和它们各自在图像坐标系中的速度。

    这里依旧使用的是匀速运动模型,并把(uvγh)作为对象状态的直接观测量。

    在目标跟踪中,需要估计目标的以下两个状态:

    均值 (Mean) :包含目标的位置和速度信息,由 8 维向量( u, v, γ, h, ẋ, ẏ, γ̇, ḣ )表示,其中每个速度值初始化为 0 。均值 Mean 可以通过观测矩阵 H 投影到测量空间输出( u v γ h )。
    协方差 (Covariance) :表示估计状态的不确定性,由 8x8 的对角矩阵表示,矩阵中数字越大则表明不确定性越大。

    4.1 卡尔曼滤波器——预测阶段

    step1 :首先利用上一时刻 k-1 的后验估计值 ,通过 状态转移矩阵 F 变换,得到 当前时刻 k 的先验估计状态

    其中,状态转移矩阵 F如下:

     •step2:然后使用上一时刻 k-1 的后验估计协方差来计算当前时刻 k 的先验估计协方差

    通过上一时刻后验估计均值和方差 估计 当前时刻先验估计均值x和协方差P

    实现代码如下:

    def predict(self, mean, covariance):
        # mean, covariance 相当于上一时刻的后验估计均值和协方差
        
        std_pos = [
            self._std_weight_position * mean[3],
            self._std_weight_position * mean[3],
            1e-2,
            self._std_weight_position * mean[3]]
        std_vel = [
            self._std_weight_velocity * mean[3],
            self._std_weight_velocity * mean[3],
            1e-5,
            self._std_weight_velocity * mean[3]]
    
        # 初始化噪声矩阵 Q
        motion_cov = np.diag(np.square(np.r_[std_pos, std_vel]))
    
        # x' = Fx
        mean = np.dot(self._motion_mat, mean)
    
        # P' = FPF^T + Q
        covariance = np.linalg.multi_dot((
            self._motion_mat, covariance, self._motion_mat.T)) + motion_cov
        
        # 返回当前时刻的先验估计均值 x 和协方差 P
        return mean, covariance

    4.2 卡尔曼滤波器——更新阶段

    • step1:首先利用先验估计协方差矩阵 P 和观测矩阵 H 以及测量状态协方差矩阵 R 计算出卡尔曼增益矩阵 K

    • step2:然后将卡尔曼滤波器的先验估计值 x 通过观测矩阵 H 投影到测量空间,并计算出与测量值 z 的残差 y

    • step3:将卡尔曼滤波器的预测值和测量值按照卡尔曼增益的比例相融合,得到后验估计值 x

    • step4:计算出卡尔曼滤波器的后验估计协方差

     卡尔曼滤波器更新阶段,代码实现:

    def update(self, mean, covariance, measurement):
    
        # 将先验估计的均值和协方差映射到检测空间,得到 Hx' 和 HP'
        projected_mean, projected_cov = self.project(mean, covariance)
    
        chol_factor, lower = scipy.linalg.cho_factor(
            projected_cov, lower=True, check_finite=False)
    
        # 计算卡尔曼增益 K
        kalman_gain = scipy.linalg.cho_solve(
            (chol_factor, lower), np.dot(covariance, self._update_mat.T).T,
            check_finite=False).T
    
        # y = z - Hx'
        innovation = measurement - projected_mean
    
        # x = x' + Ky
        new_mean = mean + np.dot(innovation, kalman_gain.T)
    
        # P = (I - KH)P'
        new_covariance = covariance - np.linalg.multi_dot((
            kalman_gain, projected_cov, kalman_gain.T))
    
        # 返回当前时刻的后验估计均值 x 和协方差 P
        return new_mean, new_covariance

    总结一下:

     在目标跟踪中,需要估计目标的以下两个状态:

    均值 (Mean) :包含目标的位置和速度信息,由 8 维向量( u, v, γ, h, ẋ, ẏ, γ̇, ḣ )表示,其中每个速度值初始化为 0 。均值 Mean 可以通过观测矩阵 H 投影到测量空间输出( u v γ h )。
    协方差 (Covariance) :表示估计状态的不确定性,由 8x8 的对角矩阵表示,矩阵中数字越大则表明不确定性越大。

    predict 阶段和 update 阶段都是为了计算出卡尔曼滤波的估计均值 协方差 P,不同的是前者是基于上一历史状态做出的先验估计,而后者则是融合了测量值信息并作出校正的后验估计

    五、匈牙利匹配——跟踪场景定义

    解决卡尔曼滤波器的预测状态测量状态之间的关联,可以通过构建匈牙利匹配来实现。

    两个状态关联

    • 卡尔曼滤波器的预测状态,后验的结果
    • 测量状态,检测器的结果。

    两个指标来实现关联

    • 运动信息(用“马氏距离 来计算)
    • 外观特征(用“余弦距离 来计算

     最后,使用线性加权和,将两个指标结合起来。

    5.1、匈牙利匹配——马氏距离 关联 运动状态

    马氏距离又称为协方差距离,是一种有效计算两个未知样本集相似度的方法,度量预测检测的匹配程度。为了整合物体的运动信息,使用了预测状态和测量状态之间的(平方)马氏距离:

     其中,d y 分别代表测量分布和预测分布;S 为两个分布之间的协方差矩阵,它是一个实对称正定矩阵,可以使用 Cholesky 分解来求解马氏距离。

    作用:马氏距离通过计算“预测框”距离“检测框”有多远的偏差,来估计跟踪器状态的不确定性。

     是一个指示器,比较的是马氏距离和卡方分布的阈值,9.4877,如果马氏距离小于该阈值,代表成功匹配。

    注意:由于测量分布的维度(4 维)和预测分布的维度(8 维)不一致,因此需要先将预测分布通过观测矩阵 H 投影到测量空间中(这一步其实就是从 8 个估计状态变量中取出前 4 个测量状态变量。),代码实现:

    # Project state distribution to measurement space.
    def project(self, mean, covariance):
        std = [
            self._std_weight_position * mean[3],
            self._std_weight_position * mean[3],
            1e-1,
            self._std_weight_position * mean[3]]
    
        # 初始化测量状态的协方差矩阵 R
        innovation_cov = np.diag(np.square(std)) # 使用的是对角矩阵,不同维度之间没有关联
    
        # 将均值向量映射到检测空间 得到 Hx
        mean = np.dot(self._update_mat, mean)
    
        # 将协方差矩阵映射到检测空间,得到 HP'H^T
        covariance = np.linalg.multi_dot((
            self._update_mat, covariance, self._update_mat.T))
    
        return mean, covariance + innovation_cov # 加上测量噪声

    计算马氏距离,代码实现:

    # Compute gating distance between state distribution and measurements.
    def gating_distance(self, mean, covariance, measurements,
                        only_position=False):
    
        # 首先需要先将预测状态分布的均值和协方差投影到测量空间
        mean, covariance = self.project(mean, covariance)
    
        # 假如仅考虑中心位置
        if only_position:
            mean, covariance = mean[:2], covariance[:2, :2]
            measurements = measurements[:, :2]
    
        # 对协方差矩阵进行 cholesky 分解
        cholesky_factor = np.linalg.cholesky(covariance)
    
        # 计算两个分布之间对差值
        d = measurements - mean
    
        # 通过三角求解计算出马氏距离
        z = scipy.linalg.solve_triangular(
            cholesky_factor, d.T, lower=True, check_finite=False,
            overwrite_b=True)
    
        # 返回平方马氏距离
        squared_maha = np.sum(z * z, axis=0)
        return squared_maha

    5.2、匈牙利匹配——余弦距离 关联 外观特征

    背景:

    当物体运动状态的不确定性比较低时,使用马氏距离确实是一个不错的选择。由于卡尔曼滤波器使用的是匀速运动模型,它只能对物体的运动位置提供一个相对粗略的线性估计。当物体突然加速或减速时,跟踪器的预测框和检测框之间的距离就会变得比较远,这时仅使用马氏距离就会变得非常不准确

    设计:

    DeepSort 还对每个目标设计了一个深度外观特征描述符,它其实是一个在行人重识别数据集上离线训练的 ReID 网络提取到的 128 维单位特征向量(模长为 1 。对于每个追踪器 tracker,保留它最后 100 个与检测框关联成功的外观特征描述符集合 R 并计算出它们和检测框的最小余弦距离:

     然后,可以设置一个合适的阈值来排除那些外观特征相差特别大的匹配。

    ReID 网络:

    Deep Sort 采用了经过大规模人员重新识别数据集训练的 Cosine 深度特征网络,该数据集包含 1,261 位行人的 1,100,000 多张图像,使其非常适合在人员跟踪环境中进行深度度量学习。

    Cosine 深度特征网络使用了宽残差网络,该网络具有 2 个卷积层和 6 个残差块,L2 归一化层能够计算不同行人间的相似性,以与余弦外观度量兼容。通过计算行人间的余弦距离,余弦距离越小,两行人图像越相似。Cosine 深度特征网络结构如下图所示。

    使用 Cosine 深度特征网络参数,将每个检测框d_{j}内图片压缩为最能表征图片特异信息的128维向量,并归一化后得到外观描述向量。

     这里轨迹使用外观特征向量库保存近期匹配成功的外观特征向量,并在匹配时去余弦距离中最小距离可以适应短时遮挡情况。比如:当前被遮挡,则使用以往外观信息判别,只要进30帧中有出现过较好的匹配,则匹配上该轨迹和检测,较好地减少了遮挡问题。

    余弦距离关联外观特征 具体展开:

    使用余弦距离来度量表观特征之间的距离,reid模型抽出得到一个128维的向量,使用余弦距离来进行比对:

      是余弦相似度,而余弦距离=1-余弦相似度,通过余弦距离来度量卡尔曼预测的表观特征和检测器对应的表观特征,来更加准确地预测IDSORT中仅仅用运动信息进行匹配会导致ID Switch比较严重,引入外观模型+级联匹配可以缓解这个问题。

     同上,余弦距离这部分也使用了一个指示器,如果余弦距离小于,则认为匹配上。这个阈值在代码中被设置为0.2(由参数max_dist控制),这个属于超参数,在人脸识别中一般设置为0.6

    5.3、匈牙利匹配——相互补充

    两个指标可以互相补充从而解决关联匹配的不同问题:

    一方面,马氏距离基于运动可以提供有关可能的物体位置的信息,这对于短期预测特别有用;

    另一方面,当运动的判别力较弱时,余弦距离会考虑外观信息,这对于长时间遮挡后恢复身份特别有用

    为了建立关联问题,我们使用加权和将两个指标结合起来:

     可以通过超参数 λ 来控制每个指标对合并成本的影响。在论文的实验过程中,发现当摄像机运动较大时,将 λ=0 是合理的选择(此时仅用到了外观信息)。

    六、级联匹配——跟踪场景

     当物体被长时间遮挡时,卡尔曼滤波器不能对目标状态准确预测。因此,概率质量在状态空间中散布,并且观察似然性的峰值降低。但是,当两个轨迹竞争同一检测结果时,马氏距离会带来较大的不确定性。因为它有效地减少了任何检测的标准偏差与投影轨迹均值之间的距离,而且可能导致轨迹碎片化增加和不稳定的轨迹。因此,Deep Sort引入了级联匹配,来更加频繁出现的目标赋予优先权,具体算法伪代码如下:

    在级联匹配的花费矩阵里,元素值为马氏距离和余弦距离的加权和。实现代码:

    def matching_cascade(
            distance_metric, max_distance, cascade_depth, tracks, detections,
            track_indices=None, detection_indices=None):
    
        if track_indices is None:
            track_indices = list(range(len(tracks)))
        if detection_indices is None:
            detection_indices = list(range(len(detections)))
    
        unmatched_detections = detection_indices
        matches = []
    
        # 遍历不同年龄
        for level in range(cascade_depth):
            if len(unmatched_detections) == 0:  # No detections left
                break
    
            # 挑选出对应年龄的跟踪器
            track_indices_l = [
                k for k in track_indices
                if tracks[k].time_since_update == 1 + level
            ]
            if len(track_indices_l) == 0:  # Nothing to match at this level
                continue
    
            # 将跟踪器和尚未匹配的检测框进行匹配
            matches_l, _, unmatched_detections = \
                min_cost_matching(
                    distance_metric, max_distance, tracks, detections,
                    track_indices_l, unmatched_detections)
            matches += matches_l
    
        # 挑选出未匹配的跟踪器
        unmatched_tracks = list(set(track_indices) - set(k for k, _ in matches))
        return matches, unmatched_tracks, unmatched_detections

    该匹配的精髓在于:挑选出所有 confirmed tracks,优先让那些年龄较小的 tracks 和未匹配的检测框相匹配,然后才轮得上那些年龄较大的 tracks

    这就使得在相同的外观特征和马氏距离的情况下,年龄较小的跟踪器更容易匹配上。至于年龄 age 的定义,跟踪器每次 predict 时则 age + 1

    七、IOU匹配——跟踪场景

    这个阶段是发生在级联匹配之后,匹配的跟踪器对象为那些 unconfirmed tracks 以及上一轮级联匹配失败中 age 1 tracks. 这有助于解决因上一帧部分遮挡而引起的突然出现的外观变化,从而减少被遗漏的概率。

    # 从所有的跟踪器里挑选出 unconfirmed tracks
    unconfirmed_tracks = [
        i for i, t in enumerate(self.tracks) if not t.is_confirmed()]
    
    # 从上一轮级联匹配失败的跟踪器中挑选出连续 1 帧没有匹配上(相当于age=1)
    # 的跟踪器,并和 unconfirmed_tracks 相加
    iou_track_candidates = unconfirmed_tracks + [
        k for k in unmatched_tracks_a if
        self.tracks[k].time_since_update == 1]
    
    # 将它们与剩下没匹配上的 detections 进行 IOU 匹配
    matches_b, unmatched_tracks_b, unmatched_detections = \
        linear_assignment.min_cost_matching(
            iou_matching.iou_cost, self.max_iou_distance, self.tracks,
            detections, iou_track_candidates, unmatched_detections)

    八、实验结果

    • 选用MOTA、MOTP、MT、ML、FN、ID swiches、FM等指标进行评估模型。
    • 相比SORT, Deep SORT的ID Switch指标下降了45%,达到了当时的SOTA。经过实验,发现Deep SORT的MOTA、MOTP、MT、ML、FN指标对于之前都有提升。
    • FP很多,主要是由于Detection和Max age过大导致的。
    • 速度达到了20Hz,其中一半时间都花费在表观特征提取。

    九、Deep Sort开源代码

     基于YOLO的Deep-Sort算法,网络上有不同版本的开源代码,下面三个分别是基于YOLOv5、YOLOv4、YOLOv3 实现的Deep Sort 多目标跟踪系统。

    【1】YOLOv5+Pytorch+Deep Sort

    开源代码地址:Yolov5_DeepSort_Pytorch 

    YOLOv5生成的检测结果是一系列在 COCO 数据集上预训练的对象检测架构和模型,被传递到Deep Sort多目标跟踪对象算法。

    开发环境:

    matplotlib>=3.2.2
    numpy>=1.18.5
    opencv-python>=4.1.2
    Pillow
    PyYAML>=5.3.1
    scipy>=1.4.1
    torch>=1.7.0
    torchvision>=0.8.1
    tqdm>=4.41.0
    seaborn>=0.11.0
    pandas
    easydict

    模型效果:

     【2】YOLOv4+TF+Deep Sort

    开源代码地址:Deep-SORT-YOLOv4-tf

    开发环境:

    # $ conda create --name <env> --file <this file>
    # platform: linux-64
    imutils=0.5.3=pypi_0
    keras=2.3.1=pypi_0
    matplotlib=3.2.1=pypi_0
    numpy=1.18.4=pypi_0
    opencv-python=4.2.0.34=pypi_0
    pillow=7.1.2=pypi_0
    python=3.6.10=h7579374_2
    scikit-learn=0.23.1=pypi_0
    scipy=1.4.1=pypi_0
    tensorboard=2.2.1=pypi_0
    tensorflow=2.0.0=pypi_0
    tensorflow-estimator=2.1.0=pypi_0
    tensorflow-gpu=2.2.0=pypi_0

    模型效果:

     【3】YOLOv3+Pytorch+Deep Sort

    开源代码地址:Deep-Sort_pytorch-yolov3

    开发环境:

    python 3 (python2 not sure)
    numpy
    scipy
    opencv-python
    sklearn
    torch >= 0.4
    torchvision >= 0.1
    pillow
    vizer
    edict

    模型效果:

    本文参考

    [1] 包俊,董亚超,刘宏哲.基于Deep_Sort的目标跟踪算法综述.北京联合大学北京市信息服务工程重点实验室.

    [2] 朱镇坤,戴德云,王纪凯,陈宗海.基于FasterR_CNN的多目标跟踪算法设计.中国科学技术大学自动化系.

    [3] 谢佳形.拥挤场景下视频多目标跟踪算法研究.浙江大学.

    [4] 谷燕飞.基于改进YOLO_V3+Deepsort多目标跟踪系统的研究与实现.辽宁大学.

     网络文章参考:

    参考1:https://zhuanlan.zhihu.com/p/97449724

    参考2:https://yunyang1994.gitee.io/2021/08/27/DeepSort-%E5%A4%9A%E7%9B%AE%E6%A0%87%E8%B7%9F%E8%B8%AA%E7%AE%97%E6%B3%95-SORT-%E7%9A%84%E8%BF%9B%E9%98%B6%E7%89%88/

    参考3:https://mp.weixin.qq.com/s?__biz=MzA4MjY4NTk0NQ==&mid=2247485748&idx=1&sn=eb0344e1fd47e627e3349e1b0c1b8ada&chksm=9f80b3a2a8f73ab4dd043a6947e66d0f95b2b913cdfcc620cfa5b995958efe1bb1ba23e60100&scene=126&sessionid=1587264986&key=1392818bdbc0aa1829bb274560d74860b77843df4c0179a2cede3a831ed1c279c4603661ecb8b761c481eecb80e5232d46768e615d1e6c664b4b3ff741a8492de87f9fab89805974de8b13329daee020&ascene=1&uin=NTA4OTc5NTky&devicetype=Windows+10+x64&version=62090069&lang=zh_CN&exportkey=AeR8oQO0h9Dr%2FAVfL6g0VGE%3D&pass_ticket=R0d5J%2BVWKbvqy93YqUC%2BtoKE9cFI22uY90G3JYLOU0LtrcYM2WzBJL2OxnAh0vLo

    参考4:https://zhuanlan.zhihu.com/p/80764724

    论文地址:https://arxiv.org/abs/1703.07402

    开源地址:https://github.com/nwojke/deep_sort

    本文只供大家参考学习,谢谢。如有错误,欢迎指出~

    展开全文
  • 多目标跟踪c++代码

    2019-01-16 02:58:30
    代码使用vs2010 + opencv2.2开发,可以检测目标跟踪多目标
  • 这是一个基于粒子滤波的视频目标跟踪的matlab仿真程序,为了方便大家的使用,还特地在文件中附加了一组从视频中提取的仿真图片,需要注意的是,在tracker.m主程序中,读取图片的路径需要改成你存放图片的路径,只要...
  • Staple综合了局部特征HOG和全局特征颜色直方图用于目标跟踪算法。此测试已经在win与ubuntu以及ros环境下完成,运行正常。

    一、介绍

    Staple综合了局部特征HOG和全局特征颜色直方图用于目标跟踪的算法。

    首先作者发现颜色分布不足以将目标和背景区分开来。局部特征这样的模板在应对剧烈形变的时候效果往往很差。

    作者针对这两个问题做了一些相关工作得到以下结论。

    1. 卷积滤波器对剧烈形变不鲁棒。
    2. 在线学习可能会带来模型漂移,也就是算法是将预测作为正样本来训练,更新模型。如果一旦预测不对,后面也跟着错。
    3. 颜色直方图是不考虑像素位置的,这在一定程度上可以减少形变的影响。
    4. 相关滤波CF的鲁棒性比较强,在目标颜色和背景颜色区分力度不够时可以发挥作用。

    因此作者结合了这些实现目标跟踪。

    二、理论方法

    2.1 总体方法

    p t = a r g m a x p ∈ S t f ( T ( x t , p ) ; θ t − 1 ) p_t=argmax_{p{\in}S_t} f(T(x_t,p);{\theta}_{t-1}) pt=argmaxpStf(T(xt,p);θt1)

    对于 t t t帧,可以通过矩形 p t p_t pt在图像 x t x_t xt中选择一个目标,并令得分函数的值最大。
    f f f是矩形窗口 p p p的得分函数,得分函数 T T T是一种图像变换, θ \theta θ是模型参数)

    θ t = a r g m i n θ ∈ Q { L ( θ ; X t + λ R ( θ ) } \theta_t=argmin_{\theta \in Q}\{L(\theta;X_t+\lambda R(\theta)\} θt=argminθQ{L(θ;Xt+λR(θ)}

    X t = { ( x i , p i ) } i = 1 t X_t=\{(x_i,p_i)\}^t_{i=1} Xt={(xi,pi)}i=1t

    可以取一组 θ \theta θ使得整个损失函数最小。
    L L L是和前面帧的目标位置有关的函数, R R R是正则项)

    2.2 得分函数

    f ( x ) = γ t m p l f t m p l ( x ) + γ h i s t f h i s t ( x ) f(x)={\gamma}_{tmpl}f_{tmpl}(x)+{\gamma}_{hist}f_{hist}(x) f(x)=γtmplftmpl(x)+γhistfhist(x)

    f t m p l ( x ; h ) = ∑ u ∈ τ h [ u ] T ϕ x [ u ] f_{tmpl}(x;h)=\sum_{u\in{\tau}}h[u]^T\phi_x[u] ftmpl(x;h)=uτh[u]Tϕx[u]

    ϕ x : τ → R K \phi_x:\tau\rightarrow\mathbb{R}^K ϕx:τRK
    τ : ⊂ Z 2 \tau:\subset\mathbb{Z}^2 τ:Z2

    f函数是由两项组成,一项是模板的得分,第二项是直方图得分。这个公式代表,假设一张图像x用 Z 2 Z^2 Z2表示

    三、论文笔记

    STAPLE目标跟踪算法结合了HOG特征和颜色直方图两种方法。由于HOG特征对运动模糊和照度较为鲁棒,但是对形变不够鲁棒,而相对应的颜色直方图对形变非常鲁棒,对光照变化不够鲁棒。因此两种方法可以互补,故同时使用这两种方法,分为两个通道进行处理。

    该算法在第一帧使用矩形框指定目标,然后在视频中跟踪一个不熟悉的物体并对其外观的变化保持鲁棒性。由于一个物体的外观在视频中可能会出现很大变化,因此只从使用第一帧计算的模型估算其他帧不会很有效,通常的做法是将跟踪帧中的预测作为训练数据更新模型。在每一帧图像中搜索目标位置时,考虑先将图像的各个旋转中进行搜索,然后再在比例放缩中进行搜索。

    四、代码测试

    论文作者使用MATLAB实现这个算法。而本人使用的是Github上的大神xuduo35以C++实现的版本,原Github项目链接如下:

    论文源代码(MATLAB):
    https://github.com/bertinetto/staple
    xuduo35(C++):
    https://github.com/xuduo35/STAPLE

    本文参考xuduo34的代码,调用了该项目中fhog.cppfhog.hsse.hppstaple_tracker.cppstaple_tracker.hpp文件,下面只放出main函数代码。

    int main(int argc, char * argv[]){
        // 数据定义
        STAPLE_TRACKER staple;  //创建staple跟踪对象
        std::vector<cv::Rect_<float>> result_rects;     //创建矩形容器,存储所有算法识别出的跟踪框
        cv::VideoCapture capture(0);	//创建VideoCapture类
        cv::Mat image;      //用来存储每一帧
        cv::Mat tempImage;  //每一帧的临时变量
        int64 tic, toc;     //算法运行时间起始点与终止点
        double time = 0;
        bool show_visualization = true;
        bool first_image = true;
    
        // 设置鼠标操作回调函数
        cv::namedWindow("STAPLE");
        cv::setMouseCallback("STAPLE", on_MouseHandle, (void*)&image);
    
        while(1){
            capture.read(image);	//逐帧读取视频
            flip(image, image, 1);	//将读取的视频左右反转
            if (image.empty()) {	//如果视频结束或未检测到摄像头则跳出循环
                break;
            }
    
            if(drawing_finished == false){
                // 鼠标按下drawing_box=true,在视频画面frame上画矩形
                if( drawing_box ){
                    tempImage.copyTo(image);
                    cv::rectangle(image,groundtruth_rect.tl(),groundtruth_rect.br(),cv::Scalar(0,0,255));// 画框
                }
                else{
                    image.copyTo(tempImage);//拷贝源图到临时变量
                }
            }
            else{
                // 如果是第一帧图像,则进行staple初始化操作,反之则只更新staple
                if (first_image){
                    // staple初始化操作
                    staple.tracker_staple_initialize(image, groundtruth_rect);
                    // staple目标追踪
                    staple.tracker_staple_train(image, true);
                    first_image = false;
                } else{
                    groundtruth_rect = staple.tracker_staple_update(image);
                    staple.tracker_staple_train(image, false);
                }
            }
            // 可视化部分
            if (show_visualization) {
                // 显示算法识别的跟踪框
                cv::rectangle(image, groundtruth_rect, cv::Scalar(0, 128, 255), 2);
    
                // 写入测试视频
                // ******************** //
                // video.write(image);
                // ******************** //
    
                // 输出图像显示结果
                cv::imshow("STAPLE", image);
                std::cout << "Center: [" << groundtruth_rect.tl().x +groundtruth_rect.width/2 << ", " << groundtruth_rect.tl().y + groundtruth_rect.height/2 << "]" << std::endl;
    
                char key = cv::waitKey(10);
                if (key == 27 || key == 'q' || key == 'Q')
                    break;
            }
    
    
        }
        cv::destroyAllWindows();
    
    }
    
    
    /******************** 函数定义 ********************/
    // 使轴对齐
    cv::Rect_<float> getAxisAlignedBB(std::vector<cv::Point2f> polygon)
    {
        double cx = double(polygon[0].x + polygon[1].x + polygon[2].x + polygon[3].x) / 4.;
        double cy = double(polygon[0].y + polygon[1].y + polygon[2].y + polygon[3].y) / 4.;
        double x1 = std::min(std::min(std::min(polygon[0].x, polygon[1].x), polygon[2].x), polygon[3].x);
        double x2 = std::max(std::max(std::max(polygon[0].x, polygon[1].x), polygon[2].x), polygon[3].x);
        double y1 = std::min(std::min(std::min(polygon[0].y, polygon[1].y), polygon[2].y), polygon[3].y);
        double y2 = std::max(std::max(std::max(polygon[0].y, polygon[1].y), polygon[2].y), polygon[3].y);
        double A1 = norm(polygon[1] - polygon[2])*norm(polygon[2] - polygon[3]);
        double A2 = (x2 - x1) * (y2 - y1);
        double s = sqrt(A1 / A2);
        double w = s * (x2 - x1) + 1;
        double h = s * (y2 - y1) + 1;
        cv::Rect_<float> rect(cx-1-w/2.0, cy-1-h/2.0, w, h);
        return rect;
    
    }
    // 获取groundtruth内的矩形坐标
    std::vector<cv::Rect_<float>> getgroundtruth(std::string txt_file)
    {
        std::vector<cv::Rect_<float>> rects;
        std::ifstream gt;
        gt.open(txt_file.c_str());
        if (!gt.is_open())
            std::cout << "Ground truth file " << txt_file
                      << " can not be read" << std::endl;
        std::string line;
        float x1, y1, x2, y2, x3, y3, x4, y4;
        while (getline(gt, line)) {
            std::replace(line.begin(), line.end(), ',', ' ');
            std::stringstream ss;
            ss.str(line);
            ss >> x1 >> y1 >> x2 >> y2 >> x3 >> y3 >> x4 >> y4;
            std::vector<cv::Point2f>polygon;
            polygon.push_back(cv::Point2f(x1, y1));
            polygon.push_back(cv::Point2f(x2, y2));
            polygon.push_back(cv::Point2f(x3, y3));
            polygon.push_back(cv::Point2f(x4, y4));
            rects.push_back(getAxisAlignedBB(polygon)); //0-index
        }
        gt.close();
        return rects;
    }
    // 第一帧画框鼠标响应
    void on_MouseHandle(int event, int x, int y, int flags, void* param ){
        cv::Mat& image = *(cv::Mat*) param;
        switch( event)
        {
            //鼠标移动消息
            case cv::EVENT_MOUSEMOVE:
            {
                if( drawing_box )//如果是否进行绘制的标识符为真,则记录下长和宽到RECT型变量中
                {
                    groundtruth_rect.width = x-groundtruth_rect.x;
                    groundtruth_rect.height = y-groundtruth_rect.y;
                }
            }
                break;
    
                //左键按下消息
            case cv::EVENT_LBUTTONDOWN:
            {
                drawing_box = true;
                groundtruth_rect = cv::Rect( x, y, 0, 0 );//记录起始点
            }
                break;
    
                //左键抬起消息
            case cv::EVENT_LBUTTONUP:
            {
                drawing_box = false;//置标识符为false
                drawing_finished = true;
                //对宽和高小于0的处理
                if( groundtruth_rect.width < 0 )
                {
                    groundtruth_rect.x += groundtruth_rect.width;
                    groundtruth_rect.width *= -1;
                }
    
                if( groundtruth_rect.height < 0 )
                {
                    groundtruth_rect.y += groundtruth_rect.height;
                    groundtruth_rect.height *= -1;
                }
                //调用函数进行绘制
                cv::rectangle(image,groundtruth_rect.tl(),groundtruth_rect.br(),cv::Scalar(0,0,255));// 画框
            }
                break;
        }
    }
    

    下图为在Staple目标跟踪程序的基础上改编,与Realsense D435i相机的深度图结合的测试程序。

    因为是毕设完整代码就不放出来了,大家可以根据自己需求,在xuduo C++版本代码的基础上修改。

    本博客文章首先发布于个人博客:https://www.mahaofei.com/,欢迎大家访问。

    展开全文
  • 目标跟踪传统算法KCF C++代码带有结果和检测视频
  • 一、多目标跟踪 MOT16 数据集介绍及评价指标 1.多目标跟踪 多目标跟踪处理的对象是视频,从视频的第一帧到最后一帧,里边有个目标在不断运动。目标跟 踪的目的就是将每个目标和其他目标进行区分开来,具体方法是...
  • 利用粒子滤波算法进行的目标跟踪代码,对学习目标跟踪的同学有所帮助
  • C-COT)相关滤波目标跟踪C-COT代码(matlab版本)
  • CSK目标跟踪算法理解与代码运行

    千次阅读 2020-08-23 19:24:18
    源代码本身加载数据集需要MIL格式,改了一点点东西,可以用OTB50,OTB100等数据集,参考:https://blog.csdn.net/qq_17783559/article/details/82080131 文章作者提供的下载地址:http://www.robots.ox.ac.uk/~joao/...
  • 视频追踪ECO算法源代码以及ECO论文PDF
  • 基于Meanshift的单目标跟踪算法【matlab+c两个版本】

    千次下载 热门讨论 2014-06-12 16:49:26
    基于meanshift的单目标跟踪算法实现 说明: 1. RGB颜色空间刨分,采用16*16*16的直方图 2. 目标模型和候选模型的概率密度计算公式参照上文 3. opencv版本运行:按P停止,截取目标,再按P,进行单目标跟踪 4. Matlab...
  • 动态背景下目标跟踪算法目标跟踪

    千次阅读 2021-03-24 14:12:19
    动态背景下目标跟踪算法目标跟踪 2.部分程序: % Programming By ALireza Fasih % Email: ar_fasih@yahoo.com % Please copy images (*.ppm) to work directory, then push F5 to view results. clc; % clear ...
  • 多目标跟踪(SORT,Deep_SORT,IOU17,SST)代码,亲身测试在MOT17上运行成功,需要准备相应的数据集及标签
  • 目标跟踪:直接调用opencv中封装的tracker即可。#!/usr/bin/env python3# -*- coding: utf-8 -*-"""Created on Sun Jan 5 17:50:47 2020第四章 kcf跟踪@author: youxinlin"""import cv2from items import ...
  • 匈牙利算法 卡尔曼滤波器多目标跟踪器实现
  • DeepSORT多目标跟踪算法

    千次阅读 多人点赞 2020-03-26 12:06:13
    DeepSORT算法理解及实现。
  • 话不说,承接上一篇《多目标跟踪算法,零基础极速入门(一)》 五、DeepSORT 论文解析 Deep SORT 论文核心内容,包括状态估计、匹配方法、级联匹配、表观模型等核心内容。 1. 简介 Simple Online and Realtim
  • sort目标跟踪算法

    2022-05-22 16:23:41
    sort目标跟踪算法 sort代码 匈牙利算法 卡尔曼滤波
  • yolo结合多目标跟踪算法实现检测和跟踪效果

    千次阅读 热门讨论 2019-10-17 11:30:40
    代码如下: import os import yolov3 import cv2 import numpy as np import threading from timeit import default_timer as timer def detect_camera(videoPath=None, loop=None, output_path="", trackingAlt=...
  • 冯如杯目标跟踪,将ECO算法转换为C语言版本 二、Guideline 1,完整读一遍代码,勾勒出算法框架 2,分工:feature extraction部分和implemention部分。后面implemention部分比较复杂,可以找两个人来读和写。 3,找...
  • 目录 目标跟踪关联匹配算法目标跟踪关联匹配算法(匈牙利算法和KM算法原理讲解和代码实现)0、多目标跟踪算法流程1、卡尔曼滤波1.1 预测1.2 更新1.3 gating_distance2、匈牙利算法原理 0、多目标跟踪算法流程 1...
  • 【滤波与目标跟踪-公开代码1】面向假设的假设目标跟踪算法-Python3.X实现前言1. tracker.py1.1 _normalize_log_sum(items)1.2 LocalHypothesis类1.2.1 id()1.2.2target()1.2.3 density()1.2.4 predict(t_now)1.2.5...
  • 最强的目标跟踪算法,比最火的孪生网络算法,在主流的各个数据集,比如VOT系列数据集,TBO系列数据集等等,表现都很SATA(先进)。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 58,759
精华内容 23,503
关键字:

多目标跟踪算法c代码