deepSORT对低帧率视频的追踪,纯代码

deepSORT依据的是两个匹配机制,马氏距离下的特征层匹配以及IOU匹配,而当IOU匹配失去作用时,也就是多目标追踪任务中目标帧与帧之间差距较大而使得IOU匹配无法实现时,就需要考虑将其替换成其他的匹配机制,比如欧氏距离匹配

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


        matches=matches_a
        unmatched_tracks=list(set(unmatched_tracks_a+iou_track_candidates))
        #欧氏距离匹配
        Euclidean_distance_candidates=unmatched_tracks
        matches_c, unmatched_tracks_c, unmatched_detections = \
            linear_assignment.min_cost_matching(
                iou_matching.Euclidean_distance_cost, self.max_iou_distance, self.tracks,
                detections, Euclidean_distance_candidates, unmatched_detections)
        matches+=matches_c
        unmatched_tracks=list(set(unmatched_tracks_c))

Euclidean_cost_matching是欧氏距离的方法

修改的位置在deep_sort_pytorch/deep_sort/sort/tracker.py

track属性相关修改

在原本的 deepSORT 中是没有 detection 这个属性的,我们需要在 track 中增加这一属性,来对后续的欧氏距离匹配铺路,在这里,唯一的改动只是增加了一个 detection 的属性

    def __init__(self, mean, covariance, track_id, n_init, max_age,
                 feature=None):
        self.mean = mean
        self.covariance = covariance
        self.track_id = track_id
        self.hits = 1
        self.age = 1
        self.time_since_update = 0

        self.state = TrackState.Tentative
        self.features = []
        if feature is not None:
            self.features.append(feature)
        self.detections = []

        self._n_init = n_init
        self._max_age = max_age

之后需要在 track 的更新函数中将每一帧检测匹配上的 detection 加上去。

    def update(self, kf, detection):
        """Perform Kalman filter measurement update step and update the feature
        cache.

        Parameters
        ----------
        kf : kalman_filter.KalmanFilter
            The Kalman filter.
        detection : Detection
            The associated detection.

        """

        self.mean, self.covariance = kf.update(
            self.mean, self.covariance, detection.to_xyah())
        self.features.append(detection.feature)

        self.detections.append(detection)

        self.hits += 1
        self.time_since_update = 0
        if self.state == TrackState.Tentative and self.hits >= self._n_init:
            self.state = TrackState.Confirmed

 欧氏距离匹配代码增加

由于是将IOU匹配替换成了欧氏距离匹配,所以在 deep_sort_pytorch/deep_sort/sort/iou_matching.py中增加方法 Euclidean_distance_cost

def Euclidean_distance(bbox,candidates):
    bbox_cx=bbox[0]+bbox[2]/2
    bbox_cy=bbox[1]+bbox[3]/2
    candidates_cx=candidates[:,0]+candidates[:,2]/2
    candidates_cy=candidates[:,1]+candidates[:,3]/2
    distance=np.sqrt((candidates_cx[:]-bbox_cx)**2+(candidates_cy-bbox_cy)**2)
    return distance
def Euclidean_distance_cost(tracks, detections, track_indices=None,
             detection_indices=None):
    if track_indices is None:
        track_indices = np.arange(len(tracks))
    if detection_indices is None:
        detection_indices = np.arange(len(detections))

    cost_matrix=np.zeros((len(track_indices),len(detection_indices)))
    for row,track_idx in enumerate(track_indices):
        bbox=tracks[track_idx].to_tlwh()
        candidates=np.asarray(
            [detections[i].tlwh for i in detection_indices])
        cost_matrix[row,:]=Euclidean_distance(bbox,candidates)
    return cost_matrix

此函数返回的是距离矩阵

最后在距离 linear_assignment.py 下将iou匹配的阈值替换成合适的欧氏距离阈值

    if (len(cost_matrix_1)==2 and cost_matrix_1[1]!='cas') or len(cost_matrix_1)!=2 :
        #默认的是max_distance = 0.7
        # cost_matrix = cost_matrix_1
        # cost_matrix[cost_matrix > max_distance] = max_distance + 1e-5
        #使用欧氏距离替换iou
        cost_matrix = cost_matrix_1
        max_distance=50
        cost_matrix[cost_matrix > max_distance] = max_distance + 1e+5

