精华内容
下载资源
问答
  • DeepSORT简单理解
    千次阅读
    2022-03-06 08:49:15

    DeepSORT算法通过结合目标框的马氏距离(Mahalanobis distance)和特征余弦距离(Cosine similarity)两个度量来整合运动信息和外观信息。外观信息是指使用了一个简单的CNN网络去提取被检测物体的外观特征。运动信息是指卡尔曼kalman滤波预测的结果

    Deepsort的算法流程是:

    (1)获取视频的初始帧

    (2)使用卡尔曼(kalman)滤波器进行目标运动状态的预测,得到估计目标的两种状态。

            DeepSORT中的滤波算法使用的状态是一个8个维度的向量。分别是u, v, γ, h, ẋ, ẏ, γ̇, ḣ,(u, v表示目标中心点的水平坐标和目标中心的垂直坐标,(γ)是宽高比,(h)是高度,其余四个变量ẋ, ẏ, γ̇, ḣ表示对应的在图像坐标系中的速度信息

            1)均值(Mean)通过观测矩阵(observation matrix)输出包含目标的位置和速度信息的(u,v,r,h)

            2)协方差(Covariance) :表示通过线性估计获取的物体运动状态的不确定性值,矩阵中数字越大则表明不确定性越大。

    (3)提取检测到的物体的视觉特征和运动特征.

    4进行相似度计算,计算前面的帧和当前帧目标之间的匹配程度。

            1)马氏距离Mahalanobis distance,是计算两个未知样本集之间相似度的有效方法。当协方差(Covariance) 不确定性越小的情况下,DeepSORT算法使用检测框和跟踪器预测框之间的马氏距离来计算运动信息的相似度,这对短时间遮挡是有效的。

            2)协方差(Covariance) 不确定性越大的情况下,DeepSORT 对每一个追踪的目标通过神经网络提取一个外观特征向量, 通过计算当前帧的检测与历史追踪的目标特征向量之间的最小余弦距离来确定相似度. 余弦距离考虑外观信息,这对长期遮挡的目标ID的找回比较有效。

    5)最后对运动和外观两种度量方式进行线性加权作为最终的度量,最终通过匈牙利算法关联的代价矩阵对数据进行关联,为每个对象分配目标的ID

    DeepSORT(SORT)알고리즘은 object bounding box의 마하라노비스 거리(Mahalanobis distance)와 특징 코사인거리(Cosine similarity)의 두 메트릭스를 결합하여 운동 정보와 외관 정보를 통합한다. 외관 정보란 검출 대상물의 외관 특징을 추출하기 위해 간단한 CNN 네트워크를 사용하는 것을 말한다. 운동 정보란 칼만(kalman) 필터가 예측한 결과를 말한다.

    Deepsort 알고리즘의 프로세스는 아래 5가지 순서로 나타낸다.

    1) 비디오의 초기 프레임 가져오기

    2) 칼만 필터를 사용하여 대상의 움직임 상태를 예측한다. 목표를 얻은 두 가지 상태.

    DeepSORT에서의 칼만 필터 알고리즘은 8차원(u, v, γ, h, ẋ, ẏ, γ̇, ḣ)벡터를 사용하여 타겟의 대상를 나타낸다. (u, v)는 목표 중심점의 수평 좌표와 목표 중심부의 수직 좌표를 나타내며, (γ)는 종횡비, (h)는 높이이고 나머지4개의 변수(ẋ, ẏ, γ̇, ḣ)는 대상물이 영상 좌표계에 있는 속도 정보를 표시한다.

    (a) 평균값(Mean): 관측 행렬(observation matrix)을 통해 출력되는 대상의 위치 및 속도 정보(u, v, r, h)를 나타낸다.

    (b) 공분산(Covariance): 선형 추정을 통해 얻은 목표의 운동 상태를 나타내는 불확실성 값. 행렬의 숫자가 클수록 불확실성이 크다는 것을 나타낸다.

    3) 감지된 물체의 외관 특징과 운동(vector) 특징을 추출한다.

    4) 유사도 계산을 통해 앞의 프레임과 현재 프레임 목표 사이의 일치도를 계산한다.

    (a) 마하라노비스의 거리(Mahalanobis distance)는 두 샘플 사이의 유사도를 계산하는 효과적인 방법이다. 공분산(Covariance)의 불확실성이 적을수록 DeepSORT 알고리즘은 detection bounding box와 예측 bounding box 간 운동 정보의 유사도를 계산하기 위해 마하라노비스 거리를 사용한다. 이는 단시간에 차단된 object의 tracking에 효과적이다.

    (b) 공분산(Covariance)의 불확실성이 클수록,DeepSORT는 각 추적 object의 외관 특징(벡터)을 신경망을 통해 추출한다. 현재 프레임과 이전 추적 object의 대상 외관 특징 벡터 사이의 최소 코사인 유사도(cosine similarity)을 계산하여 유사도를 알아낸다. 코사인 거리를 통한 외관 정보를 산출하면 장기간 가려진 object의 ID를 되찾는 것이 비교적 효과적이다.

    5) 마지막으로 운동과 외관 두 가지 도량 방식에 대한 선형 가중치를 통해 최종 결과를 도출한다. 다음 헝가리안 알고리즘(Hungarian algorithm)을 통해 연관된 대가행렬은 데이터에 연관되어 각 object에 ID를 할당한다.

    更多相关内容
  • Yolov5+Deepsort所需模型

    2021-03-29 15:56:26
    Yolov5+Deepsort所需模型,方便国内开发者下载,包括:ckpt.t7和yolov5l.pt两个主要文件。
  • 根据Deep SORT的代码进行算法流程分析,通过列举了前4 帧的跟踪流程,对每一帧各种结果的可能性进行了分析,便于研究多目标跟踪方向的道友们更好的理解代码流程。本人也是初学者,若有解释不到位或者借鉴不当之处,...
  • yolov5+DeepSort测试视频

    2021-07-12 20:03:28
    yolov5+DeepSort测试视频
  • 包含训练好的权重(人+车)+源码+行人检测追踪原视频+车辆检测追踪原视频。 基于Python+Pytorch+DeepSort
  • DeepSort 总结

    千次阅读 2021-01-07 20:00:49
    DeepSort与Sort 先把两者区别写出来: Sort 算法利用卡尔曼滤波算法预测检测框在下一帧的状态,将该状态与下一帧的检测结果进行匹配,实现车辆的追踪。 DeepSort中采用了一个简单的CNN来提取被检测物体(检测框物体...

    DeepSort与Sort

    先把两者区别写出来:

    1. Sort 算法利用卡尔曼滤波算法预测检测框在下一帧的状态,将该状态与下一帧的检测结果进行匹配,实现车辆的追踪。
    2. DeepSort中采用了一个简单的CNN来提取被检测物体(检测框物体中)的外观特征(低维向量表示),在每帧检测+追踪后,进行一次物体外观特征的提取并保存。

    Sort的问题:
    匹配的时候用的是匈牙利算法,但是当物体遮挡之后,前后帧的物体失去关联,物体重新出现后,会切换id。

    在实时视频流中,不可能保留全局视频帧中的检测框数据,因此想要解决ID频繁切换的问题,需要利用之前保存的外观特征,分配该物体受遮挡前的ID编号,从而解决ID切换的问题。
    在实际效果中:低FPS(3-5)的场景下可能会跟丢,但是FPS超过8之后,效果会好很多,两者重叠后也会继续追踪,大家可以用yolov5+deepsort试试,买个萤石(简单场景可以使用,但是要关闭内置的一些算法,会影响推流速度)或者使用ffmpeg循环推送视频流来观察效果。
    论文中提到,检测质量对跟踪性能有很大的影响。

    如下图是SORT作者使用的追踪器,发现当FrRCNN(VGG16)作为最佳检测器,在ID的切换数量和 Multi-object tracking accuracy(MOTA)多目标追踪精度上都有较好的表现。
    我们在实验时使用yolov5-l 结合deep-sort,发现表现很好,正常情况下不会出现丢失的情况。

    在这里插入图片描述

    外观特征的提取器:
    在这里插入图片描述
    这个网络最后输出的是一个128维的向量,值得关注的是,由于DeepSORT主要被用来做行人追踪的,那么输入的大小为128(高)x 64(宽)的矩形框。如果你需要做其他物体追踪,可能要把网络模型的输入进行修改。

    卡尔曼滤波

    SORT中的卡尔曼滤波算法使用的状态是一个7维的向量

    x = [ u , v , s , r , u ˙ , v ˙ , s ˙ ] T x = [u,v,s,r,\dot{u},\dot{v},\dot{s}]^T x=[u,v,s,r,u˙,v˙,s˙]T

    其中

    • u u u v v v代表目标物体框中心的水平和垂直坐标
    • s s s r r r代表了目标物体框的面积和长宽比(注意长宽比应该为一个常量)
    • u ˙ , v ˙ , s ˙ \dot{u} ,\dot{v},\dot{s} u˙,v˙,s˙ 则代表了预测的下一帧情况, r r r默认不变。

    当检测框与目标关联上之后,这个检测框会用于更新目标状态。通过卡尔曼滤波,会实时更新速度分量,保证目标的最新状态。
    若没有关联上目标(未检测或被遮挡),则使用线性速度模型简单的预测状态,但不会进行校正。

    上述是SORT中的应用,但在DeepSORT中,添加了一个新的变量,变成了
    ( u , v , γ , h , u ˙ , v ˙ , γ ˙ , h ˙ ) (u,v,\gamma,h,\dot{u},\dot{v},\dot{\gamma},\dot{h}) (u,v,γ,h,u˙,v˙,γ˙,h˙)
    多了一个长宽比(aspect ratio)的变化率,分别表示bounding box中心的位置纵横比高度以及在图像坐标中对应的速度信息。因为SORT中假设检测框的长宽比是固定的,但是在实际情况下,随着物体和相机的相对运动,距离会发生变化,物体的长宽比也是会发生变化的。
    然后使用一个kalman滤波器预测更新轨迹,该卡尔曼滤波器采用匀速模型和线性观测模型。

    框与目标的数据关联

    SORT:
    作者使用匈牙利指派算法进行数据关联,使用的cost矩阵为原有目标在当前帧中的预测位置和当前帧目标检测框之间的IOU。当然小于指定IOU阈值的指派结果是无效的。作者发现使用IOU能够解决目标的短时被遮挡问题。这是因为目标被遮挡时,检测到了遮挡物,没有检测到原有目标,假设把遮挡物和原有目标进行了关联。那么在遮挡结束后,因为在相近大小的目标IOU往往较大,因此很快就可以恢复正确的关联。这是建立在遮挡物面积大于目标的基础上的。

    缺点:遮挡结束后,车辆检测可能又将被继续执行,那么SORT只能分配给该物体一个新的ID编号,代表一个新的追踪片段的开始。所以受遮挡等情况影响较大,会有大量的ID切换。

    DeepSort:
    由于SORT忽略了被检测物体的表面特征,因此只有在物体状态估计不确定性较低是才会准确,在Deep SORT中,我们使用更加可靠的度量来代替关联度量,并使用CNN网络在大规模行人数据集进行训练,并提取特征,已增加网络对遗失和障碍的鲁棒性。

    DeepSORT中采用了一个简单(运算量不大)的CNN来提取被检测物体(检测框物体中)的外观特征(低维向量表示),在每次(每帧)检测+追踪后,进行一次物体外观特征的提取并保存。

    后面每进行一次updata,都要计算当前帧被检测物体外观特征和之前存储的外观特征的相似度,这是作为一个重要的判别依据。(由两部分组成,运动特征+外观特征,运动特征是卡尔曼滤波提供的)

    过程:

    • 初始化:一个检测没有和之前的trach相关联,就会初始化一个新的目标
    • 新生:一个目标被初始化之后,前三帧被正常捕捉和关联成功之后,物体会产生一个新的track,否则会被删除。
    • 消失:如果超过了设定的最大保存时间(原文中叫做predefined maximum age)没有被关联到的话,那么说明这个物体离开了视频画面,该物体的信息(记录的外观特征和行为特征)将会被删除。

    PS:如果实时视频处理后FPS过低的话,可能目标框未捕捉到3帧就消失,不会在屏幕上显示。

    运动特征

    DeepSort中使用了马氏距离来计算卡尔曼滤波状态和新获得的测量值(检测框)之间的距离。
    公式如下:
    在这里插入图片描述
    ( y i , S i ) (y_i,S_i) (yi,Si)表示第i个追踪分布在测量空间上的投影, y i y_i yi为均值, S i S_i Si为协方差。

    i代表追踪的序号,j表示检测框的序号。

    马氏距离通过测量卡尔曼滤波器的追踪位置均值(mean track location)之间的标准差与检测框来计算状态估计间的不确定性,即 d 1 ( i , j ) d^1(i,j) d1(i,j)为第i个追踪分布和第j个检测框之间的马氏距离(不确定度)。

    论文中使用 t = 9.4877 t = 9.4877 t=9.4877来作为马氏距离的阈值上限,超过则直接忽略。t是由倒卡方分布计算出来的95%置信区间作为阈值。

    	def gating_distance(self, mean, covariance, measurements,
                            only_position=False):
            """Compute gating distance between state distribution and measurements.
    
            A suitable distance threshold can be obtained from `chi2inv95`. If
            `only_position` is False, the chi-square distribution has 4 degrees of
            freedom, otherwise 2.
    
            Parameters
            ----------
            mean : ndarray
                Mean vector over the state distribution (8 dimensional).
            covariance : ndarray
                Covariance of the state distribution (8x8 dimensional).
            measurements : ndarray
                An Nx4 dimensional matrix of N measurements, each in
                format (x, y, a, h) where (x, y) is the bounding box center
                position, a the aspect ratio, and h the height.
            only_position : Optional[bool]
                If True, distance computation is done with respect to the bounding
                box center position only.
    
            Returns
            -------
            ndarray
                Returns an array of length N, where the i-th element contains the
                squared Mahalanobis distance between (mean, covariance) and
                `measurements[i]`.
    
            """
            mean, covariance = self.project(mean, covariance)
            if only_position:
                mean, covariance = mean[:2], covariance[:2, :2]
                measurements = measurements[:, :2]
    
            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
    
    

    外观特征

    通过CNN(其实是一个小型的残差网络,两个卷积层和六个残差网络)将人体检测框reshape成128*64的物体输入,输出一个128维的向量。通过归一化之后,向量模长为1。

    该CNN已经在大规模的人员重新识别数据集上进行了训练,该数据集包含超过1100000张1261名行人的图像,非常适合在人体跟踪环境中进行深度学习。在1050 GPU上向前传递32个边界框大约需要30毫秒。

    会为每一个目标K创建一个gallery,用于存储该目标中不同帧的外观特征。代码中的NN_BUDGET就代表了gallery最大存储的大小,默认为100,即最多只能存储目标K当前时刻前100帧的目标外观特征。
    第二个距离计算公式:
    在这里插入图片描述
    通过其求解所有已知的gallery中的外观特征与获得的检测框(编号为j)的外观特征的最小余弦距离。然后设置一个 t 2 t^2 t2来判断关联是否合理
    在这里插入图片描述

    数据融合+级联匹配

    通过上面的 d 1 d_1 d1 d 2 d_2 d2,将这两个尺度融合为:
    cost matrix C C C
    gate matrix B B B

    c i , j = λ d 1 ( i , j ) + ( 1 − λ ) d 2 ( i , j ) c_{i,j} =\lambda d^1(i,j)+(1-\lambda)d^2(i,j) ci,j=λd1(i,j)+(1λ)d2(i,j)
    在这里插入图片描述

    级联匹配:

    本文还提出了一种级联匹配的策略来提高匹配精度,主要由于当一个目标被遮挡很长时间,Kalman滤波的不确定性就会大大增加,并会导致连续预测的概率弥散,假设本来协方差矩阵是一个正态分布,那么连续的预测不更新就会导致这个正态分布的方差越来越大,那么离均值欧氏距离远的点可能和之前分布中离得较近的点获得同样的马氏距离值。
    在这里插入图片描述
    简单描述下:

    1. 输入追踪T和检测D,最大保留时长 A m a x A_{max} Amax
    2. 第一行和第二行计算了联合代价矩阵C和gate矩阵B,如上述公式
    3. 第三第四行,初始化匹配列表 M M M和非匹配列表 U U U,将 D D D赋予
    4. 1到 A m a x A_{max} Amax的for循环:
      4.1 按照给定的age选择track
      4.2 使用匈牙利算法计算min_cost_matching的i和j
      4.3 将满足合适条件的i,j赋值给匹配列表 M M M,保存
      4.4 重新更新非匹配列表 U U U
    5. 返回匹配列表 M M M和非匹配列表 U U U
      代码模块:
    def min_cost_matching(
            distance_metric, max_distance, tracks, detections, track_indices=None,
            detection_indices=None):
        """Solve linear assignment problem.
    
        Parameters
        ----------
        distance_metric : Callable[List[Track], List[Detection], List[int], List[int]) -> ndarray
            The distance metric is given a list of tracks and detections as well as
            a list of N track indices and M detection indices. The metric should
            return the NxM dimensional cost matrix, where element (i, j) is the
            association cost between the i-th track in the given track indices and
            the j-th detection in the given detection_indices.
        max_distance : float
            Gating threshold. Associations with cost larger than this value are
            disregarded.
        tracks : List[track.Track]
            A list of predicted tracks at the current time step.
        detections : List[detection.Detection]
            A list of detections at the current time step.
        track_indices : List[int]
            List of track indices that maps rows in `cost_matrix` to tracks in
            `tracks` (see description above).
        detection_indices : List[int]
            List of detection indices that maps columns in `cost_matrix` to
            detections in `detections` (see description above).
    
        Returns
        -------
        (List[(int, int)], List[int], List[int])
            Returns a tuple with the following three entries:
            * A list of matched track and detection indices.
            * A list of unmatched track indices.
            * A list of unmatched detection indices.
    
        """
        if track_indices is None:
            track_indices = np.arange(len(tracks))
        if detection_indices is None:
            detection_indices = np.arange(len(detections))
    
        if len(detection_indices) == 0 or len(track_indices) == 0:
            return [], track_indices, detection_indices  # Nothing to match.
    
        cost_matrix = distance_metric(
            tracks, detections, track_indices, detection_indices)
        cost_matrix[cost_matrix > max_distance] = max_distance + 1e-5
    
        row_indices, col_indices = linear_assignment(cost_matrix)
    
        matches, unmatched_tracks, unmatched_detections = [], [], []
        for col, detection_idx in enumerate(detection_indices):
            if col not in col_indices:
                unmatched_detections.append(detection_idx)
        for row, track_idx in enumerate(track_indices):
            if row not in row_indices:
                unmatched_tracks.append(track_idx)
        for row, col in zip(row_indices, col_indices):
            track_idx = track_indices[row]
            detection_idx = detection_indices[col]
            if cost_matrix[row, col] > max_distance:
                unmatched_tracks.append(track_idx)
                unmatched_detections.append(detection_idx)
            else:
                matches.append((track_idx, detection_idx))
        return matches, unmatched_tracks, unmatched_detections
    

    在最后阶段,作者使用之前SORT算法中的IOU关联去匹配n=1的unconfirmed和unmatched的轨迹。这可以缓解因为表观突变或者部分遮挡导致的较大变化。当然有好处就有坏处,这样做也有可能导致一些新产生的追踪被连接到了一些旧的追踪上(重叠的时候容易发生)。

    总结

    使用CNN提取的特征进行匹配,大大减少了SORT中的ID switches, 经作者实验证明减少了大约45%, 在高速率视频流中也达到了很好的水准!

    展开全文
  • Yolov5 +使用PyTorch进行深度排序 介绍 该存储库包含PyTorch YOLOv5的简化版( )。 它过滤掉不是人的所有检测。 然后,将对人员的检测传递给跟踪人员的深度排序算法( )。 它仅跟踪人员这一事实背后的原因是,深度...
  • 使用YOLOv5 + Deepsort实现车辆行人追踪和计数,代码封装成一个检测器类,更容易嵌入到自己的项目中。 代码地址(欢迎星): 最终效果: YOLOv5检测器: class Detector ( baseDet ): def __init__ ( self ): ...
  • Yolov5_DeepSort_bytetrack

    2021-11-20 23:50:00
    Yolov5 DeepSort跟踪 bytetrack跟踪实例代码, deepsort 跟踪示例代码:track.py ByteTrack超越了此前所有的跟踪方法。 参考资料:https://blog.csdn.net/zhouchen1998/article/details/120932206 bytetrack示例...
  • 目前主流的目标跟踪算法都是基于Tracking by Detection策略,即根据目标检测结果进行目标跟踪,本文主要对经典的目标跟踪算法DeepSort C++版本代码的工作流程以及模块进行讲解。如果本文内容有误,欢迎指出探讨。 ...

    本文源码基于开源项目https://github.com/bianjingshan/MOT-deepsort.git

    内容简介:

            目前主流的目标跟踪算法都是基于Tracking by Detection策略,即根据目标检测结果进行目标跟踪,本文主要对经典的目标跟踪算法DeepSort C++版本代码的工作流程以及模块进行讲解。如果本文内容有误,欢迎指出探讨。

            本次代码讲解主要遵循由上而下的方式,先讲总体后讲细节。

     代码目录结构如下:

     

    data/2DMOT2015/test:用于测试的目标跟踪数据集

    demo:目标跟踪简单应用demo

    src:目标跟踪源码

     先上代码deersort.h代码:

    #ifndef _DEEP_SORT_H_
    #define _DEEP_SORT_H_
    
    #include <vector>
    //#ifdef __cplusplus
    //extern "C" {
    //#endif
    
    //坐标信息
    typedef struct
    {
    	int x;
    	int y;
    	int width;
    	int height;
    }DS_Rect;
    
    //目标检测信息
    typedef struct
    {
    	int class_id;
    	DS_Rect rect;
    	float confidence;
    }DS_DetectObject;
    
    //目标跟踪信息
    typedef struct
    {
    	int track_id;
    	int class_id;
    	float confidence;
    	DS_Rect rect;
    }DS_TrackObject;
    
    
    typedef void * DS_Tracker;
    typedef std::vector<DS_DetectObject> DS_DetectObjects;
    typedef std::vector<DS_TrackObject> DS_TrackObjects;
    
    //目标跟踪器的创建
    DS_Tracker DS_Create(
    	float max_cosine_distance=0.2, 
    	int nn_budget=100, 
        float max_iou_distance = 0.7, 
        int max_age = 30, 
    	int n_init=3);
    //跟踪器删除
    bool DS_Delete(DS_Tracker h_tracker);
    
    //跟踪器的更新以完成跟踪过程
    bool DS_Update(
    	DS_Tracker h_tracker, 
    	DS_DetectObjects detect_objects, 
    	DS_TrackObjects &track_objects);
    
    
    //#ifdef __cplusplus
    //}
    //#endif
    
    #endif
    
    
    

            首先定义三个结构体,分别为目标坐标信息、目标检测信息以及目标跟踪信息结构体;函数部分主要为跟踪器的创建、删除、更新。

    上deepsort.cpp源码:

    #include <iostream>
    #include <sstream>
    #include <stdio.h>
    #include <fstream>
    #include <stdlib.h>
    #include <unistd.h>
    #include "tracker.h"
    #include "deepsort.h"
    
    //跟踪器创建
    DS_Tracker DS_Create(
    	float max_cosine_distance, 
    	int nn_budget, 
        float max_iou_distance, 
        int max_age, 
    	int n_init)
    {
        return (DS_Tracker)(new tracker(max_cosine_distance, nn_budget, max_iou_distance, max_age, n_init));
    }
    
    //跟踪器删除
    bool DS_Delete(DS_Tracker h_tracker)
    {
        delete((tracker *)h_tracker);
        return true;
    }
    #if 0
    bool DS_Update(
        DS_Tracker h_tracker, 
    	DS_DetectObject *p_detects, 
    	int detect_num, 
    	DS_TrackObject *p_tracks, 
    	int *p_tracks_num, 
    	int max_tracks_num)
    {
        tracker *p_tracker=(tracker *)h_tracker;
        DETECTION_ROW temp_object;
        DETECTIONS detections;
        for(int iloop=0;iloop<detect_num;iloop++)
        {
            temp_object.confidence=p_detects[iloop].confidence;
            temp_object.tlwh = DETECTBOX(p_detects[iloop].x, p_detects[iloop].y, p_detects[iloop].width, p_detects[iloop].height);
    //如果使用特征匹配,则先清空特征数组
    #ifdef FEATURE_MATCH_EN
            temp_object.feature.setZero();
    #endif 
            detections.push_back(temp_object);
        }
        p_tracker->predict();
    	p_tracker->update(detections);
        DETECTBOX output_box;
        int output_num=0;
        for(Track& track : p_tracker->tracks) 
        {
            if(!track.is_confirmed() || track.time_since_update > 1) continue;
            output_box=track.to_tlwh();
            
            p_tracks[output_num].track_id=track.track_id;
            p_tracks[output_num].x=output_box(0);
            p_tracks[output_num].y=output_box(1);
            p_tracks[output_num].width=output_box(2);
            p_tracks[output_num].height=output_box(3);
            output_num++;
            if(output_num>=max_tracks_num)
            {
                break;
            }
        }
        *p_tracks_num=output_num;
        return true;
    }
    #endif
    
    //跟踪器进行更新跟踪
    bool DS_Update(
    	DS_Tracker h_tracker, 
    	DS_DetectObjects detect_objects, 
    	DS_TrackObjects &track_objects)
    {
        tracker *p_tracker=(tracker *)h_tracker;
        DETECTION_ROW temp_object;
        DETECTIONS detections;
        //遍历目标检测信息
        for(int iloop=0;iloop<detect_objects.size();iloop++)
        {
            temp_object.class_id=detect_objects[iloop].class_id;
            temp_object.confidence=detect_objects[iloop].confidence;
            temp_object.tlwh = DETECTBOX(
                detect_objects[iloop].rect.x, 
                detect_objects[iloop].rect.y, 
                detect_objects[iloop].rect.width, 
                detect_objects[iloop].rect.height);
    #ifdef FEATURE_MATCH_EN
            temp_object.feature.setZero();
    #endif 
            detections.push_back(temp_object);
        }
        //tracker进行推理更新
        p_tracker->predict();
    	p_tracker->update(detections);
        DETECTBOX output_box;
        DS_TrackObject track_object;
        track_objects.clear();
        //筛选出跟踪匹配的目标
        for(Track& track : p_tracker->tracks) 
        {
            if(!track.is_confirmed() || track.time_since_update > 1) continue;
            output_box=track.to_tlwh();
            
            track_object.track_id=track.track_id;
            track_object.class_id=track.class_id;
            track_object.confidence=track.confidence;
            track_object.rect.x=output_box(0);
            track_object.rect.y=output_box(1);
            track_object.rect.width=output_box(2);
            track_object.rect.height=output_box(3);
            track_objects.push_back(track_object);
        }
        return true;
    }

            这里的DS_Create为初始化一些参数并创建一个tracker返回;DS_Delete则删除创建的tracker;

            DS_Update实际使用以下面的为例,三个参数分别为初始化好的tracker,目标检测信息数组,目标跟踪信息数组的引用。

            首先将目标检测到的类别、坐标等信息遍历放入到vector,然后使用tracker进行预测推理更新,更新后将得到的tracks进行筛选,得出本次跟踪的结果。其中track_id为跟踪id,可以在外部打印或者画到图像中以查看每个跟踪的目标id。

             下一篇将对tracker的内容做讲解。

    展开全文
  • deep_sort_yolo3进行的多目标跟踪,效果不错,在1080ti上可以做到实时,由于csdn上不能上传大于220MB的文件,如果有不会训练模型的朋友,可以私聊我
  • 一、Yolov5有检测输出,deepsort无track输出,原因 测试视频:MOT_trackingDemo/test_MOT16-01.avi,MOT challenge,MOT16中的test_MOT16-01.avi。把img序列压成一个avi格式的视频。 ① 现象:有
    1. 参考博客:多目标跟踪之数据关联算法——匈牙利算法
    2. Yolov5_DeepSort_Pytorch仓库: https://github.com/mikel-brostrom/Yolov5_DeepSort_Pytorch.git

    Deepsort的重点是:(我关注的是级联匹配这部分,重点分析casecade_matching,non-global assignment的特点和优缺点)

    • 级联匹配 casecade_matching,non-global assignment。
      指的是,每次只匹配几个track。按照since_time_update,就是连续多少帧没有匹配到dectect bbox的顺序来进行优先匹配。
    • 联匹配完了,用IOU去打补丁。

    Deepsort Paper原文重点:

    1. 参考博客:Deep SORT论文阅读总结
    2. DeepSORT论文翻译(SIMPLE ONLINE AND REALTIME TRACKING WITH A DEEP ASSOCIATION METRIC)_alex1801的博客-CSDN博客_deepsort论文翻译
    3. Deep SORT多目标跟踪算法代码解析 - pprp - 博客园

    0. Abstract:

    1. 本方法加入了外观信息来提高SORT的性能,用余弦距离来度量 tracks 和 detection 的相似度以减少 SORT算法中ID switch的次数

    2. 并使用Kalman预测和实际detection间的平方马氏距离来滤除可能性小的匹配。

    加入Reid提取的外观特征,对目标进行深度关联度量,ID switch减少了45%,外观距离减少ID交换;马氏距离滤除不大可能的匹配。

    1. Introduction:

    This is, because the employed association metric is only accurate when state estimation uncertainty is low.   翻译过来就是kalman的covariance小,costMatric才准确!
    只有在状态估计的残差协方差的值较小(估计不确定性小,就是估计的方差小)时,关联的Metric才是准确的。
    翻译一下就是:只有kf.covariance较小时,pos_cost_matrix的值才是靠谱的,准确的。 SORT的ID切换太多,都是因为kalman filter预测的mean的模型存在缺陷,其kf.covariance鲁棒性较差。

    SORT算法ID switch次数高是因为采用的关联矩阵只在状态预测不确定性较小的时候准确(状态估计模型存在缺陷)

    mark: 是啊,一直predict,不update,covariance就是一直累加累加。可不就变大了。costMatrix可不就变小了,然后unAssignedTrack就更容易匹配上Detect,因为它的Covariance太大了。————导致的后果就是:这个未指定的Track容易误匹配其他的detect。矩阵的横向,容易被匹配。

    翻译一下:所以,Deepsort的作者怎么解决这个问题呢?——对metric打补丁!加入新的metric

    因此,SORT在遮挡场景下存在缺陷。解决遮挡问题的办法:关联metric改为新的metric,新的metric结合了运动信息和外观信息。

    2 SORT with deep association metric:

    We adopt a conventional single hypothesis tracking methodology with recursive Kalman fifiltering and frame-by-frame data association.
    我们采用了传统的单一假设跟踪方法,逐帧数据关联。

     A conventional way to solve the association between the predicted Kalman states and newly arrived measurements is to build an assignment problem that can be solved using the Hungarian algorithm. Into this problem formulation we integrate motion and appearance information through combination of two appropriate metrics.
    运动模型、外观模型,两个metric的组合(翻译一下:但绝非相加之类的metric处理,因为两个metric的意义和量纲绝非一致,无法融合再一起。不不不,后面还是靠权重加在一起了!!!!!

    mark: 

    • ① The Mahalanobis distance takes state estimation uncertainty into account by measuring how many standard deviations the detection is away from the mean track location. Further, using this metric it is possible to exclude unlikely associations by thresholding the Mahalanobis distance at a 95% confifidence interval computed from the inverse 
      χ 2 distribution. 
      马氏距离通过测算检测与平均轨迹位置的距离,超过多少标准差,来考虑状态估计的不确定性。此外,可以通过从逆chi^2分布计算95% 置信区间的阈值,排除可能性小的关联。

      翻译一下:用公式表示就是:dist|detection - track| < \chi^2(2),才是置信度范围内的马氏距离
    • ② While the Mahalanobis distance is a suitable association metric when motion uncertainty is low, in our image-space problem formulation the predicted state distribution obtained from the Kalman filtering framework provides only a rough estimate of the object location. In particular, unaccounted camera motion can introduce rapid displacements in the image plane, making the Mahalanobis distance a rather uninformed metric for tracking through occlusions. Therefore, we integrate a second metric into the assignment problem.

      当运动不确定性较低时 运动协方差covariance较小时,马氏距离是一个合适的关联度量,但在我们的图像空间问题公式中, 从卡尔曼滤波框架获得的预测状态分布 mean只提供了物体位置的粗略估计。特别是, 未计算的摄像机运动可以在图像平面上引入快速位移使马氏距离成为通过遮挡跟踪的一个相当未知的度量。因此,我们在分配问题中集成了第二个度量。
      翻译一下:kalman的估计是粗略的,因为有相机移动等没考虑进去。所以在遮挡的情况下,马氏距离的信息量就不够了,uninformed metric

      翻译一下:这个描述说没问题也没问题,比如在动态camera中,确实是这样。Kalman的预测有它的模型假设,模型失配了就存在较大的问题。但是静态camera中,马氏距离要是计算对了,可没有那么脆弱!!!
    • ③ 外观距离的计算:存储历史最近的100个样本的CNN特征,CNN128个维度;然后检测去挨个跟100个128的向量计算余弦距离,每一个距离都有一个阈值。在平方和100个阈值化后的[0-1]的值。作为cost的内容。 这第二个阈值t(2),我们可是在单独的另外的训练集上找到的经验值。

      实际上,
      我们是预训练了一个CNN网络,来计算bbox的外观描述子(特征提取),这在2.4节中进一步详细解释。
    • ④ 有了上面2个距离之后,大家都在[0-1]中取值,马氏距离pos_matrix是靠卡方距离来进行阈值化的,大于阈值的截断,同时用阈值来归一化,就是每行保证都是[0-1]之间,但是加起来的和可不是1。外观距离appearance_matrix是余弦距离,阈值化后的和。每一行∈[0,1],加起来也不是1。就这样的两个矩阵,用权重加权起来,得到最后的代价矩阵。
       

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

      余弦距离考虑外观信息,这对于在长期遮挡之后找回ID特别有用,此时运动不那么具有辨别力

      最终的使用效果是:当相机运动时,lambda=0,不适用kalman距离了,使用外观距离;但用kalman来滤除完全不可能的匹配!!! 
      关联成本中仅使用外观信息。关联结果仍受两方面的约束。 仅当关联在两个度量的选通区域内时,称其为可接受关联:

    •  The influence of each metric on the combined association cost can be controlled through hyperparameter λ. During our experiments we found that setting λ = 0 is a reasonable choice when there is substantial camera motion. In this setting, only appearance information are used in the association cost term. However, the Mahalanobis gate is still used to disregarded infeasible assignments based on possible object locations inferred by the Kalman filter.
      每个度量对联合关联成本的影响可以通过
      超参数λ来控制。在我们的实验中,我们发现,当有大量的摄像机运动时,设置λ=0是一个合理的选择。在此设置中,在关联代价项中只使用外观信息。然而,阈值化之后的马氏距离仍然被用于忽略基于卡尔曼滤波器推断出的可能的对象位置的不可行的分配。

      • 相应的代码如下面所示:(代码为:_fuull_cost_metric函数中,下图所示)

                app_gate = app_cost > self.metric.matching_threshold
                # Now combine and threshold
                cost_matrix = self._lambda * pos_cost + (1 - self._lambda) * app_cost
                cost_matrix[np.logical_or(pos_gate, app_gate)] = linear_assignment.INFTY_COST
                # Return Matrix
                return cost_matrix

    马氏距离是二维联合高斯分布,取log后的值,可以认为是概率分布。

    但是卡方分布是两个i.i.d.的高斯分布的平方相加:Z_1^2+Z_2^2 \sim \chi^2(n),n=2, α=95%的阈值


    私以为,二者的概念都不一样,为什么要放在一起讨论????


    找到原因了:The Relationship between the Mahalanobis Distance and the Chi-Squared Distribution – ML & Stats

    马氏距离同卡方分布的关系:作者证明了,马氏距离(不开根号),马氏距离的随机随机变量,是服从卡方分布的。卡方分布的自由度,就是马氏距离随机变量的维度。

    如在此案例中,pos_matrix里面只有x,y两个坐标信息的话(中心点坐标),那么就是自由度为2的卡方分布。这里面表示的是这个马氏距离去除5%的outliers,剩下95%的置信度值。基本上,帮助有限。

    同时这里的马氏距离是没有像二元高斯分布那样,加入log det|E|的部分的。没有协方差阵的行列式。 

    同时mark:注意到pos_cost只是除以了卡方的GATTING_THRESHOLD,并没有做normalization。所以pos_cost里面是马氏距离的原生的值。
    然后 pos_cost * λ + (1-λ)* app_cost, app_cost是∈[0,1]。------------------------(两个metric直接相加,总让我无法理解! )
    (私以为)两个metric能够相加的前提是:两个metric被正确消除了量纲的影响,两个metric才能被等值的考虑。

    超过5%的数据都不要,只要95%置信度内的数据。 计算的cost矩阵不符合卡方分布啊!!!

    卡方分布知识补充:

    卡方分布_百度百科

    此处自由度为2. 因为只有posx, posy两个维度的变量。所以是自由度为2的卡方分布。若是8,就是自由度为8的卡方分布。

    这个代码里面:还对kalman计算的距离进行开根号处理!!!   马氏距离的原本含义是:二元联合高斯分布,即两个标准高斯分布的联合分布。不是标准高斯的,可以正交化为标准高斯的,公式自带标准化过程(去相关、正交化、去量纲…… 类似PCA,都一个意思)。

    d=measurement - mean, {\color{Red} pos cost }= \sqrt{\frac{d*d^T}{covariance}} < \chi^2(2) or \chi^2(8)

     马氏距离的计算值,跟卡方距离对不上啊????!!!! 无论是原理上,还是计算过程上!! 
    实际的计算数值之后将贴出来,还要同样证明,每一行的track的数值相加不为1 !!!! 总的概率为1才行吧?

    cost Matrix < thresh 的含义,是建立在costMatrix的值,服从卡方分布的情况下。然后斩断底部5%的数据为outliers。

     

     

    补充:卡方分布临界值表 统计分布临界值表 - 豆丁网

    卡方分布知识补充:卡方分布的概率密度函数和它的一些衍生问题 - 知乎

     

    3 匹配级联:Matching Cascade

    Instead of solving for measurement-to-track associations in a global assignment problem, we introduce a cascade that solves a series of subproblems. To motivate this approach, consider the following situation: When an object is occluded for a longer period of time, subsequent Kalman filter predictions increase the uncertainty associated with the object location. Consequently, probability mass spreads out in state space and the observation likelihood becomes less peaked. Intuitively, the association metric should account for this spread of probability mass by increasing the measurement-to-track distance. Counterintuitively, when two tracks compete for the same detection, the Mahalanobis distance favors larger uncertainty, because it effectively reduces the distance in standard deviations of any detection towards the projected track mean. This is an undesired behavior as it can lead to increased track fragmentations and unstable tracks. Therefore, we introduce a matching cascade that gives priority to more frequently seen objects to encode our notion of probability spread in the association likelihood.
    我们没有采用全局分配问题的求解方式,(解决全局分配问题就是以全局的方式解决检测-跟踪的关联问题),而是引入了解决一系列子问题的级联。为了激发这种方法,请考虑以下情况:当一个物体被遮挡较长时间时,随后的卡尔曼滤波预测增加了与物体位置相关的不确定性。因此,概率质量(概率密度分布函数会变平坦,没有尖峰)在状态空间中扩散,观测似然值降低(观察似然性变得不那么尖锐)。直观地说,关联度量应该通过增加测量到轨道的距离来解释概率质量的扩散。与直觉相反,当两条轨道竞争同一检测时,马氏距离倾向于更大的不确定性covariance,因为它有效地减少了任何检测对投影轨道均值的标准差距离。这是一种不希望出现的行为,因为它可能导致增加的轨道碎片和不稳定的轨道。因此,我们引入了一个匹配级联,优先考虑更常见的对象,以编码关联可能性中概率扩散的概念。

    (翻译一下:我们为什么使用级联方式解决,而不是全局方式解决呢?
    试想一下:当目标长时间被遮挡后,kalman预测的目标位置的误差/不确定性/covariance是会增加的。
    因此,直观上来讲,我们的这个马氏距离/外观距离的metric度量应该通过增加检测-轨迹的距离值distance来将长时间遮挡导致的概率密度分布变平坦/概率下降/covariance增加,给考虑进metric中。
    但是,当给一个检测框bbox分配track的时候,总是covariance大的那个track更容易被匹配。马氏距离偏爱covariance大的/也是就不确定性大的那个track。——这个是对的,没毛病
    所以,这个就不合理,就会增加track碎片和不稳定的track/乱匹配的track。
    所以,我们设计了一个匹配级联,优先保障频繁出现的目标匹配(先做概率高的目标匹配))

     道理上是没错的! 级联匹配跟全局匹配是出于完全不同的考虑的。

    说明一下(翻译一下):
    ① 为啥deepsort会出现遮挡后,covariance一直在增加的情况。——因为遮挡后就没有检测框了,就没有匹配了。deepsort只做kalman predict,协方差只做加法。deepsort不做kalman correct,就没有covariance协方差误差迭代的步骤。所以covariance一直在加加加,加到好几万了。『见:② 现象——kf.predict() 预测环节中的不合理之处 里面的covariance一直在加weight * mean』。所以covariance一直在predict,没有correct。
    而在, https://github.com/Smorodov/Multitarget-tracker 的代码逻辑中,对于unAssignedTrack是会用predict自己预测的值去correct自己的卡尔曼的。那么covariance也会被迭代,总体来看,每一个track的covariance都是会像正常的kalman过程收敛的。根据过程噪声和观测噪声的噪声水平差异,会收敛在不同的水平。 

    参考:kalman简单例子——初始化参数对kalman性能的影响__helen_520的博客-CSDN博客_kalman 可以看到Pn+1|n+1的收敛图。 

    ② 按照正常来说,kalman如果在unAssignedTrack也做correct的情况下,其track的covariance是会持续降低的。
    对于马氏距离的cost matrix而言,covariance降低,相当于cost Matrix除以了一个小一点的值,这一行的数值都会比上一轮改行的数值大一些。
    这个收敛的变化是微小的,慢慢的,趋于平稳的。所以更重要的是,需要靠马氏距离的分母,也就是空间位置/欧氏距离的部分的区分度来进行一个补偿。协方差是为了消除x,y量纲不匹配的问题。covariance的变化不能吃掉了/淹没了/覆盖了 欧氏距离远近的这样一个差异/不能改变太多。这样才能让马氏距离这个metric在长时间遮挡的情况下,也能保证其距离metric的鲁棒性!

     这个图是理解级联匹配算法的关键。第5行:先让上一帧匹配过的track去挑检测框,占着坑。

     

    def _match(self, detections):
            # Split track set into confirmed and unconfirmed tracks.
            confirmed_tracks = [i for i, t in enumerate(self.tracks) if t.is_confirmed()]
            unconfirmed_tracks = [i for i, t in enumerate(self.tracks) if not t.is_confirmed()]
    
            # Associate confirmed tracks using appearance features.
            matches_a, unmatched_tracks_a, unmatched_detections = linear_assignment.matching_cascade(
                self._full_cost_metric,
                linear_assignment.INFTY_COST - 1,  # no need for self.metric.matching_threshold here,
                self.max_age,
                self.tracks,
                detections,
                confirmed_tracks,
            )
    
            # Associate remaining tracks together with unconfirmed tracks using IOU.
            iou_track_candidates = unconfirmed_tracks + [
                k for k in unmatched_tracks_a if self.tracks[k].time_since_update == 1
            ]
            unmatched_tracks_a = [
                k for k in unmatched_tracks_a if self.tracks[k].time_since_update != 1
            ]
            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,
            )
    
            matches = matches_a + matches_b
            unmatched_tracks = list(set(unmatched_tracks_a + unmatched_tracks_b))
            return matches, unmatched_tracks, unmatched_detections

    补充SORT部分:

    sort最大的问题,是IOU的costMatrix不可靠。导致大量的ID switch。

     4 Deep Appearance Descripter 深度外观描述子 

    我们没做metric learning,而是使用了简单的最近邻查询 nearest neighbor queries。先得离线训练一个特征提取网络。我们采用的是在一个大规模的行人重识别数据集上训练的CNN网络,这个数据集包含了超过110万张图像,其中行人有1261个。这个数据集就非常适合在行人跟踪的上下文环境中进行deep metric learning。

    行人重识别的CNN网络,128维度的特征图;有280W个参数,计算32个bboxs在GTX1050的显卡上,花了30ms,所以只要是现代的GPU,非常适合online tracking。

    5 Experiment 实验部分

    MOT16数据集,参数设置:检测的阈值为0.3, λ= 0和Amax = 30帧。

    评价指标:参考:多目标跟踪MOT16数据集和评价指标 - 知乎

    • MOTA Multi-object tracking accuracy 多目标跟踪准确度:结合了误报、漏检、和ID切换三个考虑因素,得到的总的跟踪精度。这个值越高越好。
      定义为:

    • MOTP(Multiple Object Tracking Precision) 多目标跟踪精确度:

     

     

     

     与SORT相比, ID switches从1423减少到781,减少了约45%的ID切换。由于通过遮挡和遗漏来保持对象的身份,轨迹碎片会稍微增加。
    还有就是MT的值增加了,就是80%的时间内track都匹配到自己的detect bbox的比例增加了。Mostly lost减少了。

    我们的方法的ID交换是最少的,同时还能保持较高的MOTA分数、FM碎片率和FN 漏匹配。
    如果调高了检测的置信度进行筛选,漏检增加(trick),能够大幅度提高我们算法的这些指标。(漏检对提高指标有好处!!!! 我去!

    但是呢,我们观察发现,这些错误的误匹配都是由于静态场景中的零星的检测导致的。由于我们跟踪age比较大,这些静态的目标通常会加入我们的轨迹维护中。
    同时呢,我们也观察到,我们的算法不存在频繁的在误报中跳来跳去的轨迹。我们的轨迹都是比较平稳的,不会有太多跳来跳去的折线轨迹。

     (完)


    一、Yolov5有检测输出,deepsort无track输出,原因

    测试视频:MOT_trackingDemo/test_MOT16-01.avi,MOT challenge,MOT16中的test_MOT16-01.avi。把img序列压成一个avi格式的视频。

    ① 现象:有检测输出,无轨迹输出

    原因:第68帧为止,新建了491个ID了。(代码丝毫无改动的情况下)——基本上毫无匹配

    video 1/1 (66/450) /home/zhr/zhr_file/MOT_trackingDemo/test_MOT16-01.avi: 384x640 7 persons, Done. YOLO:(0.018s), DeepSort:(0.136s)
    video 1/1 (67/450) /home/zhr/zhr_file/MOT_trackingDemo/test_MOT16-01.avi: 384x640 8 persons, Done. YOLO:(0.019s), DeepSort:(0.139s)
    video 1/1 (68/450) /home/zhr/zhr_file/MOT_trackingDemo/test_MOT16-01.avi: 384x640 8 persons, Done. YOLO:(0.018s), DeepSort:(441.283s)

    ② 现象——kf.predict() 预测环节中的不合理之处:这些track基本上只出现过一次,没有过匹配,也没有被删除。且track的残差协方差巨大。
                   残差协方差的predict过程中,过程噪声processNoiseCov Qn与状态变量强相关,不符合kalman的基本假设!
    ————『作者设计意图&根据未知

    同时,由于track.mean的速度部分只有第一次初始化为0,所以mean一直原地踏步,没有速度增量。一旦不被匹配,一直不会被update更新,将一直停留在原地。

    ③ 级联匹配逻辑:cascade_depth为max_age

     由于time_since_update即,目标连续XXX帧无匹配,就不进入cost Matrix计算。

    def matching_cascade(
            distance_metric, max_distance, cascade_depth, tracks, detections,
            track_indices=None, detection_indices=None):
       # cascade_depth = self.max_age   # 30
        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


    命令行参数设置:

     parser = argparse.ArgumentParser()
        # 检测模型:模型位置,放在当前 Yolov5_DeepSort_Pytorch 目录下就可以了
        parser.add_argument('--yolo_model', nargs='+', type=str, default='yolov5m.pt', help='model.pt path(s)')
        # ReID模型
        parser.add_argument('--deep_sort_model', type=str, default='osnet_ibn_x1_0_MSMT17')
        # 视频输入:img/video、camera
        parser.add_argument('--source', type=str, default='0', help='source')  # file/folder, 0 for webcam
        # 输出文件地址,推理output
        parser.add_argument('--output', type=str, default='inference/output', help='output folder')  # output folder
        # 推理图像尺寸设置
        parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640], help='inference size h,w')
        # 目标置信度阈值筛选
        parser.add_argument('--conf-thres', type=float, default=0.5, help='object confidence threshold')
        # NMS的IOU阈值设置
        parser.add_argument('--iou-thres', type=float, default=0.5, help='IOU threshold for NMS')
        # 输出视频格式设置
        parser.add_argument('--fourcc', type=str, default='mp4v', help='output video codec (verify ffmpeg support)')
        # GPU/CPU设置
        parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
        # 是否展示tracking结果
        parser.add_argument('--show-vid', action='store_true', help='display tracking video results')
        # 是否存储视频跟踪结果
        parser.add_argument('--save-vid', action='store_true', help='save video tracking results')
        # 是否保存跟踪结果
        parser.add_argument('--save-txt', action='store_true', help='save MOT compliant results to *.txt')
        # 检测类别筛选:class 0 is person, 1 is bycicle, 2 is car... 79 is oven
        parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 16 17')
        # 
        parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
        parser.add_argument('--augment', action='store_true', help='augmented inference')
        parser.add_argument('--evaluate', action='store_true', help='augmented inference')
        parser.add_argument("--config_deepsort", type=str, default="deep_sort/configs/deep_sort.yaml")
        parser.add_argument("--half", action="store_true", help="use FP16 half-precision inference")
        parser.add_argument('--visualize', action='store_true', help='visualize features')
        parser.add_argument('--max-det', type=int, default=1000, help='maximum detection per image')
        # 使用opencv dnn for ONNX 推理
        parser.add_argument('--dnn', action='store_true', help='use OpenCV DNN for ONNX inference')
        # 工程保存到runs/track/文件夹下
        parser.add_argument('--project', default=ROOT / 'runs/track', help='save results to project/name')
        parser.add_argument('--name', default='exp', help='save results to project/name')
        # 就在已有的目录下,不要新建目录
        parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
    
    # 模型位置,yolov5m.pt放在当前 Yolov5_DeepSort_Pytorch 目录下就可以了,其余参数设置如下
    --source ../../MOT_trackingDemo/test_MOT16-03.avi --show-vid --exist-ok --class 0

    输出结果如下:(模型读入成功)

    # 输出的结果如下:
    Available ReID models for automatic download
    ['resnet50_market1501', 'resnet50_dukemtmcreid', 'resnet50_msmt17', 'resnet50_fc512_market1501', 'resnet50_fc512_dukemtmcreid', 'resnet50_fc512_msmt17', 'mlfn_market1501', 'mlfn_dukemtmcreid', 'mlfn_msmt17', 'hacnn_market1501', 'hacnn_dukemtmcreid', 'hacnn_msmt17', 'mobilenetv2_x1_0_market1501', 'mobilenetv2_x1_0_dukemtmcreid', 'mobilenetv2_x1_0_msmt17', 'mobilenetv2_x1_4_market1501', 'mobilenetv2_x1_4_dukemtmcreid', 'mobilenetv2_x1_4_msmt17', 'osnet_x1_0_market1501', 'osnet_x1_0_dukemtmcreid', 'osnet_x1_0_msmt17', 'osnet_x0_75_market1501', 'osnet_x0_75_dukemtmcreid', 'osnet_x0_75_msmt17', 'osnet_x0_5_market1501', 'osnet_x0_5_dukemtmcreid', 'osnet_x0_5_msmt17', 'osnet_x0_25_market1501', 'osnet_x0_25_dukemtmcreid', 'osnet_x0_25_msmt17', 'resnet50_MSMT17', 'osnet_x1_0_MSMT17', 'osnet_x0_75_MSMT17', 'osnet_x0_5_MSMT17', 'osnet_x0_25_MSMT17', 'osnet_ibn_x1_0_MSMT17', 'osnet_ain_x1_0_MSMT17']
    YOLOv5 🚀 v6.1-38-g7c6a335 torch 1.11.0+cu102 CUDA:0 (NVIDIA GeForce RTX 2060, 5926MiB)
    
    Model: osnet_ibn_x1_0
    - params: 2,194,640
    - flops: 978,878,352
    Successfully loaded pretrained weights from "deep_sort/deep/checkpoint/osnet_ibn_x1_0_MSMT17.pth"
    ** The following layers are discarded due to unmatched keys or layer size: ['classifier.weight', 'classifier.bias']
    YOLOv5 🚀 v6.1-38-g7c6a335 torch 1.11.0+cu102 CUDA:0 (NVIDIA GeForce RTX 2060, 5926MiB)

    二、MOT eval

    1. 下载模型:参考 https://github.com/mikel-brostrom/Yolov5_DeepSort_OSNet/wiki/Evaluation,下载地址为:https://drive.google.com/file/d/1gglIwqxaH2iTvy6lZlXuAcMpd_U0GCUb/view谷歌网盘地址。如果有需要,我之后可以放在百度云盘里面。
      下载crowdhuman_yolov5m.pt到yolov5/weights的文件夹中
    2. git clone https://github.com/JonathonLuiten/TrackEval
    3. 下载data.zip到Yolov5_Deepsort_Pytorch主文件夹中,data.zip的下载地址为:https://omnomnom.vision.rwth-aachen.de/data/TrackEval/data.zip
    4. 下载MOT16.zip到Yolov5_Deepsort_Pytorch主文件夹中,MOT16.zip的下载地址为:https://motchallenge.net/data/MOT16.zip
    5. Yolov5_DeepSort_Pytorch文件夹下:运行命令    ./MOT_eval/eval.sh

     MOT16 评估中:

    继续跑,最后看结果和效果。是否有result统计,以及参数统计的结果。

    遇到的傻问题:运行完了之后,该存的数据不知道存到哪里去了。郁闷了好久。

    结果发现是脚本的问题,MOT16_eval/eval.sh,仔细看里面的脚本,里面的路径是作者设置好了的!!!!

    所以最后去了作者事先设置好了的路径下面了。


    $ python ~/Yolov5_DeepSort_OSNet/MOT16_eval/TrackEval/scripts/run_mot_challenge.py --BENCHMARK MOT16  --TRACKERS_TO_EVAL ch_yolov5m_deep_sort --SPLIT_TO_EVAL train --METRICS CLEAR Identity  --USE_PARALLEL False --NUM_PARALLEL_CORES 4
    
    Eval Config:
    USE_PARALLEL         : False                         
    NUM_PARALLEL_CORES   : 4                             
    BREAK_ON_ERROR       : True                          
    RETURN_ON_ERROR      : False                         
    LOG_ON_ERROR         : /home/zhr/Yolov5_DeepSort_OSNet/MOT16_eval/TrackEval/error_log.txt
    PRINT_RESULTS        : True                          
    PRINT_ONLY_COMBINED  : False                         
    PRINT_CONFIG         : True                          
    TIME_PROGRESS        : True                          
    DISPLAY_LESS_PROGRESS : False                         
    OUTPUT_SUMMARY       : True                          
    OUTPUT_EMPTY_CLASSES : True                          
    OUTPUT_DETAILED      : True                          
    PLOT_CURVES          : True                          
    
    MotChallenge2DBox Config:
    PRINT_CONFIG         : True                          
    GT_FOLDER            : /home/zhr/Yolov5_DeepSort_OSNet/MOT16_eval/TrackEval/data/gt/mot_challenge/
    TRACKERS_FOLDER      : /home/zhr/Yolov5_DeepSort_OSNet/MOT16_eval/TrackEval/data/trackers/mot_challenge/
    OUTPUT_FOLDER        : None                          
    TRACKERS_TO_EVAL     : ['ch_yolov5m_deep_sort']      
    CLASSES_TO_EVAL      : ['pedestrian']                
    BENCHMARK            : MOT16                         
    SPLIT_TO_EVAL        : train                         
    INPUT_AS_ZIP         : False                         
    DO_PREPROC           : True                          
    TRACKER_SUB_FOLDER   : data                          
    OUTPUT_SUB_FOLDER    :                               
    TRACKER_DISPLAY_NAMES : None                          
    SEQMAP_FOLDER        : None                          
    SEQMAP_FILE          : None                          
    SEQ_INFO             : None                          
    GT_LOC_FORMAT        : {gt_folder}/{seq}/gt/gt.txt   
    SKIP_SPLIT_FOL       : False                         
    
    CLEAR Config:
    METRICS              : ['CLEAR', 'Identity']         
    THRESHOLD            : 0.5                           
    PRINT_CONFIG         : True                          
    
    Identity Config:
    METRICS              : ['CLEAR', 'Identity']         
    THRESHOLD            : 0.5                           
    PRINT_CONFIG         : True                          
    
    Evaluating 1 tracker(s) on 7 sequence(s) for 1 class(es) on MotChallenge2DBox dataset using the following metrics: CLEAR, Identity, Count
    
    
    Evaluating ch_yolov5m_deep_sort
    
        MotChallenge2DBox.get_raw_seq_data(ch_yolov5m_deep_sort, MOT16-02)     0.2778 sec
        MotChallenge2DBox.get_preprocessed_seq_data(pedestrian)                0.2561 sec
        CLEAR.eval_sequence()                                                  0.0542 sec
        Identity.eval_sequence()                                               0.0127 sec
        Count.eval_sequence()                                                  0.0000 sec
    1 eval_sequence(MOT16-02, ch_yolov5m_deep_sort)                          0.6029 sec
        MotChallenge2DBox.get_raw_seq_data(ch_yolov5m_deep_sort, MOT16-04)     1.1343 sec
        MotChallenge2DBox.get_preprocessed_seq_data(pedestrian)                0.5486 sec
        CLEAR.eval_sequence()                                                  0.1355 sec
        Identity.eval_sequence()                                               0.0331 sec
        Count.eval_sequence()                                                  0.0000 sec
    2 eval_sequence(MOT16-04, ch_yolov5m_deep_sort)                          1.8559 sec
        MotChallenge2DBox.get_raw_seq_data(ch_yolov5m_deep_sort, MOT16-05)     0.1684 sec
        MotChallenge2DBox.get_preprocessed_seq_data(pedestrian)                0.3186 sec
        CLEAR.eval_sequence()                                                  0.0646 sec
        Identity.eval_sequence()                                               0.0176 sec
        Count.eval_sequence()                                                  0.0000 sec
    3 eval_sequence(MOT16-05, ch_yolov5m_deep_sort)                          0.5716 sec
        MotChallenge2DBox.get_raw_seq_data(ch_yolov5m_deep_sort, MOT16-09)     0.1236 sec
        MotChallenge2DBox.get_preprocessed_seq_data(pedestrian)                0.2047 sec
        CLEAR.eval_sequence()                                                  0.0442 sec
        Identity.eval_sequence()                                               0.0105 sec
        Count.eval_sequence()                                                  0.0000 sec
    4 eval_sequence(MOT16-09, ch_yolov5m_deep_sort)                          0.3847 sec
        MotChallenge2DBox.get_raw_seq_data(ch_yolov5m_deep_sort, MOT16-10)     0.1991 sec
        MotChallenge2DBox.get_preprocessed_seq_data(pedestrian)                0.2612 sec
        CLEAR.eval_sequence()                                                  0.0573 sec
        Identity.eval_sequence()                                               0.0138 sec
        Count.eval_sequence()                                                  0.0000 sec
    5 eval_sequence(MOT16-10, ch_yolov5m_deep_sort)                          0.5336 sec
        MotChallenge2DBox.get_raw_seq_data(ch_yolov5m_deep_sort, MOT16-11)     0.1906 sec
        MotChallenge2DBox.get_preprocessed_seq_data(pedestrian)                0.3497 sec
        CLEAR.eval_sequence()                                                  0.0705 sec
        Identity.eval_sequence()                                               0.0178 sec
        Count.eval_sequence()                                                  0.0000 sec
    6 eval_sequence(MOT16-11, ch_yolov5m_deep_sort)                          0.6315 sec
        MotChallenge2DBox.get_raw_seq_data(ch_yolov5m_deep_sort, MOT16-13)     0.2175 sec
        MotChallenge2DBox.get_preprocessed_seq_data(pedestrian)                0.2918 sec
        CLEAR.eval_sequence()                                                  0.0607 sec
        Identity.eval_sequence()                                               0.0149 sec
        Count.eval_sequence()                                                  0.0000 sec
    7 eval_sequence(MOT16-13, ch_yolov5m_deep_sort)                          0.5873 sec
    
    All sequences for ch_yolov5m_deep_sort finished in 5.17 seconds
    
    CLEAR: ch_yolov5m_deep_sort-pedestrianMOTA      MOTP      MODA      CLR_Re    CLR_Pr    MTR       PTR       MLR       sMOTA     CLR_TP    CLR_FN    CLR_FP    IDSW      MT        PT        ML        Frag      
    MOT16-02                           33.034    77.764    33.78     37.251    91.476    16.667    37.037    46.296    24.751    6643      11190     619       133       9         20        25        245       
    MOT16-04                           63.698    76.456    63.97     72.023    89.943    42.169    40.964    16.867    46.741    34252     13305     3830      129       35        34        14        387       
    MOT16-05                           58.17     78.043    59.695    71.003    86.262    36        52        12        42.579    4841      1977      771       104       45        65        15        154       
    MOT16-09                           61.975    83.36     63.23     76.431    85.272    60        36        4         49.256    4018      1239      694       66        15        9         1         76        
    MOT16-10                           52.874    76.762    54.067    59.19     92.035    25.926    50        24.074    39.119    7291      5027      631       147       14        27        13        308       
    MOT16-11                           66.296    85.093    66.721    78.777    86.727    50.725    33.333    15.942    54.553    7227      1947      1106      39        35        23        11        66        
    MOT16-13                           38.262    74.881    39.17     45.197    88.235    16.822    45.794    37.383    26.909    5175      6275      690       104       18        49        40        260       
    COMBINED                           54.692    77.905    55.346    62.901    89.277    33.075    43.907    23.017    40.794    69447     40960     8341      722       171       227       119       1496      
    
    Identity: ch_yolov5m_deep_sort-pedestrianIDF1      IDR       IDP       IDTP      IDFN      IDFP      
    MOT16-02                           31.815    22.385    54.971    3992      13841     3270      
    MOT16-04                           63.189    56.894    71.049    27057     20500     11025     
    MOT16-05                           57.49     52.405    63.667    3573      3245      2039      
    MOT16-09                           51.6      48.925    54.584    2572      2685      2140      
    MOT16-10                           54.536    44.804    69.667    5519      6799      2403      
    MOT16-11                           62.204    59.353    65.343    5445      3729      2888      
    MOT16-13                           44.828    33.895    66.172    3881      7569      1984      
    COMBINED                           55.303    47.134    66.898    52039     58368     25749     
    
    Count: ch_yolov5m_deep_sort-pedestrianDets      GT_Dets   IDs       GT_IDs    
    MOT16-02                           7262      17833     62        54        
    MOT16-04                           38082     47557     118       83        
    MOT16-05                           5612      6818      103       125       
    MOT16-09                           4712      5257      40        25        
    MOT16-10                           7922      12318     84        54        
    MOT16-11                           8333      9174      107       69        
    MOT16-13                           5865      11450     74        107       
    COMBINED                           77788     110407    588       517       
    
    Timing analysis:
    MotChallenge2DBox.get_raw_seq_data                                     2.3113 sec
    MotChallenge2DBox.get_preprocessed_seq_data                            2.2309 sec
    CLEAR.eval_sequence                                                    0.4870 sec
    Identity.eval_sequence                                                 0.1204 sec
    Count.eval_sequence                                                    0.0000 sec
    eval_sequence                                                          5.1675 sec
    Evaluator.evaluate                                                     5.1695 sec
    

    https://github.com/mikel-brostrom/Yolov5_DeepSort_OSNet/wiki/Evaluation

     作者给出的结果是:

    数据基本上对应的上,我跑出来的指标略有下降。

     

    三、新版本的代码阅读分析

    GitHub - mikel-brostrom/Yolov5_DeepSort_OSNet: Real-time multi-camera multi-object tracker using YOLOv5 and Deep SORT with OSNet

    源码仓库地址: https://github.com/mikel-brostrom/Yolov5_DeepSort_OSNet

     3.1 新建track时,kalman filter的初始化 covariance跟bbox本身息息相关

     3.2 kalman filter predict 所有的track的kf都会predict

    预测: 残差协方差的迭代过程——就是越加越多。

     

     

    展开全文
  • 项目简介: 代码地址: github地址:...本项目使用deepsort+cpp+tensorrt实现tracking,使用c++实现,并用tensorrt加速。 效果 可以参考我的yolov5-deepsort-tensorrt文章,yolov5-dee
  • yolov5+Deepsort实现目标跟踪

    万次阅读 热门讨论 2022-01-19 21:34:37
    pytorch yolo5+Deepsort实现目标检测和跟踪 工程落地 YoloV5 + deepsort + Fast-ReID 完整行人重识别系统(三) yolov5-deepsort-pedestrian-counting Yolov5-Deepsort-Fastreid 二、相关介绍 Deepsort是实现目标...
  • 目标跟踪——Deep Sort算法原理浅析

    千次阅读 2022-04-06 16:00:14
    目标跟踪——DeepSort算法原理浅析 文章目录目标跟踪文章目录前言多目标跟踪主要流程DeepSort总结 前言 背景:DeepSort是基于Sort目标跟踪进行的改进,它引入深度学习模型,在实时目标跟踪过程中,提取目标的外观...
  • DeepSORT C++版的一个bug

    千次阅读 2021-12-11 17:51:15
    DeepSORT的官方python版实现是https://github.com/nwojke/deep_sort,C++版的DeepSORT中https://github.com/shaoshengsong/DeepSORT这个版本实现较早,github上可以看到不少人的DeepSORT都是在这个版本上做的集成和...
  • DeepSort+YOLOv3的多目标跟踪开源项目及deepsort原理

    万次阅读 多人点赞 2019-07-25 10:56:31
    DeepSort+YOLOv3的多目标跟踪开源项目及deepsort原理 目录 链接 Sort 卡尔曼滤波简单解释 匈牙利算法简单解释 DeepSort DeepSort相比于Sort改进的地方 YOLOv3+DeepSort 链接 本文来源:...
  • 一、DeepSort介绍 论文地址: https://arxiv.org/pdf/1703.07402.pdf 参考文章: DeepSort讲解 代码地址: https://github.com/mikel-brostrom/Yolov5_DeepSort_OSNet(可参考这个源代码,如果需要我这边的源代码可...
  • YOLOv5+DeepSORT多目标跟踪与计数精讲 以上就是课程YOLOv5+DeepSORT多目标跟踪与计数精讲的介绍与目录
  • [MOT] DeepSORT简单理解

    千次阅读 2022-02-04 18:39:17
    DeepSORT是一种tracking_by_detection框架的算法 虽然性能一般,但速度不错,GitHub上有很多基于不同检测器的实现 而且JDE、FairMOT、CSTrack等JDE的追踪器,匹配思路其实都是DeepSORT的思路 给出yolov3、yolov...
  • reid笔记 yolov5 deepsort

    千次阅读 2021-10-08 22:24:56
    YoloV5 + deepsort + Fast-ReID 完整行人重识别系统(三)_zengwb的博客-CSDN博客 改进点:将deepsor的表征提取模型替换成了fastreid训练的reid模型。能够提升跟踪性能。 yolov5 + deepsort顺带实现了行人计数功能...
  • 多目标跟踪yolov5+deep sort转ncnn调用

    千次阅读 2021-11-30 14:53:54
    Qt,ncnn,opencv调用yolov5+deep sort
  • 目标追踪---deepsort训练特征提取网络模型

    千次阅读 多人点赞 2021-09-13 22:17:38
    deepsort之所以可以大量避免IDSwitch,是因为deepsort算法中特征提取网络可以将目标检测框中的特征提取出来并保存,在目标被遮挡后又从新出现后,利用前后的特征对比可以将遮挡的后又出现的目标和遮挡之前的追踪的...
  • python车流量检测车流统计车辆计数yolov5 deepsort车流检测配置gpu和训练模型视频教程 项目下载:https://download.csdn.net/download/babyai996/85020479
  • 在这里简单概述一下目标检测算法:主要分为传统的目标跟踪算法,基于深度学习的目标跟踪算法、也可以分为基于检测的目标跟踪算法(目标检测网络+跟踪部分yolov3/yolov5+deepsort/sort),基于孪生网络的跟踪算法...
  • ​多目标跟踪,在DeepSORT提出之前是SORT算法(SORT论文链接),但是它对身份变换的问题,仅仅采取框和框之间距离的匹配方式,没有考虑框内的内容,所以容易发生ID-switch,不过这个问题已经在2017年的论文中进行了...
  • Deep sort算法代码解读

    万次阅读 多人点赞 2019-08-05 21:04:19
    重新排版太烦了,word写完直接截图过来了.....
  • YOLOX+Deepsort 实现多目标追踪

    千次阅读 热门讨论 2021-08-03 17:02:43
    使用YOLOX+Deepsort实现车辆行人追踪和计数,代码封装成一个Detector类,更容易嵌入到自己的项目中。 代码地址(欢迎star): https://github.com/Sharpiless/yolox-deepsort 最终效果: 运行demo: python demo.py...
  • DeepSort 解读

    千次阅读 2020-05-26 17:49:28
    最详细DeepSort论文解读 ...
  • 训练车辆的Deepsort深度模型记录

    万次阅读 多人点赞 2019-10-11 10:25:32
    DeepSORT的深度外观模型是在人的重识别数据集上训练得到的,在用于人的多目标跟踪效果好,用于车辆就不一定适用,所以要训练适用于车辆的深度外观模型。 下面是我参考的训练方法的链接,在此基础上记录我的训练过程...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,293
精华内容 917
热门标签
关键字:

deep sort csdn