智能车走马观碑组目标检测算法
WSL/Linux 测试数据集训练 -> TorchScript 导出 -> pnnx 转换 ncnn -> example/yolo_ncnn_app 部署测试
当前使用 WSL2,可通过 NVIDIA WSL 驱动访问宿主机 GPU。目标检测训练、TorchScript 导出和 pnnx 转换统一在 WSL/Linux 中完成。
回到顶部
一、项目结构与环境准备
1.1 目录职责
当前仓库根目录:
/opt/2k0300/loongson_2k300_lib
与本流程相关的目录:
tb_yolo/
configs/demo/target_board.names # 类别名,一行一个类别
configs/demo/target_board.yaml # YOLOv5 数据集配置
dataset/demo/images/train/ # 测试训练集图片
dataset/demo/images/val/ # 测试验证集图片
dataset/demo/labels/train/ # 测试训练集标签
dataset/demo/labels/val/ # 测试验证集标签
models/pretrained/yolov5n.pt # 默认迁移学习权重
models/demo/best.pt # 演示 PyTorch 权重
models/demo/best.torchscript # 演示 TorchScript
models/demo/best.param # 演示 ncnn 结构文件,转换后生成
models/demo/best.bin # 演示 ncnn 权重文件,转换后生成
scripts/train_yolov5_host.sh # WSL/Linux 训练入口
scripts/export_torchscript_host.sh # WSL/Linux TorchScript 导出入口
scripts/export_ncnn_host.sh # WSL/Linux TorchScript 转 ncnn 入口
vendor/yolov5/ # YOLOv5 源码
example/yolo_ncnn_app/ # 久久派 ncnn 离线推理示例
scripts/build_ncnn_loongarch.sh # 下载并交叉编译 ncnn
cross_lib/ncnn/ # ncnn 安装目录,脚本生成
1.2 日常操作目录
tb_yolo 相关命令默认在:
cd /opt/2k0300/loongson_2k300_lib/tb_yolo
example 部署命令默认在仓库根目录或 example 目录执行,文档会分别写清楚。
1.3 初始化 WSL/Linux 训练环境
必须使用 Python 3.10 或 Python 3.11,不要使用系统自带 Python 3.14。
如果系统还没有 conda,先安装 Miniforge。如果 wget 不存在,先安装:
sudo apt update
sudo apt install -y wget
安装并初始化 Miniforge:
cd /tmp
wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh
bash Miniforge3-Linux-x86_64.sh -b -p “HOME/miniforge3"eval"HOME/miniforge3" eval "HOME/miniforge3"eval"(”$HOME/miniforge3/bin/conda" shell.bash hook)"
conda init bash
执行 conda init bash 后,重新打开一个终端,或者执行:
source ~/.bashrc
如果安装后当前终端仍提示 Command ‘conda’ not found,说明当前 shell 还没有加载 conda,先执行:
eval “("("("HOME/miniforge3/bin/conda” shell.bash hook)"
conda --version
确认能看到 conda 版本号后,创建并进入 loong 环境:
conda create -n loong python=3.10
conda activate loong
安装 YOLOv5 依赖:
cd /opt/2k0300/loongson_2k300_lib/tb_yolo
python -m pip install -r requirements-host.txt
requirements-host.txt 已固定使用 CUDA 12.8 版 PyTorch:
torch2.11.0+cu128
torchvision0.26.0+cu128
vendor/yolov5/requirements.txt 不直接写 --extra-index-url,因为 YOLOv5 训练启动时会检查该文件,运行期检查逻辑会把 pip 参数误当成包名。训练脚本会提前复用系统字体生成 ~/.config/Ultralytics/Arial.ttf,避免训练时联网下载字体。
确认 WSL 能访问 GPU:
nvidia-smi
python -c “import torch; print(torch.version); print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else ‘cpu’)”
成功后应看到:
torch: 2.11.0+cu128
CUDA available: True
CUDA device: NVIDIA GeForce RTX 5060 Laptop GPU
CUDA tensor test: 1.0
只看 torch.cuda.is_available() 不够,必须确认 CUDA 张量能实际创建和同步。
1.4 检查类别配置
测试数据集当前类别文件:
configs/demo/target_board.names
内容:
Mouse
Printer
drill
Wrench
Screwdriver
类别顺序必须同时匹配:
YOLO 标签 class_id
configs/demo/target_board.yaml
开发板运行目录中的 names.txt
回到顶部
二、使用测试数据集训练和转换
2.1 测试数据集位置
测试数据集已经放在:
tb_yolo/dataset/demo/images/train
tb_yolo/dataset/demo/images/val
tb_yolo/dataset/demo/labels/train
tb_yolo/dataset/demo/labels/val
本场景只用于验证流程,不代表最终上车效果。
注意:当前已经按数据集名隔离目录,不再使用拆分前的平铺目录。demo 场景统一使用:
outputs/train/demo/exp_demo_gpu/weights/best.pt
dataset/demo/images/val
configs/demo/target_board.yaml
2.2 启动训练
执行:
./scripts/train_yolov5_host.sh --name exp_demo_gpu
默认核心参数:
参数 默认值 说明
–name 命令指定(必填) 本次实验目录名,输出在 outputs/train/demo//
–weights models/pretrained/yolov5n.pt 迁移学习预训练权重,轻量模型适合开发板部署
–data configs/demo/target_board.yaml 数据集配置文件
–epochs 150 训练轮数
–batch-size 32 批量大小;显存不足时降低,例如 --batch-size 16
–imgsz 96 输入尺寸;后续 TorchScript 导出和 ncnn 推理必须与此一致
–device 0 使用第 0 块 GPU;CPU 训练用 --device cpu
–project outputs/train/demo 训练输出根目录
–optimizer SGD 优化器,可选 Adam、AdamW
–hyp vendor/yolov5/data/hyps/hyp.scratch-low.yaml 超参数配置文件,小型数据集推荐 hyp.scratch-low.yaml
–patience 100 早停耐心值;验证集指标连续不提升的轮数
–cache -(不使用) 缓存图片到内存/磁盘,加速训练;可选 ram 或 disk
–resume - 从断点恢复训练,传入中断的权重路径
–noval switch(默认不启用) 跳过每轮验证,加快训练但无法观察过拟合
–nosave switch(默认不启用) 不保存中间权重,只保留 last.pt 和 best.pt
–exist-ok switch(默认不启用) 允许覆盖已存在同名输出目录
–freeze -(默认不冻结) 冻结前 N 层,例如 --freeze 10 只微调检测头
训练完成后优先使用:
outputs/train/demo/exp_demo_gpu/weights/best.pt
2.3 查看训练结果
重点查看:
outputs/train/demo/exp_demo_gpu/results.png
outputs/train/demo/exp_demo_gpu/confusion_matrix.png
outputs/train/demo/exp_demo_gpu/weights/best.pt
曲线含义:
曲线 含义 判断方法
train/box_loss 训练集框回归损失 越低越好,应逐步下降
train/obj_loss 训练集目标置信度损失 越低越好,反映是否能找到目标
train/cls_loss 训练集分类损失 越低越好,类别少时通常下降较快
val/box_loss 验证集框回归损失 如果训练下降但验证上升,可能过拟合
val/obj_loss 验证集目标置信度损失 验证集稳定下降更可信
val/cls_loss 验证集分类损失 类别混淆时会偏高
metrics/precision 预测为目标的结果有多少是真的 误检多时偏低
metrics/recall 真实目标有多少被检出 漏检多时偏低
metrics/mAP_0.5 IoU=0.5 下的检测精度 判断是否大体能检出
metrics/mAP_0.5:0.95 更严格的综合精度 判断框是否贴合
2.4 本机检测验证
执行:
python vendor/yolov5/detect.py --weights outputs/train/demo/exp_demo_gpu/weights/best.pt --source dataset/demo/images/val --data configs/demo/target_board.yaml --imgsz 96 --conf-thres 0.25 --project outputs/detect/demo --name exp_demo_val
输出图片在:
outputs/detect/demo/exp_demo_val
图片框上的数字是置信度,例如 0.91 表示模型认为该框属于对应类别的综合置信度约为 91%。
2.5 导出 TorchScript
执行:
zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/tb_yolo$ ./scripts/export_torchscript_host.sh --weights models/demo/best.pt --imgsz 96 --copy-model demo
TorchScript 导出不强制需要 GPU;脚本默认使用 --device cpu。导出时不要加 --optimize,pnnx 需要标准 TorchScript 文件,不使用移动端 lite interpreter 格式。
参数说明:
参数 默认值 说明
–weights 必填 训练好的 .pt 权重路径,例如 outputs/train/demo/exp_demo_gpu/weights/best.pt
–imgsz 96 导出输入尺寸,必须与训练时的 --imgsz 一致
–copy-model - 导出后拷贝 best.torchscript 和 best.pt 到 models// 目录
–batch 1 导出时的 batch 大小,部署推理通常为 1
–device cpu 导出设备;Linux 虚拟机没有 GPU 时保持 cpu
–install-deps false 导出前安装 YOLOv5 requirements.txt 依赖
生成:
models/demo/best.torchscript
models/demo/best.pt
–imgsz 必须与训练时一致。
2.6 检查 TorchScript
Netron 是神经网络模型结构查看工具,用来确认输入输出,不负责训练或推理。
网页版:
https://netron.app
本地安装:
zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/tb_yolo$ pip install netron
zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/tb_yolo$ netron ./models/demo/best.torchscript
重点确认:
输入尺寸:1x3x96x96
模型类型:TorchScript
导出尺寸与训练 imgsz 一致
注意:pnnx 转换后,ncnn 输入输出名固定按 in0、out0、out1、out2 使用。
2.7 生成 ncnn 部署模型
前面导出的 best.torchscript 是中间格式,久久派上的 yolo_ncnn_app 使用 ncnn 推理,实际加载的是:
best.param
best.bin
其中:
best.param 网络结构
best.bin 网络权重
因此流程是:
best.pt -> best.torchscript -> best.param + best.bin
pnnx 是 ncnn 官方提供的模型转换工具。本流程中它负责读取 TorchScript,根据 inputshape 推断输入输出形状,完成算子转换和必要图优化,最终直接生成 ncnn 加载用的 best.param 和 best.bin。开发板端只加载转换产物,不再解析 .pt 或 TorchScript。
本项目使用 TorchScript -> pnnx -> ncnn 链路。部署端读取 out0 候选框矩阵,再在 C++ 中完成置信度过滤和 NMS。
先安装官方 pnnx 命令行工具:
python3 -m pip install pnnx
然后在 tb_yolo 下转换:
cd /opt/2k0300/loongson_2k300_lib/tb_yolo
./scripts/export_ncnn_host.sh --torchscript models/demo/best.torchscript --imgsz 96 --copy-model demo
该脚本会:
调用 pnnx
使用 inputshape=[1,3,96,96]
生成 best.param / best.bin
复制 best.param / best.bin 到 models/demo/
参数说明:
参数 默认值 说明
–torchscript models/demo/best.torchscript TorchScript 模型路径
–imgsz 96 pnnx 输入尺寸,必须与训练和 TorchScript 导出尺寸一致
–copy-model - 转换后拷贝 best.param 和 best.bin 到 models// 目录
–pnnx 自动查找 指定其他 pnnx 可执行文件
–fp16 1 pnnx 权重存储选项,默认启用 FP16 存储以减小模型体积
–optlevel 2 pnnx 优化等级
–device cpu pnnx 转换设备
–moduleop 空 可选 pnnx 高级参数;本项目默认不使用
生成:
models/demo/best.param
models/demo/best.bin
后续部署到久久派时,example/build_deploy_run.sh 会默认上传这两个文件到开发板运行目录。
转换后的 ncnn 模型使用以下 blob 名:
输入尺寸:float32[1,3,96,96]
输入:in0
输出:out0
这里 out0 是 YOLOv5 已解码的候选框矩阵,每行格式为:
x_center, y_center, width, height, objectness, class0, class1, …
yolo_ncnn_app 会在 C++ 里完成置信度过滤、坐标还原和 NMS。
回到顶部
三、编译 ncnn 和部署到久久派
3.1 编译 ncnn 到 cross_lib
在能运行 bash、git、cmake 和仓库交叉工具链的环境中执行:
./scripts/build_ncnn_loongarch.sh
环境变量说明:
环境变量 默认值 说明
NCNN_GIT_REF master 要编译的 ncnn git 版本标签,例如 20250503
NCNN_INSTALL_PREFIX cross_lib/ncnn 安装目标目录
NCNN_GIT_URL https://github.com/Tencent/ncnn.git ncnn 源码仓库地址
NCNN_JOBS $(nproc) 编译并行任务数,默认使用全部 CPU 核心
脚本会从 NCNN_GIT_URL 下载 Tencent/ncnn 源码,使用:
cross_lib/loongarch64-linux-gnu-gcc13.3
安装到:
cross_lib/ncnn
cross_lib/src/ 和 cross_lib/build/ 是源码和中间构建目录,已加入 .gitignore。需要固定源码版本时,可在运行前设置 NCNN_GIT_REF,例如:
NCNN_GIT_REF=20250916 ./scripts/build_ncnn_loongarch.sh
3.2 编译 yolo_ncnn_app
在仓库根目录执行:
cd example/yolo_ncnn_app
make clean
make
默认依赖:
cross_lib/ncnn
cross_lib/opencv-4.10.0
cross_lib/loongarch64-linux-gnu-gcc13.3
yolo_ncnn_app 使用 ncnn 推理,使用 OpenCV 读取图片、缩放和保存结果。
3.3 一键部署运行
在仓库根目录执行:
cd example
./build_deploy_run.sh --app yolo_ncnn_app – --param best.param --bin best.bin --names names.txt --image test.jpg --output result.jpg
脚本会自动:
编译 example/yolo_ncnn_app/main
上传可执行文件到 /opt/yolo_ncnn_app/yolo_ncnn_app
上传 OpenCV core/imgproc/imgcodecs 运行库到 /usr/local/opencv/lib
上传 libncnn.so 到 /usr/local/ncnn/lib
上传 models/demo/best.param 到 /opt/yolo_ncnn_app/best.param
上传 models/demo/best.bin 到 /opt/yolo_ncnn_app/best.bin
上传 configs/demo/target_board.names 到 /opt/yolo_ncnn_app/names.txt
上传一张验证集图片到 /opt/yolo_ncnn_app/test.jpg
在开发板运行 /opt/yolo_ncnn_app/yolo_ncnn_app
3.4 部署参数说明
3.4.1 脚本参数(-- 之前,控制编译和上传行为)
参数 类型 默认值 说明
–app string 必填 要部署的应用名,对应 example// 目录
–deploy string scripts/board_env.sh 开发板 SSH 地址,例如 root@172.23.15.40
–remote-dir string /opt 开发板上的部署基础目录,实际使用 /opt//
–remote-name string APP_NAME 远端可执行文件名
–target string main 本地构建产物文件名
–model string demo 本地模型/数据集名,对应 tb_yolo/models// 和 tb_yolo/dataset//
–yolo-param string tb_yolo/models//best.param 本地 .param 文件路径,通常不用手动写
–yolo-bin string tb_yolo/models//best.bin 本地 .bin 文件路径,通常不用手动写
–yolo-names string 自动推导 本地类别名文件,默认使用 tb_yolo/configs//target_board.names
–yolo-image string 自动推导 本地测试图片路径,默认从 tb_yolo/dataset//images/val/ 取第一张
–ncnn-lib-dir string cross_lib/ncnn/lib 本机 libncnn.so 所在目录
–remote-ncnn-lib-dir string /usr/local/ncnn/lib 开发板 libncnn.so 部署目录
–opencv-lib-dir string cross_lib/opencv-4.10.0/lib 本机 OpenCV 运行库目录
–remote-lib-dir string /usr/local/opencv/lib 开发板 OpenCV 运行库目录
–no-run switch false 只编译和上传,不执行推理
–skip-build switch false 跳过本地构建,只上传已有可执行文件
–no-clean switch false 构建前不执行 make clean
–stop-old switch false 部署运行前先停止远端同名旧进程
–stop-only switch false 只停止远端同名旧进程,不构建、不上传
3.4.2 应用参数(-- 之后,传给 yolo_ncnn_app 的 argv)
重要:–param、–bin、–names、–image 的值是开发板上的文件名,不是本地路径。脚本上传时会自动做文件名映射:
本地 .param → 远端 best.param(固定命名)
本地 .bin → 远端 best.bin(固定命名)
本地类别名文件(来自 --yolo-names 或默认配置)→ 远端 names.txt(固定命名)
本地图片(来自 --yolo-image 或默认验证集第一张)→ 远端 test.jpg(固定命名)
所以 --image test.jpg 中的 test.jpg 是脚本上传图片时强制重命名的结果,无需用户关心本地图片叫什么。
参数 说明
–param 开发板上 .param 文件名,与脚本上传时固定使用的名称一致,例如 best.param
–bin 开发板上 .bin 文件名,与脚本上传时固定使用的名称一致,例如 best.bin
–names 开发板上类别名文件名,与脚本上传时固定使用的名称一致,例如 names.txt
–image 开发板上测试图片的文件名,脚本 scp 上传时固定重命名为 test.jpg
–output 开发板上输出结果图片的名称,例如 result.jpg
–conf 置信度阈值,默认 0.25;检测不到目标时可临时降低到 0.1 排查
–nms NMS 交并比阈值,默认 0.45
3.5 常用部署示例
指定模型和测试图片:
./build_deploy_run.sh --app yolo_ncnn_app --model demo --yolo-image …/tb_yolo/dataset/demo/images/val/resized-171.jpg – --param best.param --bin best.bin --names names.txt --image test.jpg --output result.jpg
指定本机 ncnn 库目录:
./build_deploy_run.sh --app yolo_ncnn_app --ncnn-lib-dir …/cross_lib/ncnn/lib – --param best.param --bin best.bin --names names.txt --image test.jpg --output result.jpg
只构建和上传,不立即运行:
./build_deploy_run.sh --app yolo_ncnn_app --no-run
跳过本地构建,只重新上传已有可执行文件:
./build_deploy_run.sh --app yolo_ncnn_app --skip-build – --param best.param --bin best.bin --names names.txt --image test.jpg --output result.jpg
部署运行前先停止远端旧进程:
./build_deploy_run.sh --app yolo_ncnn_app --stop-old – --param best.param --bin best.bin --names names.txt --image test.jpg --output result.jpg
回到顶部
四、常见问题与排查
4.1 缺少 pnnx
报错类似:
Missing pnnx
说明当前机器找不到 pnnx 转换工具。安装官方 pnnx:
python3 -m pip install pnnx
4.2 缺少 libncnn.so
如果部署时报:
ncnn library directory not found
Missing ncnn library
先执行:
./scripts/build_ncnn_loongarch.sh
确认存在:
cross_lib/ncnn/lib/libncnn.so
4.3 输出维度不匹配
优先检查:
names.txt 行数是否等于类别数量
–input-name 是否等于 best.param 中输入 blob 名,pnnx 默认 in0
–output-name 是否等于 best.param 中输出 blob 名,pnnx 默认 out0
训练、TorchScript 导出、ncnn 推理的输入尺寸是否一致
4.4 框位置不对
优先检查:
是否使用 letterbox 预处理
是否按 letterbox 的 scale/pad 还原坐标
输入 BGR/RGB 是否处理一致
imgsz 是否一致
4.5 类别整体错位
优先检查:
configs/demo/target_board.names
LabelImg classes.txt
开发板运行目录中的 names.txt
更多推荐




所有评论(0)