如果是简单的修改能够使算法满足项目要求的话下半部分就不用去看了

欧氏距离下的路径规划

在实际的项目中,IOU发挥不了作用的情况下,欧氏距离匹配能够勉强发挥作用,但仍不能达到高帧数下的追踪效果

这种情况下就应该加入运动规划了,规范化目标的运行路径,使得不合理的匹配结果尽可能的少。

在这里就需要利用之前增加的 detection 属性了,修改如下

def Euclidean_distance(bbox,candidates):
    bbox_cx=bbox[0]+bbox[2]/2
    bbox_cy=bbox[1]+bbox[3]/2
    candidates_cx=candidates[:,0]+candidates[:,2]/2
    candidates_cy=candidates[:,1]+candidates[:,3]/2
    distance=np.sqrt((candidates_cx[:]-bbox_cx)**2+(candidates_cy-bbox_cy)**2)
    return distance

#距离长宽比矩阵
def distance_xy_a(bbox,candidates):
    #上一帧的位置
    bbox_cx = bbox[0]
    bbox_cy = bbox[1]
    candidates_cx=candidates[:,0]+candidates[:,2]/2
    candidates_cy=candidates[:,1]+candidates[:,3]/2
    juzhen=[]
    for i in range(len(candidates_cy)):
        # if abs(candidates_cx[i]-bbox_cx)>=10 and abs(candidates_cy[i]-bbox_cy)>=10 :
        #     juzhen.append(True)
        #     continue
        if abs(candidates_cy[i]-bbox_cy)>=50:
            juzhen.append(True)
            continue
        if candidates_cy[i]-bbox_cy<-20:
            juzhen.append(True)
            continue
        if candidates_cx[i]-bbox_cx<-10:
            juzhen.append(True)
            continue
        juzhen.append(False)
    return juzhen

def Euclidean_distance_cost(tracks, detections, track_indices=None,
             detection_indices=None):
    if track_indices is None:
        track_indices = np.arange(len(tracks))
    if detection_indices is None:
        detection_indices = np.arange(len(detections))

    cost_matrix=np.zeros((len(track_indices),len(detection_indices)))
    for row,track_idx in enumerate(track_indices):
        track=tracks[track_idx]
        bbox=tracks[track_idx].to_tlwh()
        candidates=np.asarray(
            [detections[i].tlwh for i in detection_indices])
        cost_matrix[row,:]=Euclidean_distance(bbox,candidates)
        if len(track.detections)!=0:
            ret=track.detections[-1].to_xyah()

            cost_matrix[row,distance_xy_a(ret,candidates)]+=1000

distance_xy_a是设定的路径规划,使得 ID 切换和 ID 丢失的情况尽可能的下降,可根据实际的项目进行修改

总结

以上就是对 deepSORT 进行的所有修改,能够有效的解决帧数过低或目标移动过快的问题,在实际的项目中效果良好,欢迎在评论指出并提出修改意见。

本人主要研究神经网络以及目标追踪,拥有爬虫、数据分析的项目经验,有需要的朋友可以联系。

群号 715269212

祝大家所愿皆成!

版权声明:本文为CSDN博主「山地车撒旦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sandichesadan/article/details/122454104

山地车撒旦

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

YOLO-V3-SPP详细解析

YOLO-V3-SPP 继前两篇简单的YOLO博文 YOLO-V1 论文理解《You Only Look Once: Unified, Real-Time Object Detection》YOLO-V2论文理解《YOLO9000: Bet

目标检测部署(卡牌识别)

最近在折腾yolov5,训练了一个识别纸牌的模型,最后使用onnxruntime进行部署,感兴趣的可以上github上clone下来玩玩,模型的权重文件上传到了百度网盘,链接

基于YOLOv5的垃圾目标检测

使用yolov5实现垃圾目标检测(有图形化界面,webapp)。 计算机视觉爱好者,有自己的算力(8块2080Ti),熟练运用pytorch深度学习框架&#x

YOLOX训练自己的数据

YOLOX是旷世开源的用于目标检测的算法,相比于YOLO(V3-V5)系列,在精度上有提升,速度上也具有一定的竞争优势。 介绍 YOLOX是YOLO的anchor-free版本,设计更