yolov5+Deepsort目标检测加目标跟踪算法(附代码)


前言

近期实习项目可能需要目标跟踪,所以学习了一下目标跟踪算法,并根据了解到的算法,在github上寻找项目直接上手验证。


更新

1、如果出现这个问题

    return _VF.meshgrid(tensors, **kwargs, indexing = 'ij')  # type: ignore[attr-defined]
TypeError: meshgrid() got multiple values for keyword argument 'indexing'

删除indexing = 'ij即可,即变为。return _VF.meshgrid(tensors, **kwargs)
2、嵌入自己任意版本的yolo中。请查看最新的方法。
https://blog.csdn.net/qq_45874142/article/details/132586026?spm=1001.2014.3001.5501

一、目标跟踪算法选择

看了一些综述,发现每个人的分类都不太一样,而且分的很详细,就连传统机器学习里面的方法都提出来了。看的甚是头大,我看了一天,晚上头疼死了。如果直接奔着项目来上手,那就简单多了,目前多用的是深度学习yolov5,因此,找了深度学习方向的目标跟踪,同样很多算法,但大家常用的,资源最多的,还是用Deepsort算法。原理自己去找吧,涉及到卡尔曼和匈牙利算法。
这有几个链接可以参考(我后面可能深入的话也需要细看,就做个笔记记录一下):
Deep sort算法代码解读(这个最详细,但很不友好)
Deepsort-Yolov3目标跟踪相关学习
YOLOv8 + DeepSORT | YOLO与DeepSORT跟踪的难分难舍,直接用吧(附源码)

二、直接上手

1.找资源

这个目标跟踪代码有很多,但都是参考这个大牛的,大牛主页:https://github.com/mikel-brostrom

在这里插入图片描述
但这个我下载后,不会用。我小白,抱歉了。这个貌似是已经更新过了。看很多人参考的代码,并不是这个更新的,而是之前的版本,之前的版本貌似只有gitcode上有。
mirrors / mikel-brostrom / Yolov5_DeepSort_Pytorch
在这里插入图片描述

还有很多资源,大多都是要么需要私信、一键三连,甚至有收费29.9的,恶心心,可怕怕。如果加上轨迹跟踪,基本网上没有。所以我后面直接在github上找了。大概找了一些,并测试可用,然后就分享给大家。

2.测试代码1

这个资源是github上的,https://github.com/HowieMa/DeepSORT_YOLOv5_Pytorch

(1)检测效果

请添加图片描述

(2)评价

有显示检测帧率,标签只显示了ID,没有类别和概率,总体还不错。也没有轨迹显示。

3.测试代码2

资源地址:https://github.com/Sharpiless/yolov5-deepsort/

(1)检测效果

请添加图片描述

(2)评价

帧率打印输出是摄像头的帧率,没有推理的帧率。
增加了标签的类别显示。
把检测和其他模块都进行的打包,自己写一个demo进行掉包检测,上手简单,但不利于再次修改调用位置挺多。大佬能加上类别,也是挺厉害的。

(3)我的改进

我增加了平均帧率显示,把每帧的fps放进列表中,每20个计算一次平均值,每20次更新一次。
在detector里面的检测推理部分修改的。

def detect(self, im):
    im0, img = self.preprocess(im)
    t0 = time.time()  # 记录开始时间
    pred = self.m(img, augment=False)[0]
    pred = pred.float()
    pred = non_max_suppression(pred, self.threshold, 0.4)
    pred_boxes = []
    for det in pred:
        if det is not None and len(det):
            det[:, :4] = scale_coords(
                img.shape[2:], det[:, :4], im0.shape).round()
            for *x, conf, cls_id in det:
                lbl = self.names[int(cls_id)]
                if not lbl in ['person', 'car', 'truck']:
                    continue
                x1, y1 = int(x[0]), int(x[1])
                x2, y2 = int(x[2]), int(x[3])
                pred_boxes.append(
                    (x1, y1, x2, y2, lbl, conf))
    t1 = time.time()  # 记录结束时间
    fps = 1 / (t1 - t0)  # 计算帧率
    self.fps_list.append(fps)

    if len(self.fps_list) > 20:  # 保留最近的20个帧率数据
        self.fps_list.pop(0)
    self.fps_average = sum(self.fps_list) / len(self.fps_list)  # 计算平均帧率
    cv2.putText(im, f'Avg FPS: {self.fps_average:.2f}', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255),2)
    return im, pred_boxes

