多目标跟踪-DeepSort分析(一)论文解读及代码架构

2023-05-16

先引入多目标跟踪DeepSort的论文地址及代码链接(Python版):

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

代码链接:https://github.com/nwojke/deep_sort

写在前面:

    这些天看了deepsort的论文及源码,并在网上检索一些相关资料(不是很多),现结合论文、博客及自己的理解进行总结。
    本文为第一篇,首先对论文进行解读,然后对github的代码进行简要的流程分析及解读,后期还会对所用算法进行具体的展开。
    
    本文结构:
        一、论文重点部分解读
        二、代码流程及算法分析

1. 论文重点部分解读

1.1. 轨迹处理及状态估计(track handing and state estimation)

第i时刻的状态用8维状态空间表示:
1
其中,u,v表示目标框的中心坐标;
γ,h(第三和第四个值)表示宽高比(宽高比应该为一个常量)、高度;
以上四个值构成观测变量。
以及图像坐标系下的速度(导数)

对于每条轨迹 k 都有一个阈值a用于记录轨迹从上一次成功匹配到当前时刻的时间。当该值大于提前设置的阈值 Amax 则认为改轨迹终止,直观上说就是长时间匹配不上的轨迹认为已经结束。
轨迹的三种状态:(在代码中定义为枚举变量)
tentative(初始默认状态)
confirmed
deleted

enum TrackState
{
     Tentative = 1
     Confirmed = 2
     Deleted = 3
}

在匹配时,对于没有匹配成功的检测都认为可能产生新的轨迹。但由于这些检测结果可能是一些错误警告,所以:
对这种新生成的轨迹标注状态 tentative (初始默认状态);
然后判定在接下来的连续3帧中是否连续匹配成功,若成功,则标注为 confirmed ,认为是新轨迹产生;
否则,标注为 deleted,删除 。另外,超过预先设置的Amax = 30 的轨迹,也被认为离开场景,并标注为 deleted,删除 。

        if self.state == TrackState.Tentative:
            self.state = TrackState.Deleted
        elif self.time_since_update > self._max_age:
            self.state = TrackState.Deleted

1.2分配(匹配)问题(assignment problem)

这里的匹配,是只当前被标注为“ confirmed ”的轨迹(即有效轨迹)与当前的检测之间的匹配。
使用匈牙利算法进行目标框的匹配;
使用运动匹配和外观匹配对目标框进行匹配。

1.2.1运动匹配

用Mahalanobis距离(马氏距离)来表示第j个检测和第i条轨迹之间的运动匹配程度。公式如下图所示:
1
其中,
dj表示第j个检测的状态;
yi是轨迹在当前时刻的预测值;
si是轨迹,由kalman滤波器预测得到的;
通过该马氏距离对检测框进行筛选,使用卡方分布的0.95分位点作为阈值。

1.2.2外观匹配

在实际中,比如相机运动,都会导致马氏距离匹配失效,因此引入余弦距离(第i次跟踪和第j次检测的最小余弦距离)来进行外观匹配,该匹配对长时间遮挡后恢复尤其有用,公式如下:
1

最后,利用加权的方式对这两个距离进行融合。关联度量的总公式如下所示:
1
其中,λ设置为0(论文中)。

