第一步:本地环境检测与创建(核心)
训练模型对显卡(GPU)有硬性要求。在本地 Dell 电脑上,我们需要建立一个支持 CUDA 加速的 PyTorch 环境。
1.1 硬件与驱动检查
在 Dell 电脑上打开普通的命令提示符(cmd)或终端,运行以下命令:
nvidia-smi检查目的:确认你的 Dell 电脑是否有 NVIDIA 显卡(如 RTX 3060/4060 等),并记录下右上角显示的CUDA Version(例如
CUDA Version: 12.x或11.x)。这决定了你后续能安装的 PyTorch 版本。
1.2 创建隔离的 Anaconda 虚拟环境
为了不污染你电脑上的其他 Python 项目,建议在本地也创建一个名为yolov5_train的独立虚拟环境。
在 Anaconda Prompt(或终端)中依次输入:
# 1. 创建 Python 3.8 的虚拟环境 conda create -n yolov5_train python=3.8 -y # 2. 激活该虚拟环境 conda activate yolov5_train检测当前环境:请把下面这行测试脚本直接复制到你当前的终端(确保处于(yolov5_train)环境下)并回车运行:
python3 -c " try: import torch print('✅ PyTorch 已安装,版本:', torch.__version__) print('🔥 GPU 加速(CUDA)状态:', torch.cuda.is_available()) if torch.cuda.is_available(): print(' 显卡型号:', torch.cuda.get_device_name(0)) except ImportError: print('❌ 未检测到 PyTorch') try: import torchvision print('✅ Torchvision 已安装,版本:', torchvision.__version__) except ImportError: print('❌ 未检测到 Torchvision') "1.3 安装带 CUDA 加速的 PyTorch
根据你 1.1 步骤中查到的 CUDA 版本,去 PyTorch 官网挑选对应的安装命令。
如果是 CUDA 11.x,通用安装命令通常为:
pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 --extra-index-url https://download.pytorch.org/whl/cu1131.4 环境验证测试(关键)
环境装好后,必须运行以下脚本验证 GPU 是否真正被 PyTorch 识别。在激活的虚拟环境中输入python进入交互模式:
import torch print("PyTorch版本:", torch.__version__) print("CUDA是否可用:", torch.cuda.is_available()) if torch.cuda.is_available(): print("当前显卡名称:", torch.cuda.get_device_name(0))通关标准:必须输出
CUDA是否可用: True并且正确打印出你的 NVIDIA 显卡型号。如果输出为False,说明安装成了 CPU 版本,无法用来加速训练。输入
exit()退出 Python。
1.5 安装 YOLOv5 依赖源码包
将你小车上的yolov5-pytorch源码整体复制到这台 Dell 电脑上,在终端中cd进入该目录,利用国内源快速安装剩下的工具包:
cd path/to/yolov5-pytorch pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple第二步:数据标注工具安装以及数据标注
2.1 标注工具(LabelImg)
需要在本地电脑上安装一个图片标注软件,用来框选你的数字。
pip install labelimg # 在终端直接输入 labelimg 即可打开可视化界面2.2 采集“数字标牌”数据集(核心资产)
拍照采集:用手机或小车摄像头,拍摄比赛/课设中使用的数字标牌(1、2、3、4)。
场景多样性:每个数字至少在不同的光照、不同的距离、不同的侧倾角度下拍摄50 ~ 100 张照片。整个数据集建议在 300 张照片以上。
摆放结构:在
yolov5-pytorch根目录下,按照说明书创建VOCdevkit/VOC2007/JPEGImages(放图片)和VOCdevkit/VOC2007/Annotations(放后面生成的 xml 标注)。
2.3 配置文件修改
类别文件:在
model_data/下新建num_classes.txt,里面写上:
1 2 3 4修改路径:修改
voc_annotation.py中的classes_path指向这个num_classes.txt,运行它来自动切分出训练集和验证集的索引文件(2007_train.txt)。
2.4 预训练权重垫底(yolov5_s.pth)
训练不能从零瞎猜,需要“站在巨人的肩膀上”。确保你的
model_data/目录下有你之前看到的yolov5_s.pth文件。train.py会读取它作为基础特征(骨干网络),在此基础上收敛出你的数字特征。
2.5 启动 LabelImg 标注工具
在终端输入:
labelimg(如果弹出界面,但终端疯狂报错提示缺少pyqt等,请运行
pip install labelimg -i https://pypi.tuna.tsinghua.edu.cn/simple后重试)
2.6 进行黄金三配置(最重要,防止格式出错)
打开 LabelImg 的图形化界面后,请立即完成这 3 点设置,这是数据成功的关键:
确定格式:点击界面左侧工具栏的那个大大的按钮(它默认可能是 YOLO 或 CreateML),多点几次,直到它显示为
💡 原因:你的小车代码包默认配置的是 VOC 数据格式,如果我们选错了格式,后面训练时会报错找不到标签。PascalVOC。设置图片目录 (Open Dir):
点击界面左侧的Open Dir按钮。
选择目录:📁
~/yolo5/yolov5-pytorch/VOCdevkit/VOC2007/JPEGImages。此时你就能在界面上看到你的第一张数字图片了。
设置保存目录 (Change Save Dir):
点击界面左侧的Change Save Dir按钮。
选择目录:📁
~/yolo5/yolov5-pytorch/VOCdevkit/VOC2007/Annotations。💡 原因:这能确保每一个框选操作生成的
.xml标签文件,都被精准地存在它该去的地方。
2.7 开始纯鼠标流标注步骤
配置好后,开始给这 173 张图片“点石成金”:
启用框选:在键盘上按下
W键(Create\RectBox),此时你的鼠标会变成一个十字光标。画框:用鼠标十字瞄准图片里你要识别的数字标牌,左键按住不放拖动,拉出一个大小适中、刚好把数字标牌完全包裹住的框。
输入标签名:松开鼠标左键,会弹出一个输入框。请直接输入你要训练的真实数字:
如果是数字 1,就输入
1。如果是数字 2,就输入
2。(依此类推,不要写复杂的名字如“num_1”,只写纯数字标签)。点击 OK。
保存:按下键盘
Ctrl + S(Save),保存这行标注。(此时隔壁的 Annotations 文件夹里会多出一个对应的 xml 文件)
切换下一张:按下键盘
D键(Next Image),LabelImg 会自动加载第 2 张图片。重复:重复
W(框选) -> 输入数字 ->Ctrl+S(保存) ->D(下一张) 的循环。
# 1. 下载 labelImg 的官方纯源码包 git clone https://github.com/HumanSignal/labelImg.git # 2. cd 进入刚刚下载的源码目录 cd labelImg # 3. 编译出 Linux 系统需要的界面资源文件 pyrcc5 -o libs/resources.py resources.qrc # 4. 直接用 Python 启动源码 python3 labelImg.py第三步:生成训练索引与启动模型训练
3.1 生成数据索引文件 (2007_train.txt)
训练代码需要通过文本索引文件找到对应图片的标注路径。在终端中确保处于(yolov5_train)虚拟环境下,执行:
# 确保在项目根目录 cd ~/yolo5/yolov5-pytorch # 生成数据集索引文件 python3 voc_annotation.py检查输出:运行完毕后,项目根目录下会自动生成
2007_train.txt和2007_val.txt。可以通过ls -l确认文件已建立。
3.2 启动训练
在你的源码架构(基于 bubbliiiing 版本 yolov5-pytorch)中,核心配置默认已在train.py文件内设置,只需确认代码中classes_path已指向model_data/num_classes.txt。
1. 直接运行默认训练命令(最简指令)
python3 train.py2. 自定义参数启动命令(推荐)
如果你需要通过命令行动态覆盖参数(如调整 Batch Size、训练轮数等),直接复制并运行以下指令:
python3 train.py \ --model_path model_data/yolov5_s.pth \ --classes_path model_data/num_classes.txt \ --input_shape 640 640 \ --Epoch 50 \ --batch_size 8 \ --num_workers 4 \ --cuda True💡 Ubuntu 训练常见问题与调试建议
显存溢出 (CUDA Out of Memory):如果显卡显存较小导致报错,将
--batch_size调小(例如改成4或2):python3 train.py --batch_size 4DataLoader 多进程报错:若提示 multiprocessing 错误,可将
--num_workers设为0:python3 train.py --num_workers 0后台挂载训练(防止终端中断):
nohup python3 train.py > train.log 2>&1 & tail -f train.log # 实时查看后台输出
训练结果与部署
训练启动后,模型权重与日志会自动保存到logs/目录中:
best_epoch_weights.pth:准确率最高的模型权重(训练完成后将此文件拷贝到小车端/树莓派端部署使用)。last_epoch_weights.pth:最后一轮训练结束后的权重。
完整全流程:从录制视频 → 抽帧 → LabelImg标注 → 更新ImageSets → 生成训练索引 → 训练 → 导出OAK模型 → ROS部署
适配你的项目:工件实物颜色固定,光照会变化,工件运动距离可变;bubbliiiing‑yolov5‑pytorch;Pascal‑VOC(xml)标签格式。 重点标注:什么时候、用什么命令更新ImageSets/Main下面的txt文件。
0.前期准备
工作目录:~/yolo5
- oak录制视频输出:
~/yolo5/workpiece_video/xxx.mp4(OAK录制的工件视频) - yolov5‑pytorch项目路径:
~/yolo5/yolov5‑pytorch - labelImg路径:
~/yolo5/labelImgVOC目录结构(标准)
yolov5‑pytorch/VOCdevkit/VOC2007/ ├─JPEGImages/ #存放所有抽帧jpg图片 ├─Annotations/ #存放对应xml标签,图片和xml同名一一对应 └─ImageSets/Main/ #trainval.txt / train.txt / val.txt / test.txt,**由voc_annotation.py自动生成,不要手动编辑!**步骤1:OAK录制工件视频
- 固定OAK相机支架;工件在实际工作运动区间运动;
- 覆盖现场全部实际工作距离(近‑远),包含现场典型光照:正常灯光、轻微阴影、明暗变化;
⚠️只录制【实物标准大小、标准本体颜色】工件;不要录制变色、异形、别的物体。
- 运行oak_record_video.py录制视频,保存到
~/yolo5/workpiece_video/,例如work_01.mp4。
步骤2:视频抽帧,把图片放进JPEGImages
运行video_to_frames.py抽帧,间隔不要太密避免大量重复图片。
cd ~/yolo5 python3 video_to_frames.py- 输出图片命名格式:
num_target_0000.jpg、num_target_0001.jpg … - 将抽帧得到的全部
.jpg复制到VOC的JPEGImages文件夹
cp workpiece_images/*.jpg ~/yolo5/yolov5-pytorch/VOCdevkit/VOC2007/JPEGImages/校验:
ls ~/yolo5/yolov5-pytorch/VOCdevkit/VOC2007/JPEGImages确认图片全部存在。
步骤3:LabelImg标注(PascalVOC)
cd ~/yolo5/labelImg pyrcc5 -o libs/resources.py resources.qrc python3 labelImg.py界面设置:
- 左上角格式切换为PascalVOC(生成xml,不是YOLO txt)
Open Dir→ 选择:~/yolo5/yolov5‑pytorch/VOCdevkit/VOC2007/JPEGImagesChange Save Dir→ 选择:~/yolo5/yolov5‑pytorch/VOCdevkit/VOC2007/Annotations
标注操作规则:
- W画框,框住标准工件;弹出类别输入框填写:
target_workpiece; - 无论图片里面有没有工件,必须按 Ctrl+S 保存,生成同名xml,再按D下一张!
没有工件也要保存空xml,否则后续脚本报xml找不到。 图片名
num_target_xxxx.jpg↔ 标签num_target_xxxx.xml,名字必须完全一模一样。
标注完成校验:jpg数量 = xml数量
cd ~/yolo5/yolov5-pytorch/VOCdevkit/VOC2007 ls JPEGImages/*.jpg | wc -l ls Annotations/*.xml | wc -l两个数字必须相等。
步骤4:更新 ImageSets/Main 的全部txt文件【重点】
⚠️不要手动编辑
trainval.txt!不要自己手写文件名进去!bubbliiiing的voc_annotation.py,当annotation_mode = 0时: 脚本会自动扫描Annotations文件夹下面所有真实存在的xml文件,自动生成 ImageSets/Main下面:trainval.txt、train.txt、val.txt、test.txt。 新增/删除图片‑xml之后,只需要重新运行voc_annotation.py,ImageSets内容自动刷新。
- 确认
voc_annotation.py头部配置
annotation_mode = 0 classes_path = 'model_data/work_classes.txt' trainval_percent = 0.9 train_percent = 0.9 VOCdevkit_path = 'VOCdevkit'annotation_mode=0:①扫描Annotations的xml,重写ImageSets下面全部txt;②再生成根目录的2007_train.txt、2007_val.txt训练索引。annotation_mode=1:仅生成ImageSets下面txt,不生成2007_train/val.txtannotation_mode=2:只读取已有的ImageSets/train.txt、val.txt,不会刷新ImageSets!(新增图片时绝对不要用mode=2)
- 确认类别文件
model_data/work_classes.txt
cd ~/yolo5/yolov5-pytorch cat model_data/work_classes.txt内容只有一行,无多余空格换行:
target_workpiece- 运行脚本,自动刷新ImageSets!
python3 voc_annotation.py输出示例:
Generate txt in ImageSets. train and val size XX train size XX Generate txt in ImageSets done. Generate 2007_train.txt and 2007_val.txt for train done. | target_workpiece | XX |✔此时
VOCdevkit/VOC2007/ImageSets/Main/trainval.txt已经自动更新为当前Annotations内所有xml对应的id。 脚本内部逻辑:读取Annotations下全部.xml,去掉后缀得到图片id,随机划分train/val/test,写入ImageSets下各个txt。
查看ImageSets/Main/trainval.txt确认内容
cat VOCdevkit/VOC2007/ImageSets/Main/trainval.txt同时项目根目录生成训练用索引文件:
2007_train.txt、2007_val.txt,这两个是给train.py读取的。
⚠️重要规则(以后新增图片牢记)
每次新增一批图片+xml:
- 把jpg复制进JPEGImages;
- labelImg全部标注生成对应xml;
- 修改
voc_annotation.py确保annotation_mode = 0; - 执行
python3 voc_annotation.py,自动刷新ImageSets全部内容,自动生成2007_train/val.txt。❌不要手动修改ImageSets里面任何txt!手动改会出现id和实际xml不一致,报FileNotFound。
步骤5:修改训练相关配置文件
5‑1 train.py 修改
classes_path = 'model_data/work_classes.txt' input_shape = [640, 640] mosaic = False model_path = "model_data/yolov5_s.pth" Freeze_Train = False UnFreeze_Epoch = 100 Unfreeze_batch_size = 8 #显存不足改为4/2 num_workers = 0 eval_flag = True5‑2 utils/dataloader.py 修改数据增强(适配你的光照变化需求)
打开utils/dataloader.py
get_random_data函数头部参数
def get_random_data(self, annotation_line, input_shape, jitter=.3, hue=0.0, sat=0.25, val=0.30, random=True):get_random_data_with_Mosaic函数头部参数
def get_random_data_with_Mosaic(self, annotation_line, input_shape, jitter=0.3, hue=0.0, sat=0.25, val=0.30):
hue=0.0关闭色相偏移,拒绝识别别的颜色物体;- sat、val小扰动模拟现场明暗光照变化;
- 保留随机scale缩放,适配工件远近运动成像大小变化;
- 工件非对称:注释掉flip翻转代码。
- train.py设置
mosaic=False,mosaic增强不会执行。
步骤6:开始训练模型
cd ~/yolo5/yolov5-pytorch #前台运行 python3 train.py #或者后台运行 nohup python3 train.py > train_log.txt 2>&1 & tail -f train_log.txt注意:样本数量过少会触发
ZeroDivisionError,此时需要扩充数据集;临时调试可以eval_flag=False并修改utils_fit.py跳过验证loss计算,仅用于跑通流程,不用于实际项目。
训练完成,最优权重:logs/best_epoch_weights.pth
步骤7:导出ONNX,再转OAK的OpenVINO IR模型
⚠️必须用bubbliiiing自带export_onnx.py,不能用ultralytics的export
python export_onnx.py --weights logs/best_epoch_weights.pth --input_shape 640,640 ov-convert model.onnx --output_model workpiece得到:workpiece.xml、workpiece.bin
步骤8:复制模型、标签到ROS2 oak_arm_detector包
cp workpiece.xml ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86/src/core/oak_arm_detector/model/workpiece_model/ cp workpiece.bin ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86/src/core/oak_arm_detector/model/workpiece_model/ echo "target_workpiece" > ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86/src/core/oak_arm_detector/labels_work.txt步骤9:编译ROS2包,启动空间检测节点(SpatialDetectionNetwork,深度计算真实物理尺寸过滤)
节点逻辑:不用像素面积过滤,依靠OAK双目深度计算工件真实mm物理长宽做过滤;同时识别机械臂,两者同时满足才输出匹配信号。
cd ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86 colcon build --packages-select oak_arm_detector source install/setup.bash ros2 launch oak_arm_detector oak_detector.launch.py新开终端观察话题输出
ros2 topic echo /oak/arm_work_match ros2 topic echo /oak/workpiece_xyz_mm ros2 topic echo /oak/workpiece_real_wh_mm附录:常见故障点&ImageSets相关坑
- ❌手动修改ImageSets/Main/trainval.txt:新增图片之后脚本读取旧id,报xml找不到。 ✅正确:annotation_mode=0运行
voc_annotation.py自动扫描Annotations,刷新全部ImageSets内容。 - ❌annotation_mode=2运行voc_annotation.py:不会刷新ImageSets,只会读取旧的train.txt/val.txt,新增图片不会加入训练集。
- ❌标注图片,图内无工件直接D下一张,不Ctrl+S:缺少xml,voc_annotation.py直接FileNotFound。 ✅正确:每张图片必须Ctrl+S保存,生成同名xml,空目标也是空xml。
- 图片删除操作:
- 删除JPEGImages里面的jpg;
- 删除Annotations里面对应的xml;
- 执行
python3 voc_annotation.py,annotation_mode=0,ImageSets自动剔除该id。
极简记忆版(新增一批数据只做这几步)
- 视频抽帧 → jpg复制进JPEGImages
- labelImg全部标注,每张Ctrl+S生成xml
- voc_annotation.py保持
annotation_mode=0,运行python3 voc_annotation.py👉自动更新ImageSets/Main全部txt,自动生成2007_train.txt、2007_val.txt - 执行训练。
ONNX → OpenVINO IR(xml/bin)完整转换操作步骤
环境状态:已经成功安装
openvino‑dev,mo命令可用;已经导出model.onnx(422K) ⚠️新版本mo参数:没有--output_model,改用--output_dir和--model_name
步骤1:切换到onnx所在项目目录
cd ~/yolo5/yolov5-pytorch确认model.onnx存在:
ls -lh model.onnx输出示例:-rw‑rw‑r-- 1 a a 422K 10月 8 17:21 model.onnx
步骤2:执行mo模型转换命令
mo --input_model model.onnx --output_dir ./ --model_name workpiece参数说明:
--input_model model.onnx:输入的ONNX模型文件--output_dir ./:输出到当前工作目录--model_name workpiece:生成模型文件前缀,输出workpiece.xml、workpiece.bin
如果出现算子/opset兼容报错,使用带opset参数版本:
mo --input_model model.onnx --output_dir ./ --model_name workpiece --opset 17日志提示
MO command line tool is considered as the legacy conversion API属于版本警告,直接忽略,不影响使用。
步骤3:校验转换输出产物
ls -lh workpiece.xml workpiece.bin正常会看到两个不为0字节的文件:
workpiece.xml:网络拓扑描述文件workpiece.bin:模型权重二进制文件
步骤4:复制xml/bin到ROS2 oak_arm_detector模型目录
cp workpiece.xml ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86/src/core/oak_arm_detector/model/workpiece_model/ cp workpiece.bin ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86/src/core/oak_arm_detector/model/workpiece_model/步骤5:生成类别标签文件labels_work.txt
echo "target_workpiece" > ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86/src/core/oak_arm_detector/labels_work.txt步骤6:进入ROS工作空间,编译包并source环境
cd ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86 colcon build --packages-select oak_arm_detector source install/setup.bash步骤7:启动OAK识别launch文件
ros2 launch oak_arm_detector oak_detector.launch.py步骤8:新开终端,监听业务话题,观察输出
ros2 topic echo /oak/arm_work_match ros2 topic echo /oak/workpiece_xyz_mm ros2 topic echo /oak/workpiece_real_wh_mm部署前必须修改(否则深度尺寸过滤会全部拦截工件)
打开oak_arm_detector/main_double_model.py填入你的工件真实物理毫米尺寸+合理公差
self.real_w_min = xxx self.real_w_max = xxx self.real_h_min = xxx self.real_h_max = xxx硬性对齐约束:训练图像尺寸640×640 → 导出onnx 640×640 → OAK节点内部推理输入也必须是640×640。
常见问题
mo:未找到命令:执行export PATH=$PATH:~/.local/bin,把用户本地脚本目录加入PATH;- 转换警告
legacy conversion API:忽略; - numpy版本冲突警告
ml‑dtypes requires numpy>=2.0.0:推理场景可以忽略,当前numpy=1.26.4适配YOLO训练。
完整一键复制整组命令(直接粘贴执行)
cd ~/yolo5/yolov5-pytorch mo --input_model model.onnx --output_dir ./ --model_name workpiece ls -lh workpiece.xml workpiece.bin cp workpiece.xml ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86/src/core/oak_arm_detector/model/workpiece_model/ cp workpiece.bin ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86/src/core/oak_arm_detector/model/workpiece_model/ echo "target_workpiece" > ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86/src/core/oak_arm_detector/labels_work.txt cd ~/work/2026.7ROS2/1/2026.9.3/2026./nav_ws_x86 colcon build --packages-select oak_arm_detector source install/setup.bash ros2 launch oak_arm_detector oak_detector.launch.py