4.测试代码3

因为想要轨迹,所以我就一直在找有轨迹的代码,基本没有,好不容易找到一个
Deepsort跟踪算法画目标运动轨迹
我也做了相关的改进,下面的效果是我改进之后的效果。你可以自己改进,也可以直接用我的。注意这个代码是用的原来的yolov5,版本不知道,猜测是5.0以下。后续将替换为我们版本的yolov5,我用的是6.1版本。
我的仓库代码直达:https://github.com/zzzbut/Yolov5_DeepSort_Track

(1)检测效果

请添加图片描述

(2)评价

作者增加了轨迹,根据目标框计算的。
但是轨迹一直会留在图上,就算目标走了也会留着。颜色分配也不一致,是乱的。

(3)我的改进

根据ID分配颜色,颜色是一致的了。
轨迹限制最近的一段。
轨迹显示与目标框搭配,目标框在的时候,才显示轨迹,没有目标id,直接跳过显示,就不绘制。核心代码就是下面的。如果有需要的,我可近期挂github上,现在我还不会挂,近期应该要学习一下。
但我还没加上类别和置信度。这个我其实不太会加。有大佬可以一起交流一下。

# Pass detections to deepsort
 outputs = deepsort.update(xywhs, confss, im0)
 # outputs = [x1, y1, x2, y2, track_id]
 if len(outputs) > 0:
     bbox_xyxy = outputs[:, :4]  # 提取前四列  坐标
     identities = outputs[:, -1]  # 提取最后一列 ID
     draw_boxes(im0, bbox_xyxy, identities)

     box_xywh = xyxy2tlwh(bbox_xyxy)
     # xyxy2tlwh是坐标格式转换,从x1, y1, x2, y2转为top left x ,top left y, w, h 具体函数看文章最后
     for j in range(len(box_xywh)):
         x_center = box_xywh[j][0] + box_xywh[j][2] / 2  # 求框的中心x坐标
         y_center = box_xywh[j][1] + box_xywh[j][3] / 2  # 求框的中心y坐标
         id = outputs[j][-1]
         center = [x_center, y_center]
         dict_box.setdefault(id, []).append(center)  # 这个字典需要提前定义 dict_box = dict()
     # 以下为画轨迹,原理就是将前后帧同ID的跟踪框中心坐标连接起来
     if frame_idx > 2:  # 这里可以调整判断条件
         max_trajectory_length = 50  # 设置轨迹的最大长度
         temp_dict_box = dict_box.copy()  # 创建字典的副本
         for key, value in temp_dict_box.items():
             if key in identities:  # 判断目标是否存在
                 if len(value) > max_trajectory_length:  # 限制轨迹长度
                     value = value[-max_trajectory_length:]  # 截断保留最近的一部分轨迹
                 for a in range(len(value) - 1):
                     color = compute_color_for_labels(key)  # 使用固定颜色
                     index_start = a
                     index_end = index_start + 1
                     cv2.line(im0, tuple(map(int, value[index_start])),
                              tuple(map(int, value[index_end])),
                              color, thickness=5, lineType=8)
             else:
                 continue

三、总结

测试了三个目标跟踪的代码,总体效果不错,也做了适当的改进,比如加入平均帧率显示,加入轨迹线的一段显示和目标框消失即不显示。

附录(本文gif在线工具)

视频转gif工具:https://www.img2go.com/zh/convert-video-to-gif
gif压缩工具:https://gifcompressor.com/zh/

  • 16
    点赞
  • 119
    收藏
    觉得还不错? 一键收藏
  • 26
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值