龙芯2k0300 - 智能车走马观碑组目标检测算法
该片文章用于跑通测试数据集链路:在 WSL/Linux 上训练 YOLOv5,导出 TorchScript,转换为 ncnn 的 param/bin,再通过 example/yolo_ncnn_app 部署到久久派测试。
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/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:
torch==2.11.0+cu128
torchvision==0.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/<name>/ |
--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/<name>/ 目录 |
--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/<name>/ 目录 |
--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/<app>/ 目录 |
--deploy |
string | scripts/board_env.sh |
开发板 SSH 地址,例如 root@172.23.15.40 |
--remote-dir |
string | /opt |
开发板上的部署基础目录,实际使用 /opt/<app>/ |
--remote-name |
string | APP_NAME |
远端可执行文件名 |
--target |
string | main |
本地构建产物文件名 |
--model |
string | demo |
本地模型/数据集名,对应 tb_yolo/models/<name>/ 和 tb_yolo/dataset/<name>/ |
--yolo-param |
string | tb_yolo/models/<model>/best.param |
本地 .param 文件路径,通常不用手动写 |
--yolo-bin |
string | tb_yolo/models/<model>/best.bin |
本地 .bin 文件路径,通常不用手动写 |
--yolo-names |
string | 自动推导 | 本地类别名文件,默认使用 tb_yolo/configs/<model>/target_board.names |
--yolo-image |
string | 自动推导 | 本地测试图片路径,默认从 tb_yolo/dataset/<model>/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 <name> |
开发板上 .param 文件名,与脚本上传时固定使用的名称一致,例如 best.param |
--bin <name> |
开发板上 .bin 文件名,与脚本上传时固定使用的名称一致,例如 best.bin |
--names <name> |
开发板上类别名文件名,与脚本上传时固定使用的名称一致,例如 names.txt |
--image <name> |
开发板上测试图片的文件名,脚本 scp 上传时固定重命名为 test.jpg |
--output <name> |
开发板上输出结果图片的名称,例如 result.jpg |
--conf <value> |
置信度阈值,默认 0.25;检测不到目标时可临时降低到 0.1 排查 |
--nms <value> |
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
三处顺序必须完全一致。

浙公网安备 33010602011771号