1.3级联匹配(matching cascade)

 //# Run matching cascade.
 typedef std::vector<int> IDS;
 
 struct RR
{
    std::vector<std::pair<int, int>> matches;
    IDS unmatched_detections; 
    IDS unmatched_tracks;
};
 RR _match(const std::vector<Detection> &detections)
    {
        int64_t mtm1 = line_gtm();
        //Split track set into confirmed and unconfirmed kalmanTrackers.
        IDS confirmed_trackIds;
        IDS unconfirmed_trackIds;
        for (int i = 0; i < kalmanTrackers_.size(); i++)
        {
            KalmanTracker t = kalmanTrackers_[i];
            if (t->is_confirmed())
            {
                confirmed_trackIds.push_back(i);
            }
            else
            {
                unconfirmed_trackIds.push_back(i);
            }
        }

        //# Associate confirmed kalmanTrackers using appearance features.
        RR rr = linear_assignment::matching_cascade(
            getCostMatrixByNND,
            NearestNeighborDistanceMetric::Instance()->matching_threshold(),
            max_age_,
            kalmanTrackers_,
            detections,
            &confirmed_trackIds);
        std::vector<std::pair<int, int>> matches_a = rr.matches;
        IDS unmatched_tracks_a = rr.unmatched_tracks;
        IDS unmatched_detections = rr.unmatched_detections;

        int64_t mtm2 = line_gtm();

        //# Associate remaining kalmanTrackers together with unconfirmed kalmanTrackers using IOU.
        IDS iou_track_candidateIds, tmp;
        std::copy(unconfirmed_trackIds.begin(),
                  unconfirmed_trackIds.end(),
                  std::back_inserter(iou_track_candidateIds));
        for (int k = 0; k < unmatched_tracks_a.size(); k++)
        {
            int id = unmatched_tracks_a[k];
            if (kalmanTrackers_[id]->time_since_update_ == 1)
            {
                iou_track_candidateIds.push_back(id);
            }
            else
            {
                tmp.push_back(id);
            }
        }
        unmatched_tracks_a.clear();
        unmatched_tracks_a = tmp;

        int64_t mtm3 = line_gtm();
        
        RR rr1 = linear_assignment::min_cost_matching(
            iou_matching::getCostMatrixByIOU,
            max_iou_distance_,
            kalmanTrackers_,
            detections,
            &iou_track_candidateIds,
            &unmatched_detections);
        std::vector<std::pair<int, int>> matches_b = rr1.matches;
        IDS unmatched_tracks_b = rr1.unmatched_tracks;
        unmatched_detections = rr1.unmatched_detections;

        int64_t mtm4 = line_gtm();
        
        RR re;
        re.matches = matches_a;
        std::copy(matches_b.begin(), matches_b.end(),
                  std::back_inserter(re.matches));
        re.unmatched_detections = unmatched_detections;
        re.unmatched_tracks = unmatched_tracks_a;
        std::copy(unmatched_tracks_b.begin(),
                  unmatched_tracks_b.end(),
                  std::back_inserter(re.unmatched_tracks));
        int64_t mtm5 = line_gtm();
        return re;
    }

    int _NewTrack(const Detection &detection)
    {
        int id = _next_id_;
        std::pair<MEAN, VAR> pa =
            KF::Instance()->initiate(detection.to_xyah());
        KalmanTracker newt(new KalmanTrackerN(
            pa.first, pa.second, _next_id_, n_init_, max_age_,
            detection.feature_, true, detection.oriPos_));
        kalmanTrackers_.push_back(newt); 
        _next_id_ += 1;
        return id;
    }
};
RR rr = this->_match(detections);

当一个目标被遮挡很长时间,Kalman滤波的不确定性就会大大增加,为了解决该问题 ,论文采用级联匹配的策略来提高匹配精度。文中算法如下图所示:
1
其中,T表示目标跟踪集合
D表示目标检测集合
C矩阵存放所有目标跟踪与目标检测之间距离的计算结果
B矩阵存放所有目标跟踪与目标检测之间是否关联的判断(0或者1)
M,U为返回值,分别表示匹配集合和非匹配集合。

1.4深度表观特征(deep appearance descriptor)

论文中,作者用一个深度卷积神经网络去提取目标的特征信息,论文中的预训练的网络是在一个ReID的大数据集上训练得到的,包含1261个人的1100000幅图像,非常适合对人物目标跟踪。
网络结构如下:
CNN
该网络有2,800,864参数和32个目标框,在NVIDIA GTX1050上需要30ms。

2.代码流程及算法分析(待补充)

