照着做就能复刻

Jetson 人物检测 Demo 复刻手册

整理 2026-09-07 · 每一步都是 09-04~05 在设备上真实执行过的命令

整套系统 = 一台 Jetson + 一个 USB 摄像头 + 一份约 1900 行的 Python 代码 + 四个下载来的开源模型。搭建分五个阶段,装完后是一个开机自启的服务,局域网里用浏览器打开就能用。脚本和代码都在 ~/Documents/AI/work/jetson-person-demo/。

0. 你需要准备什么

项目要求
设备Jetson Orin NX 16GB,已刷 JetPack 6.2.x(Ubuntu 22.04,Python 3.10),NVMe 启动,能上网
摄像头任意支持 1080p30 MJPEG 的 USB 摄像头(用的是绿联 CM797)
开发机一台能 SSH 到设备的电脑(用的是 Mac),装有 rsync
网络设备直连国外源很慢,全部用国内镜像和 GitHub 加速前缀 https://gh-proxy.com/
权限设备上的用户要能免密 sudo

1. 整体结构

一条流水线,单进程多线程,每一帧顺序做六件事:

capture.pyUSB 摄像头 1080p MJPEG → GStreamer + nvv4l2decoder 硬件解码,读取线程只保留最新一帧
detectors.pyYOLO26n-pose(TensorRT)→ 人框 + 17 个关键点,ByteTrack 给稳定编号,每帧
detectors.py / common.py头部检测器 YOLOv8n(TensorRT,每 3 帧)→ 头框;漏检时用耳、眼、肩关键点估算
faces.pyInsightFace SCRFD + ArcFace(onnxruntime CUDA,每 3 帧)→ 人脸特征 → 与注册库比对、投票确认
gestures.pyHaGRID YOLOv10n 手势(TensorRT,每 3 帧)+ 姿态规则 → 归到人、时序平滑、双手校验
draw.py → pipeline.py → web.py叠加绘制 → JPEG → FastAPI:MJPEG 直播 + 数据面板 + 注册接口

代码文件(app/)

文件职责
config.py所有可调参数:摄像头、模型路径、阈值、温控、网页端口
capture.py摄像头/视频文件读取线程
common.py不依赖模型的纯逻辑:估头框、身份投票、手势平滑、双手校验(可在任何电脑上单元测试)
detectors.py人体姿态模型、头部检测模型的封装
faces.pyInsightFace 封装 + 人脸库(data/faces/db.json + 缩略图)
gestures.py姿态规则手势 + HaGRID 手部手势模型
draw.py画框、骨架、中文标签
pipeline.py主循环、跟踪状态、事件流、温控、信号源切换
web.py static/FastAPI 接口与网页界面
main.py run.sh export_engines.py入口、启动脚本、TensorRT 引擎导出

设备目录

