这篇博客是上一篇博客的续集,所有测试和评测均基于第一篇刷机博客的环境上完成的测试。此篇博客对一些目标跟踪领域优秀的开源项目提供了在 Nvidia Jetson Thor 硬件平台上部署的参考操作。

系列博客如下:


DeepSORT

DeepSORT 是非常经典的基于深度学习的目标跟踪算法,尽管已经距今 8 年了,但仍然是很多 Paper 的 Benchmark。这一小节将对该算法在 Jetson Thor 设备上如何部署进行介绍。

该章节涉及到的模型资料我已经放到了网盘中,有需要的话自行提取:

通过网盘分享的文件:DeepSORT
链接: https://pan.baidu.com/s/1Segb58qz0hmdJ3EtQoBm1w?pwd=9rvs 提取码: 9rvs 
--来自百度网盘超级会员v5的分享

Step1. 拉取容器

因为 DeepSORT 使用了 Tensorflow 作为深度学习框架,并且制定了细分版本,实验室测试后得到 nvcr.io/nvidia/tensorflow:25.02-tf2-py3 容器是可以使用的:

$ docker pull nvcr.io/nvidia/tensorflow:25.02-tf2-py3

$ docker images

REPOSITORY                  TAG             IMAGE ID       CREATED         SIZE
nvcr.io/nvidia/tensorflow   25.02-tf2-py3   da00c18369f9   6 months ago    17.9GB

在这里插入图片描述


Step2. 创建工作空间并拉取源码

创建工作空间

这里为了和宿主机 Thor 传输文件方便,建议在宿主机上先创建一个文件夹并映射到容器中,此处以 Deskop/track_ws 为例:

$ cd Desktop
$ mkdir track_ws

拉取源码

进入工作空间 Deskop/track_ws 中拉取 DeepSORT 源码:

$ cd Desktop/track_ws
$ git clone https://github.com/nwojke/deep_sort.git

拉取预训练模型

为了运行官方示例还需要拉取对应资源,你可以通过官方提供的链接下载,也可以直接从我提供的网盘链接下载:

官方模型下载界面官方数据集下载界面网盘资源
在这里插入图片描述在这里插入图片描述在这里插入图片描述

下载好的数据与模型文件放置在如下位置,你需要在 deep_sort 新建 resources 和 MOT16 两个文件夹:

$ cd Desktop/track_ws/deep_sort
$ tree -L 2

在这里插入图片描述


Step3. 启动容器

【Note】:这里因为涉及到调用宿主机的显示功能,因此这一章节的操作都需要在宿主机的终端上完成,不能通过 SSH 完成;

启动容器

在启动容器之前需要先给宿主机终端进行显示授权:

$ sudo xhost +local:docker

然后使用下面的命令运行容器:

$ cd Desktop/track_ws

$ docker run -dit \
	--net=host \
	--runtime nvidia \
	--privileged \
	--ipc=host \
	-e DISPLAY=$DISPLAY \
	-v /tmp/.X11-unix:/tmp/.X11-unix \
	--ulimit memlock=-1 \
	--ulimit stack=67108864 \
	-v $(pwd):/workspace \
	nvcr.io/nvidia/tensorflow:25.02-tf2-py3 \
	bash

$ docker ps -a
$ docker exec -it relaxed_banach /bin/bash

在这里插入图片描述

安装依赖

因为这个容器中已经自带了 requirements-gpu.txt 文件中涉及到大部分第三方库,此处只需要手动安装特定的库即可:

$ pip install tf-slim  opencv-python==4.7.0.72

安装 libgl:

$ apt-get update
$ apt-get install libgl-dev -y

Step4. 运行示例

使用下面的代码运行官方提供的示例:

$ python deep_sort_app.py \
    --sequence_dir=./MOT16/test/MOT16-06 \
    --detection_file=./resources/detections/MOT16_POI_test/MOT16-06.npy \
    --min_confidence=0.3 \
    --nn_budget=100 \
    --display=True

启动后会有一个对应的弹窗,如果你启动后报了一个有关 Qt Plugin 的错误,那么说明 Step3 中启动时显示映射存在问题,仔细检查你的命令是否正确:

在这里插入图片描述


Step5. [可选] 保存容器

在完成配置并退出容器后,使用下面的命令提交并保存容为一个稳定镜像:

  1. 查看当前运行的容器:
$ docker ps -a
CONTAINER ID   IMAGE                                     COMMAND                  CREATED          STATUS          PORTS     NAMES
b1624bdb5e49   nvcr.io/nvidia/tensorflow:25.02-tf2-py3   "/opt/nvidia/nvidia_…"   35 minutes ago   Up 35 minutes             relaxed_banach
  1. 暂停当前运行的容器:
$ docker stop relaxed_banach
relaxed_banach
  1. 提交刚才运行的容器:
$ docker commit -a "GaohaoZhou" -m "DeepSORT-TF finished" b1624bdb5e49 deep-sort:tensorflow
sha256:81e4fe1592de3299e8ced165fa4d86256c5d1c6b5dc0f5281a34a896a4929322
  1. 查看当前存在的镜像:
$ docker images
REPOSITORY                  TAG             IMAGE ID       CREATED         SIZE
deep-sort                   tensorflow      81e4fe1592de   9 seconds ago   18.4GB
nvcr.io/nvidia/tensorflow   25.02-tf2-py3   da00c18369f9   6 months ago    17.9GB

在这里插入图片描述


Boxmot

Step1. 拉取容器

使用 nvcr.io/nvidia/pytorch:25.08-py3 容器:

$ docker pull nvcr.io/nvidia/pytorch:25.08-py3

查看容器列表:

$ docker images

在这里插入图片描述


Step2. 创建工作空间并拉取源码

创建工作空间

这里为了和宿主机 Thor 传输文件方便,建议在宿主机上先创建一个文件夹并映射到容器中,此处以 Deskop/track_ws 为例:

$ cd Desktop
$ mkdir track_ws

拉取源码

进入工作空间 Deskop/track_ws 中拉取 Boxmot 源码:

$ cd Desktop/track_ws
$ git clone https://github.com/mikel-brostrom/boxmot.git

拉取完之后需要修改 pyproject.toml 文件,将该文件中 opencv-python<5.0.0,>=4.7.0 和 pyqt5>=5.15.11 注释掉,分别在 127 和 133 行:

【Note】:虽然安装依赖文件中需要 pyqt,但实际工程中并没有导入这个包,此外还发现在容器中安装 pyqt 存在一些问题,好在不影响当前工程。

  "setuptools",
  "filterpy<2.0.0,>=1.4.5",
  "gdown<6.0.0,>=5.1.0",
  "lapx<1.0.0,>=0.5.5",
  "loguru<1.0.0,>=0.7.2",
  "numpy",
  "pyyaml<7.0.0,>=6.0.1",
  "regex<2025.0.0,>=2024.0.0",
  "yacs<1.0.0,>=0.1.8",
  "scikit-learn<2.0.0,>=1.3.0",
  "pandas<3.0.0,>=2.0.0", 
  # "opencv-python<5.0.0,>=4.7.0",
  "ftfy<7.0.0,>=6.1.3",
  "gitpython<4.0.0,>=3.1.42",
  "torch>=2.2.1,<3.0.0",
  "torchvision>=0.17.1,<1.0.0",
  "mplcursors>=0.6",
  # "pyqt5>=5.15.11",
  "bayesian-optimization>=2.0.4",
  "click>=8.1.8",
]

在这里插入图片描述


Step3. 启动容器

启动容器

使用下面的命令启动容器:

$ docker run -dit \
	--net=host \
	--runtime nvidia \
	--privileged \
	--ipc=host \
	--ulimit memlock=-1 \
	--ulimit stack=67108864 -v $(pwd):/workspace nvcr.io/nvidia/pytorch:25.08-py3 bash

然后查看正在运行的容器:

$ docker ps -a