2.1detection

检测基类。

2.2HungarianOper

匈牙利指派,采用的是匈牙利算法/Hungrain/带权重的二分图指派算法Munkres Alogrithm。

2.3iou_matching

IOU匹配模块。(Iou–重叠区域面积)

2.4kalman_filter

卡尔曼滤波器,该模块实现图像空间的目标状态的预测/创建及移除,即滤波的具体参数化。

2.5linear_assignment

线性匹配–用最小的cost-matirx匹配级联。考虑了运动信息和外观信息。

for (int row = 0; row < track_indices.size(); row++)
        {
            int track_idx = track_indices[row];
            KalmanTracker track = tracks[track_idx];
 //计算detection中边框 dj(u,v,r,h)dj​(u,v,r,h)和Track中的边框 yiyi​之间的马氏距离
//计算 predicted Kalman states 和newly arrived measurements之间的马氏距离
Eigen::Matrix<float, 1, -1> gating_distance = kalmanFilter.gating_distance(
              track->mean_, track->covariance_, measurements, only_position);
          for (int i = 0; i < gating_distance.cols(); i++)
          // gating_distance is a vector
          {
              if (gating_distance(0, i) > gating_threshold)
              {
                  cost_matrix(row, i) = gated_cost;
              }
          }
      }
      return cost_matrix;

2.6nn_matching

最近邻匹配模块。

2.7tracker

目标跟踪。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多目标跟踪-DeepSort分析(一)论文解读及代码架构 的相关文章

