草庐IT

YOLOV7 + StrongSORT 实现目标检测与跟踪

迷途小书童的Note 2023-07-10 原文

环境

  • windows 10 64bit

  • python 3.8

  • pytorch1.7.1 + cu101

简介

前面,我们介绍过 基于YOLOv5和DeepSort的目标跟踪,最近大神又在刚出的 YOLOv7 的基础上加上了目标跟踪,跟踪部分使用的是基于 OSNetStrongSORT,项目地址: https://github.com/mikel-brostrom/Yolov7_StrongSORT_OSNet。

源码下载

首先去下载源码,目前作者已经发布了 v1.0 正式版,我们就用它

# 使用参数-b下载特定tag的源码,--recurse-submodules参数是为了递归下载根目录下的子项目,这里有yolov7,它是从官方的仓库fork而来,还有deep-person-reid,这种方式也是开源项目中非常常见的依赖管理模式
git clone --recurse-submodules https://github.com/mikel-brostrom/Yolov7_StrongSORT_OSNet.git -b v1.0

这里不建议直接去下载 zip 包,很多新手会碰到这个问题,然后就跑来问,运行程序的时候,为什么缺模块?这是因为,项目中包含了子项目,而子项目往往是一个链接,它并没有直接放到本项目中去管理维护,所以,下载的 zip 中并不包含子项目的源码。

如果因为网络原因,实在是 clone 不下来,可以参考下面的操作

找到对应的 tag 标签,比如现在的 v1.0 版本,然后点击进入对应版本的源码

然后下载 zip 压缩包

至于源码中的子项目,注意到,它的项目名后面带了一个 commit id,我们可以直接点击进去,下载 zip 压缩包进行解压。如果有多个子项目,就依次操作多次

安装项目依赖

下面来安装依赖

# 安装gpu版本的pytorch1.7.1,cuda10.1
pip install torch==1.7.1+cu101 torchvision==0.8.2+cu101 torchaudio==0.7.2 -f https://download.pytorch.org/whl/torch_stable.html

除此之外,将 requirements.txt 文件中的 torchtorchvision 注释掉,然后执行安装其它依赖

pip install -r requirements.txt

实践

环境准备好了,那就找个视频来跑跑看效果,执行

python track.py --source test.mp4 --strong-sort-weights osnet_x0_25_market1501.pt

这里是 source 可以是视频文件、摄像头 ID 或者网络视频(rtsphttphttps 都支持),参数 --strong-sort-weights 是指使用的 reid 重识别模型,模型可以到 https://kaiyangzhou.github.io/deep-person-reid/MODEL_ZOO 下载,这里的模型后缀是 pth,可以直接重命名为 pt

程序执行过程中,会去自动下载2个模型文件,一个是 yolov7的,另一个是你指定的 reid 模型,一个是存放的 github 上,下载后放在源码目录下的 weights 文件夹内;另一个是存放的 google 网盘里,下载后放在源码根目录下。

完整的 track.py 参数列表如下,除了 --strong-sort-weights--config-strongsort,其余都是 yolov7 支持的命令行参数