~/demo/ ├── app/ 代码(从开发机 rsync 过来) ├── venv/ Python 虚拟环境 ├── models/ │ ├── yolo26n-pose.pt / .engine │ ├── heads/head_abcfsa_yolov8n.pt / .engine │ ├── gestures/YOLOv10n_gestures.pt / .engine │ └── insightface/models/buffalo_l/*.onnx ├── data/faces/ 人脸库 ├── data/test/ 测试视频 ├── debs/ wheels/ 安装包缓存 ├── setup_*.sh 安装脚本 └── thermal.log 温度记录

2. 开发机:SSH 免密 + 同步代码

ssh-keygen -t ed25519 -N "" -f ~/.ssh/jetson_orin_nx
ssh-copy-id -i ~/.ssh/jetson_orin_nx.pub -p <端口> <用户>@<设备地址>   # 这一步要输一次设备密码

在 ~/.ssh/config 里加别名,后面全部用 ssh jetson:

Host jetson
  HostName <设备地址>
  User linux
  Port <端口>
  IdentityFile ~/.ssh/jetson_orin_nx

同步代码,以后每次改完代码都是这一条:

rsync -az --delete --exclude __pycache__ ./app/ jetson:~/demo/app/

2b. 不用开发机,直接在设备上操作

如果你就坐在 Jetson 前面(接了显示器键盘),第 2 步整个跳过,代码这样拿:

mkdir -p ~/demo && cd ~/demo
wget https://jetson.weorgcloud.com/jetson-demo-src.zip && unzip -o jetson-demo-src.zip   # 得到 app/ scripts/ docs/
bash scripts/setup_jetson.sh 2>&1 | tee setup.log                                        # 后面全自动

没网的话用 U 盘把 app/ 和 scripts/ 拷到 ~/demo/ 下也一样。以后改代码直接在设备上改 ~/demo/app/ 里的文件(nano 或 VS Code 都行),改完 sudo systemctl restart person-demo 生效。

现在这台设备上已经全部装好了,不需要再复刻;这一节是给"另一台新机器"或"重刷系统后"用的。代码包:jetson-demo-src.zip(约 56KB,含代码、脚本和本手册)。

3. 设备:一键脚本

把 scripts/setup_jetson.sh 拷到设备后执行,它按下面五个阶段走,每个阶段可以单独重跑:

scp scripts/setup_jetson.sh jetson:~/demo/
ssh jetson 'bash ~/demo/setup_jetson.sh 2>&1 | tee ~/demo/setup.log'
这份一键脚本是把当时真实跑通的四个分阶段脚本(setup_phase1d / 2 / 2b / 3.sh,也在 scripts/ 里)合并整理的,没有在一台全新机器上从头复跑过。遇到差异以分阶段脚本为准。

阶段 1:apt 源和 JetPack 组件(约 10 分钟)

出厂系统只有 CUDA,没有 cuDNN 和 TensorRT。

1
NVIDIA 源 repo.download.nvidia.com 改成 .cn 镜像,并新增 /etc/apt/preferences.d/nvidia-repo-pin-cn(Pin: origin "*.nvidia.cn",优先级 600)。不补这条,apt 会选中 Ubuntu 仓库里版本号更高的旧 CUDA 包,报依赖冲突。
2
Ubuntu 源改清华镜像。
3
.cn 镜像单连接只有 100KB/s:先用 apt-get install --print-uris 列出全部 deb 地址,用 aria2c -x 16 多线程预取(1.5GB 几分钟),拷进 /var/cache/apt/archives/,再 apt-get install -y nvidia-jetpack。
4
装工具:v4l-utils curl ffmpeg python3-venv python3-dev build-essential cmake libopenblas-dev fonts-noto-cjk(最后一个是中文字体,画面标签要用)。

阶段 2:模型和轮子(约 3 分钟)

文件来源
yolo26n-pose.ptgithub.com/ultralytics/assets/releases/download/v8.4.0/
buffalo_l.zip → 解压到 models/insightface/models/buffalo_l/github.com/deepinsight/insightface/releases/download/v0.7/
heads/head_abcfsa_yolov8n.ptraw.githubusercontent.com/Abcfsa/YOLOv8_head_detector/main/nano.pt
gestures/YOLOv10n_gestures.ptrndml-team-cv.obs.ru-moscow-1.hc.sbercloud.ru/datasets/hagrid_v2/models/(设备直连可下)
torch-2.10.0 torchvision-0.25.0 onnxruntime_gpu-1.23.0(cp310 aarch64 轮子)github.com/ultralytics/assets/releases/download/v0.0.0/

为什么不用 PyPI:PyPI 上的 torch 是 CPU 版;Jetson 专用轮子站 pypi.jetson-ai-lab.io 从国内只有 80KB/s。

阶段 3:Python 环境(约 5 分钟)

python3 -m venv --system-site-packages ~/demo/venv   # 继承系统包:才有 apt 装的 TensorRT 绑定和带硬解的 OpenCV
source ~/demo/venv/bin/activate
pip install --no-deps torch-2.10.0*.whl torchvision-0.25.0*.whl onnxruntime_gpu-1.23.0*.whl
pip install "numpy<2" filelock networkx jinja2 fsspec packaging protobuf flatbuffers coloredlogs pillow
pip install -U "sympy>=1.13.3" "typing_extensions>=4.10"   # 系统旧 sympy 会让 torch 无法 import
# cuDSS(torch 2.10 依赖):aria2 从 developer.download.nvidia.cn 拿 deb,dpkg -i 后 apt install cudss
pip install --no-deps ultralytics                          # 不带依赖,否则拉 CPU 版 torch 和无硬解 opencv
pip install matplotlib pyyaml requests scipy tqdm psutil py-cpuinfo ultralytics-thop polars pandas seaborn lap onnx onnxslim
pip install cython && pip install insightface fastapi "uvicorn[standard]" python-multipart aiofiles
pip uninstall -y onnxruntime opencv-python-headless opencv-python   # insightface 顺带装的,会盖掉 GPU 版和系统 OpenCV
pip install --no-deps onnxruntime_gpu-1.23.0*.whl

验证(都要为真):torch.cuda.is_available();cv2 的 build 信息里 GStreamer YES;onnxruntime.get_available_providers() 含 CUDA 和 TensorRT;import tensorrt 成功。

最终版本:torch 2.10.0 / torchvision 0.25.0 / onnxruntime-gpu 1.23.0 / TensorRT 10.3 / cuDNN 9.3 / OpenCV 4.8(系统)/ ultralytics 8.4.138 / insightface 1.0.1 / numpy 1.26.4。

阶段 4:导出 TensorRT 引擎(3 个模型,共约 20 分钟)

cd ~/demo/app && source ~/demo/venv/bin/activate
python export_engines.py ~/demo/models/yolo26n-pose.pt ~/demo/models/heads/head_abcfsa_yolov8n.pt ~/demo/models/gestures/YOLOv10n_gestures.pt

引擎只能在目标机、同版本 TensorRT 上生成;换 JetPack 要重做。代码里 resolve_model() 会自动优先使用同名 .engine。

阶段 5:服务化与散热

4. 摄像头怎么验证

v4l2-ctl -d /dev/video0 --list-formats-ext | head          # 支持的分辨率/帧率
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=MJPG --stream-mmap --stream-count=120   # 原始帧率,应接近 30
# 硬解通路(程序里用的就是这条管线)
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=120 ! "image/jpeg,width=1920,height=1080,framerate=30/1" ! jpegparse ! nvv4l2decoder mjpeg=1 ! nvvidconv ! "video/x-raw,format=BGRx" ! fpsdisplaysink video-sink=fakesink text-overlay=false sync=false -v 2>&1 | grep -oE "average: [0-9.]+" | tail -1

实测:这只摄像头 nvjpegdec 只有 11 帧,nvv4l2decoder 32 帧,CPU 解码 30 帧占 1 核。程序开不了硬解时自动回退到 V4L2 + CPU 解码。

5. 运行、验证、更新

sudo systemctl status person-demo                 # 状态
journalctl -u person-demo -f                      # 实时日志
curl -s localhost:8080/api/status | python3 -m json.tool    # 帧率、各阶段耗时、温度、原始手势输出
curl -s -X POST -H "Content-Type: application/json" -d '{"kind":"demo"}' localhost:8080/api/source   # 切到内置演示视频,camera 切回
curl -s -F "name=张三" -F "files=@photo.jpg" localhost:8080/api/register   # 命令行注册人脸

网页:http://<设备局域网 IP>:8080。改代码:开发机改 → rsync → sudo systemctl restart person-demo。

本机单元测试(不需要设备):python3 scripts/test_common.py,覆盖头框估算、身份确认、手势平滑、双手校验。

6. 会踩的坑(都已在脚本里处理)

现象原因处理
apt 装 nvidia-jetpack 报依赖冲突换 .cn 镜像后自带的优先级规则失效补 *.nvidia.cn 的 pin
下载几十 KB/s国外源单连接限速GitHub 走 gh-proxy;deb 和 cuDSS 用 aria2 多线程
torch 无法 import(equal_valued)venv 继承的系统 sympy 太旧在 venv 里升级 sympy
人脸跑在 CPU、摄像头硬解开不了insightface 顺带装了 CPU 版 onnxruntime 和 headless OpenCV卸掉,重装 GPU 轮子
只有 7 帧给 TensorRT 模型传了 half=True,Ultralytics 每帧重建推理器不传 half
只有 19 帧没锁频,动态调频拖慢jetson_clocks(散热允许时)
硬断电后摄像头打不开(USB -110)摄像头卡死拔插摄像头
远程 heredoc 里跑 ffmpeg 后面命令消失ffmpeg 吃掉了标准输入ffmpeg -nostdin
网页新旧脚本混用浏览器缓存脚本地址带版本号,静态文件 no-cache

7. 许可与合规

YOLO(AGPL-3.0)、InsightFace 预训练模型(仅非商用)、HaGRID(CC BY-SA 4.0)都只适合内部 demo;产品化要换可商用模型或购买授权。人脸数据只存设备本地,需符合《人脸识别技术应用安全管理办法》。