随机推荐

  • uint8_t / uint16_t / uint32_t /uint64_t数据类型详解

    https blog csdn net bruce 0712 article details 72805903
  • 什么是系统调用?为什么要用系统调用?

    什么是系统调用 Linux内核中设置了一组用于实现各种系统功能的子程序 xff0c 称为系统调用 用户可以通过系统调用命令在自己的应用程序中调用它们 从某种角度来看 xff0c 系统调用和普通的函数调用非常相似 区别仅仅在于 xff0c 系
  • android的surfaceflinger原理学习

    概念 SurfaceFlinger是一个系统服务 xff0c 如 xff1a audioflinger xff0c audiopolicyservice等等 xff0c 系统的主要服务通过这个文章进行了解 xff0c Android的系统服
  • labview界面分隔和自定义窗口大小

    gt gt gt gt gt gt 我的博客目录导航 转自 statemic LabVIEW程序界面的布局 控件的显示效果与监视器是密切相关的 xff0c 因此在程序设计时需要考虑目标监视器的颜色 分辨率等因素 xff0c 并明确运行该应用
  • CAN通信矩阵的理解(CAN报文信号的属性)

    CAN通信矩阵 1 CAN通信矩阵是什么 CAN通信矩阵 xff08 CAN Communication Matrix xff09 通常由整车厂完成定义 xff0c 车辆网络中的各个节点需要遵循该通讯矩阵才能完成信息的交互和共享 我们知道C
  • Android OMX介绍(总括)

    一 OpenMax简介 xff08 缩写为 xff1a OMX xff09 OpenMAX是一个多媒体应用程序的标准 由NVIDIA公司和Khronos 在2006年推出 它是无授权费的 跨平台的C语言程序接口序列 xff0c 这些接口对音
  • 从此以后谁也别说我不懂LDO了

    LDO是个很简单的器件 xff0c 但是我跟客户沟通的过程中 xff0c 发现客户工程师的技术水平参差不齐 xff0c 有的工程师只是follow 别人以前的设计 xff0c 任何原理和设计方法都不懂 xff0c 希望大家看完这篇文章都能成
  • 屏下指纹技术实现方案与原理

    1月24日 xff0c 全球第一台量产的屏幕指纹手机vivo X20 Plus屏幕指纹版正式在北京亮相 据悉 xff0c 该手机屏幕指纹版已经支持支付宝和微信的指纹支付 vivo X20 Plus屏下指纹 xff0c 其原理是利用光电反射技
  • linux系统的休眠与唤醒简介

    系统挂起 xff08 Suspend xff09 是电源管理 xff08 APM amp ACPI xff09 的一个特性 xff0c 给用户带来了很大的方便 Linux在2 6系列核心中对电源管理有了较好的支持 xff0c 下面就谈谈Li
  • 奇偶校验的概念

    奇偶校验 Parity Check 是一种校验代码传输正确性的方法 根据被传输的一组二进制代码的数位中 34 1 34 的个数是奇数或偶数来进行校验 采用奇数的称为奇校验 xff0c 反之 xff0c 称为偶校验 采用何种校验是事先规定好的
  • HTTP Basic, Session, Token 三种认证方法简介

    1 概述 本文简介 HTTP Basic xff0c Session xff0c Token 三种认证方法 Basic 认证 xff1a 户籍部门已给你签发了一张身份证 你每次去办事 xff0c 都要带上身份证证 xff0c 后台要拿你的身
  • 车路协同、智能网联方面的英文专业词汇

    车路协同系统 Cooperative Vehicle Infrastructure System xff08 CVIS xff09 车辆对基础设施 Vehicle to Infrastructure V2N 车辆对网络 Vehicle to
  • 国内外知名激光雷达企业盘点

    https mp weixin qq com s KBOZfM qP9y oCAB6FxZxQ 国外知名产品 品牌 图示 所属国家 核心产品 Velodyne 美国 机械式激光雷达 HDL 64E HDL 32E VLP 16 车规级 激光
  • 激光雷达的性能指标-以大疆livox-Mid40激光雷达为例

    xff08 看了一下 xff0c 有网上列表的探测范围数据与本文截图不太一致 xff0c 本文截图来自livox官网手册 xff09 有人问我 这个参数是什么意思 xff0c 在此解释一下 xff1a 激光打到不同的射物上 xff0c 能反
  • 《FlowNet3D》(CVPR2019)--直接从点云中估计场景流

    暴走兔学习了CVPR 2019的论文 xff1a FlowNet3D Learning Scene Flow in 3D Point Clouds xff0c 为了更好的理解该论文 xff08 年纪大了容易忘 xff09 xff0c 在此做
  • 增量式PID和位置式PID

    转自 panpan 0315的博客 原文地址 http www eefocus com panpan 0315 blog 10 08 194022 25161 html 1 先介绍几个概念 xff0c 首先是比例带 比例带是一个无量纲的纯数
  • 需要基于消失点标定资料的亲们注意啦!(Especially for私信和留言给我的小伙伴)

    需要基于消失点标定资料的亲们注意啦 xff01 xff08 Especially for私信和留言给我的小伙伴 xff09 截图为我调研和筛选之后的经典文献 xff0c 已上传至CSDN xff0c 请移步到该链接下载 https down
  • 解决error:OpenCV4.3.0 无法解析的外部符号 void __cdecl cv::imshow

    今天用opencv 4 3 0写demo xff0c 遇到编译错误 xff1a error LNK2019 无法解析的外部符号 void cdecl cv imshow xff0c 反复检查了几次VS的配置 xff0c 确定自己包含了头文件
  • 毫米波雷达和视觉融合简记

    毫米波雷达和视觉传感器融合笔记 毫米波雷达和摄像头概述毫米波雷达和视觉传感器融合时间融合空间融合 写在前面 xff1a 1 按照信息抽象的五个层次 xff0c 融合可分成五个级别 xff0c 即 xff1a 检测级融合 位置级融合 属性 x
  • 多目标跟踪-DeepSort分析(一)论文解读及代码架构

    先引入多目标跟踪DeepSort的论文地址及代码链接 xff08 Python版 xff09 xff1a 论文地址 xff1a https arxiv org pdf 1703 07402 pdf 代码链接 xff1a https gith