(pytorch1.7) PS D:\Github\Yolov7_StrongSORT_OSNet> python .\track.py -h
strong_sort/deep/reid\torchreid\metrics\rank.py:11: UserWarning: Cython evaluation (very fast so highly recommended) is unavailable, now use python evaluation.
  warnings.warn(                                                                                                                                               
usage: track.py [-h] [--yolo-weights YOLO_WEIGHTS [YOLO_WEIGHTS ...]] [--strong-sort-weights STRONG_SORT_WEIGHTS] [--config-strongsort CONFIG_STRONGSORT] [--source SOURCE] [--imgsz IMGSZ [IMGSZ ...]] 
                [--conf-thres CONF_THRES] [--iou-thres IOU_THRES] [--max-det MAX_DET] [--device DEVICE] [--show-vid] [--save-txt] [--save-conf] [--save-crop] [--save-vid] [--nosave]                   
                [--classes CLASSES [CLASSES ...]] [--agnostic-nms] [--augment] [--visualize] [--update] [--project PROJECT] [--name NAME] [--exist-ok] [--line-thickness LINE_THICKNESS] [--hide-labels]
                [--hide-conf] [--hide-class] [--half] [--dnn]                                                                                                                                           

optional arguments:
  -h, --help            show this help message and exit
  --yolo-weights YOLO_WEIGHTS [YOLO_WEIGHTS ...]
                        model.pt path(s)
  --strong-sort-weights STRONG_SORT_WEIGHTS
  --config-strongsort CONFIG_STRONGSORT
  --source SOURCE       file/dir/URL/glob, 0 for webcam
  --imgsz IMGSZ [IMGSZ ...], --img IMGSZ [IMGSZ ...], --img-size IMGSZ [IMGSZ ...]
                        inference size h,w
  --conf-thres CONF_THRES
  --classes CLASSES [CLASSES ...]
                        filter by class: --classes 0, or --classes 0 2 3
  --agnostic-nms        class-agnostic NMS
  --augment             augmented inference
  --visualize           visualize features
  --update              update all models
  --project PROJECT     save results to project/name
  --name NAME           save results to project/name
  --exist-ok            existing project/name ok, do not increment
  --line-thickness LINE_THICKNESS
                        bounding box thickness (pixels)
  --hide-labels         hide labels
  --hide-conf           hide confidences
  --hide-class          hide IDs
  --half                use FP16 half-precision inference
  --dnn                 use OpenCV DNN for ONNX inference

这里提几个比较常用的参数,检测时显示结果跟参数 --show-vid;保存结果跟参数 --save-vid;如果模型中包含多个目标,但实际只想检测某一个目标时,跟参数 --classes,它的值是目标的 id

Q & A

下面是常见的一些错误及解决方法

AttributeError: partially initialized module 'cv2' has no attribute 'gapi_wip_gst_GStreamerPipeline' (most likely due to a circular import)

升级 opencv-python,执行 pip install -U opencv-python

(pytorch1.7) PS D:\Github\Yolov7_StrongSORT_OSNet> python track.py --source test.mp4 --strong-sort-weights osnet_x0_25_market1501.pt
strong_sort/deep/reid\torchreid\metrics\rank.py:11: UserWarning: Cython evaluation (very fast so highly recommended) is unavailable, now use python evaluation.
  warnings.warn(                                                                                                                                               
Fusing layers... 
RepConv.fuse_repvgg_block
RepConv.fuse_repvgg_block
RepConv.fuse_repvgg_block
Model: osnet_x0_25
** The following layers are discarded due to unmatched keys or layer size: ['classifier.weight', 'classifier.bias']
(1, 256, 128, 3)
video 1/1 (1/7501) D:\Github\Yolov7_StrongSORT_OSNet\test.mp4: Traceback (most recent call last):
  File "track.py", line 332, in <module>
    main(opt)
  File "track.py", line 327, in main
    run(**vars(opt))
  File "D:\Tools\anaconda3\envs\pytorch1.7\lib\site-packages\torch\autograd\grad_mode.py", line 26, in decorate_context
    return func(*args, **kwargs)
  File "track.py", line 149, in run
    for frame_idx, (path, im, im0s, vid_cap) in enumerate(dataset):
  File "D:\Github\Yolov7_StrongSORT_OSNet\yolov7\utils\datasets.py", line 191, in __next__
    img = letterbox(img0, self.img_size, stride=self.stride)[0]
  File "D:\Github\Yolov7_StrongSORT_OSNet\yolov7\utils\datasets.py", line 1000, in letterbox
    dw, dh = np.mod(dw, stride), np.mod(dh, stride)  # wh padding
  File "D:\Tools\anaconda3\envs\pytorch1.7\lib\site-packages\torch\tensor.py", line 630, in __array__
    return self.numpy()
TypeError: can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.

修改 track.py 中的 loadImages 部分,将原来的

dataset = LoadImages(source, img_size=imgsz, stride=stride)

改为

dataset = LoadImages(source, img_size=imgsz, stride=stride.cpu().numpy())

可以参考官方 issue

下载

本文中使用的 v1.0 版本的完整工程,放在网盘里,方便大伙下载

链接:https://pan.baidu.com/s/1di_ju3JeoZDpnX3IuSBLlw
提取码:y3ib

参考资料

  • https://github.com/mikel-brostrom/Yolov7_StrongSORT_OSNet

  • https://github.com/mikel-brostrom/yolov7

  • https://github.com/WongKinYiu/yolov7

  • https://xugaoxiang.com/2019/12/18/windows-10-cuda-cudnn/

有关YOLOV7 + StrongSORT 实现目标检测与跟踪的更多相关文章

  1. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  2. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  3. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  4. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  5. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  6. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  7. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

  8. ruby - "public/protected/private"方法是如何实现的,我该如何模拟它? - 2

    在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定

  9. ruby - 检测由 RSpec、Ruby 运行的代码 - 2

    我想知道我的代码是否在rspec下运行。这可能吗?原因是我正在加载一些错误记录器,这些记录器在测试期间会被故意错误(expect{x}.toraise_error)弄得乱七八糟。我查看了我的ENV变量,没有(明显的)测试环境变量的迹象。 最佳答案 在spec_helper.rb的开头添加:ENV['RACK_ENV']='test'现在您可以在代码中检查RACK_ENV是否经过测试。 关于ruby-检测由RSpec、Ruby运行的代码,我们在StackOverflow上找到一个类似的问题

  10. ruby - 使用 Ruby Daemons gem 检测停止 - 2

    我正在使用rubydaemongem。想知道如何向停止操作添加一些额外的步骤?希望我能检测到停止被调用,并向其添加一些额外的代码。任何人都知道我如何才能做到这一点? 最佳答案 查看守护程序gem代码,它似乎没有用于此目的的明显扩展点。但是,我想知道(在守护进程中)您是否可以捕获守护进程在发生“停止”时发送的KILL/TERM信号...?trap("TERM")do#executeyourextracodehereend或者你可以安装一个at_exit钩子(Hook):-at_exitdo#executeyourextracodehe

随机推荐