CONTAINER ID   IMAGE                              COMMAND                  CREATED         STATUS         PORTS     NAMES
0bc8b56a67b7   nvcr.io/nvidia/pytorch:25.08-py3   "/opt/nvidia/nvidia_…"   6 minutes ago   Up 6 minutes             crazy_gould

在这里插入图片描述

进入刚刚启动的容器:

$ docker exec -it crazy_gould /bin/bash

在这里插入图片描述

安装依赖

在容器中依次执行以下命令:

  • 更新源并安装 libgl-dev:
$ apt-get update
$ apt-get install libgl-dev
  • 源码安装 boxmot 工程:
$ cd /workspace/boxmot/
$ pip install -e . 
  • 覆盖 opencv 与 numpy 到指定版本:
$ pip install numpy==1.26.4
$ pip install opencv-python==4.7.0.72

Step4. 运行示例

这里提供了一个示例文件,是我们在自动化大厦楼下拍摄的一段视频,不涉及任何版权问题可以随意使用,下载好的文件直接放在 boxmot 项目目录下即可:

通过网盘分享的文件:Action5Pro.mp4
链接: https://pan.baidu.com/s/1pNiMKy5WZHTul6zxTH0wZQ?pwd=bvix 提取码: bvix 
--来自百度网盘超级会员v5的分享

我们也提供了一个小脚本用来演示如何转换一个视频文件,将下面的脚本同样放在 boxmot 项目目录下:

import cv2
import torch
import numpy as np
from pathlib import Path
import argparse
import time  # 1. 导入 time 模块

from boxmot import BoostTrack
from torchvision.models.detection import (
    fasterrcnn_resnet50_fpn_v2,
    FasterRCNN_ResNet50_FPN_V2_Weights as Weights
)

# --- 1. 设置和解析命令行参数 ---
parser = argparse.ArgumentParser(description="使用 BoXMOT 和 Torchvision 对视频进行目标跟踪")
parser.add_argument(
    '-i', '--video_path',
    type=str,
    required=True,
    help="输入视频的文件路径 (例如: ./input.mp4)"
)
parser.add_argument(
    '-o', '--output_path',
    type=str,
    required=True,
    help="保存处理后视频的文件路径 (例如: ./output.mp4)"
)
args = parser.parse_args()

# --- 2. 使用从参数中获取的路径 ---
VIDEO_PATH = Path(args.video_path)
OUTPUT_PATH = Path(args.output_path)

# 确保输出目录存在
OUTPUT_PATH.parent.mkdir(parents=True, exist_ok=True)

# --- 3. 开始计时:模型加载 ---
print("正在加载模型...")
start_load_time = time.time()  # 记录模型加载开始时间

# Set device
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"使用设备: {device}")

# Load model with pretrained weights and preprocessing transforms
weights = Weights.DEFAULT
model = fasterrcnn_resnet50_fpn_v2(weights=weights, box_score_thresh=0.5)
model.to(device).eval()
transform = weights.transforms()

# Initialize tracker
tracker = BoostTrack(reid_weights=Path('osnet_x0_25_msmt17.pt'), device=device, half=False)

end_load_time = time.time()  # 记录模型加载结束时间
model_load_duration = end_load_time - start_load_time
print(f"模型加载完成。")

# --- 4. 视频输入(使用参数路径) ---
# 注意:cv2.VideoCapture() 本身很快,真正耗时的是 cap.read()
print(f"正在打开视频文件: {VIDEO_PATH}")
cap = cv2.VideoCapture(str(VIDEO_PATH))

if not cap.isOpened():
    print(f"Error: 无法打开视频文件 {VIDEO_PATH}")
    exit()

# --- 5. 视频输出(使用参数路径) ---
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)

fourcc = cv2.VideoWriter_fourcc(*'mp4v')
writer = cv2.VideoWriter(str(OUTPUT_PATH), fourcc, fps, (frame_width, frame_height))

print(f"开始处理视频...")
print(f"结果将保存至: {OUTPUT_PATH}")

# --- 6. 初始化统计变量 ---
total_frames = 0
total_processing_time = 0  # 仅用于检测和跟踪

# --- 7. 处理循环 ---
with torch.inference_mode():
    while True:
        # 视频帧读取 (这部分时间不计入检测耗时)
        success, frame = cap.read()
        if not success:
            print("视频处理完成。")
            break

        # 帧计数
        total_frames += 1

        # 开始计时 (单帧处理)
        start_frame_time = time.time()

        # Convert frame to RGB and prepare for model
        rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        tensor = torch.from_numpy(rgb).permute(2, 0, 1).to(torch.uint8)
        input_tensor = transform(tensor).to(device)

        # Run detection
        output = model([input_tensor])[0]
        scores = output['scores'].cpu().numpy()
        keep = scores >= 0.5

        # Prepare detections for tracking
        boxes = output['boxes'][keep].cpu().numpy()
        labels = output['labels'][keep].cpu().numpy()
        filtered_scores = scores[keep]
        detections = np.concatenate([boxes, filtered_scores[:, None], labels[:, None]], axis=1)

        # Update tracker and draw results
        res = tracker.update(detections, frame)
        tracker.plot_results(frame, show_trajectories=True)

        # 结束计时 (单帧处理)
        end_frame_time = time.time()
        total_processing_time += (end_frame_time - start_frame_time)

        # 写入帧 (这部分时间不计入检测耗时)
        writer.write(frame)

        # (可选) 实时显示输出
        # cv2.imshow('BoXMOT + Torchvision', frame)
        # if cv2.waitKey(1) & 0xFF == ord('q'):
        #     print("处理被用户终止。")
        #     break

# --- 8. 清理和释放资源 ---
cap.release()
writer.release()
cv2.destroyAllWindows()

print(f"视频已成功保存到 {OUTPUT_PATH}")

# --- 9. 打印统计结果 ---
print("\n--- 性能统计 ---")
print(f"模型加载耗时: {model_load_duration:.4f} 秒")
print(f"总 帧 数: {total_frames} 帧")

if total_frames > 0:
    avg_processing_time = total_processing_time / total_frames
    avg_fps = 1.0 / avg_processing_time if avg_processing_time > 0 else 0
    print(f"检测/跟踪总耗时: {total_processing_time:.4f} 秒")
    print(f"平均每帧耗时: {avg_processing_time:.4f} 秒 (约 {avg_fps:.2f} FPS)")
else:
    print("未处理任何帧。")

此时你的文件结构应该如下:

$ ll /workspace/boxmot/

在这里插入图片描述

运行转换脚本,这里由于为了写入到本地文件中将图像从 GPU 搬到 CPU 中,因此耗时较大:

$ python track.py -i Action5Pro.mp4 -o output.mp4

正在加载模型...
使用设备: cuda
模型加载完成。
正在打开视频文件: Action5Pro.mp4
开始处理视频...
结果将保存至: output.mp4
视频处理完成。
视频已成功保存到 output.mp4

--- 性能统计 ---
模型加载耗时: 0.6163 秒
总 帧 数: 310 帧
检测/跟踪总耗时: 34.2212 秒
平均每帧耗时: 0.1104 秒 (约 9.06 FPS)

最终效果如下:

在这里插入图片描述


Step5. [可选] 保存容器

保存容器核心为 3 步:

  1. 从容器中退出并暂停容器:
$ docker ps -a
$ docker stop crazy_gould

在这里插入图片描述

  1. 提交容器为镜像并打上自己的信息:
$ docker commit -a "GaohaoZhou" -m "Boxmot finished" 0bc8b56a67b7 boxmot

在这里插入图片描述

  1. 确保打包成功后退出终止容器:
$ docker images

REPOSITORY                  TAG             IMAGE ID       CREATED          SIZE
boxmot                      latest          61c48da57490   59 seconds ago   22.8GB
$ docker rm crazy_gould

在这里插入图片描述


ByteTrack

这个算法也是 2022 年的一个多目标跟踪 SOTA,也是应用比较广的算法;

Step1. 拉取容器

使用 nvcr.io/nvidia/pytorch:25.08-py3 容器:

$ docker pull nvcr.io/nvidia/pytorch:25.08-py3

查看容器列表:

$ docker images

REPOSITORY                  TAG             IMAGE ID       CREATED         SIZE
nvcr.io/nvidia/pytorch      25.08-py3       eeefcd24d725   5 weeks ago     21.9GB

在这里插入图片描述


Step2. 创建工作空间并拉取源码

创建工作空间

这里为了和宿主机 Thor 传输文件方便,建议在宿主机上先创建一个文件夹并映射到容器中,此处以 Deskop/track_ws 为例:

$ cd Desktop
$ mkdir track_ws

拉取源码

进入工作空间 Deskop/track_ws 中拉取 ByteTrack 源码:

$ cd Desktop/track_ws
$ git clone https://github.com/FoundationVision/ByteTrack.git

修改源码文件中的 requirements.txt 文件,注释掉 torch、numpy、opencv、onnx 相关的三行:

在这里插入图片描述

下载资源

作者在这里提供了多款开源数据集和模型资源,这里以 MOT20 数据集与模型为例,使用下面的链接或者从网盘中下载,你需要下载 MOT20.zip 和 bytetrack_x_mot20.tar 这两个文件:

将下载好的数据集解压后移动到 track_ws/ByteTrack/datasets 目录下;在 track_ws/ByteTrack 目录下新建一个 pretrained 文件夹用来存放模型,并将模型文件移动进去。此时你的 ByteTrack 文件结构应该如下:

$ tree -L 2

在这里插入图片描述


Step3. 启动容器

启动容器

进入到 track_ws 目录下启动容器:

$ docker run -dit \
	--net=host \
	--runtime nvidia \
	--privileged \
	--ipc=host \
	--ulimit memlock=-1 \
	--ulimit stack=67108864 -v $(pwd):/workspace nvcr.io/nvidia/pytorch:25.08-py3 bash

查看并进入容器:

$ docker ps -a

在这里插入图片描述

$ docker exec -it goofy_black /bin/bash

在这里插入图片描述

安装依赖

进入容器后进入到 track_ws/ByteTrack 目录安装依赖:

首先需要安装 libgl 库:

$ apt-get update
$ apt-get install libgl-dev -y

安装完成后手动安装 onnx 部分:

$ pip install onnx onnxruntime onnx-simplifier

为了使用 GPU 加速,还需要安装 onnxruntime-gpu 的轮子,在下面的网页中找到 JetPack 6.0 的轮子,经过实验测试是可以用的:

在这里插入图片描述

下载好后从宿主机复制到工作空间,然后在容器中安装:

$ pip install onnxruntime_gpu-1.17.0-cp310-cp310-linux_aarch64.whl

在这里插入图片描述

然后是 python 第三方依赖:

$ pip install numpy==1.23.5
$ pip install opencv-python==4.7.0.72 cpython_bbox
$ pip install -r requirements.txt

安装工程:

$ python3 setup.py develop

Step4. 运行示例

在运行模型推理之前还需要使用下面的命令将 MOT 数据集转换为 COCO 格式:

$ python3 tools/convert_mot20_to_coco.py

在这里插入图片描述

命令执行完成后会在 datasets/MOT20 目录下生成一个 annotations 文件夹,里面包含了以下几个文件:

$ ls ByteTrack/datasets/MOT20/annotations
total 327M
drwxr-xr-x 2 root root 4.0K Sep 16 13:02 ./
drwxrwx--- 5 thor thor 4.0K Sep 16 12:56 ../
-rw-r--r-- 1 root root 714K Sep 16 13:02 test.json
-rw-r--r-- 1 root root  75M Sep 16 12:57 train_half.json
-rw-r--r-- 1 root root 164M Sep 16 13:01 train.json
-rw-r--r-- 1 root root  89M Sep 16 12:59 val_half.json

在这里插入图片描述

在容器中执行以下命令运行示例:

$ python3 tools/track.py -f exps/example/mot/yolox_x_mix_mot20_ch.py -c pretrained/bytetrack_x_mot20.tar -b 1 -d 1 --fp16 --fuse --match_thresh 0.7 --mot20

在这里插入图片描述


Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