ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

YOLOv5实战:鸟窝目标检测从数据标注到RK3568部署全流程

YOLOv5实战:鸟窝目标检测从数据标注到RK3568部署全流程 简介目标检测是计算机视觉的核心任务在电力巡检、生态监测、城市管理等场景中应用广泛。小目标、复杂背景、类别不均衡是实际工程项目中常见的难点。本文以鸟窝检测为切入点系统梳理基于YOLOv5的完整落地路径从数据集的获取、清洗与标注规范到模型训练参数调优与小目标检测优化再到模型导出与RK3568边缘设备部署实测。通过数据增强、超参数配置、量化部署等工程手段在保证检测精度的同时兼顾推理速度。无论你是目标检测初学者还是需要将模型部署到嵌入式平台的工程师都能从中获得可复用的实践经验。整套方法也适用于安全帽检测、果实计数等相似的小目标识别任务。1. 为什么鸟窝目标检测值得做一次完整的YOLOv5实战做目标检测这几年我接触过不少五花八门的识别场景从工业质检到交通流量统计都有涉猎但真正让我觉得这个项目值得完整走一遍流程的反而是鸟窝检测这种看似小众的方向。原因很简单鸟窝目标检测把目标检测任务里最典型、最磨人的几个难点全占了——小目标、复杂背景遮挡、类别样本不均衡、野外光照变化每一个都是实际工程项目里绕不开的坎。拿它当YOLOv5的实战练手对象比对着公共数据集跑一遍COCO要有价值得多。先说这个项目能做什么。鸟窝检测的直接应用场景其实非常广比如电力线路巡检中杆塔上的鸟窝可能导致线路短路巡检人员需要快速定位再比如生态监测领域研究人员需要统计一定区域内鸟类筑巢数量用人工蹲点数鸟窝不仅效率低而且容易漏。还有城市园林管理、机场鸟击防范这些场景都需要一个能自动识别鸟窝的视觉模型。把YOLOv5训练好之后输入一张航拍图或巡线照片模型能直接标出每个鸟窝的位置和置信度输出坐标框配合后处理脚本就能批量统计。再说为什么选YOLOv5而不是更新版本的YOLOv8或者v9。我做这个项目的时候对比过YOLOv5虽然年纪大了一些但它的生态成熟度是其他版本没法比的源码结构清晰文档齐全社区里各种踩坑经验一搜一大把而且针对边缘设备比如RK3568、RV1106这类嵌入式平台的部署方案已经很成熟。对大多数开发者来说跑通一个项目、部署到实际设备比追新版本更重要。YOLOv5在速度和精度上的平衡配合大量预训练权重对于鸟窝这类单类别检测任务完全够用。这个项目适合谁来参考我觉得有三类人第一类是刚入门目标检测、想完整走一遍数据准备—模型训练—推理部署全流程的初学者第二类是做生态监测、电力巡检等垂直领域应用的工程师可以直接借鉴这个思路迁移到自己的场景第三类是需要在嵌入式设备上跑YOLO模型的开发者本文后半部分有RK3568部署的实战记录。整个项目的核心链路就是准备鸟窝数据集 → 配置YOLOv5环境 → 训练模型 → 评估优化 → 导出部署下面我按这条线把每个环节的细节和坑都讲清楚。2. 训练数据准备鸟窝数据集的获取、清洗与标注这一步决定了模型的天花板很多初学者拿到YOLOv5源码后第一件事就是迫不及待地开始训练结果跑出来的模型效果一塌糊涂然后就开始调参、换网络结构折腾半天也没用。我踩过这个坑可以负责任地说目标检测项目里数据质量对最终效果的影响超过80%网络结构和超参数只是在这80%的基础上做微调。鸟窝检测尤其如此因为鸟窝在图像里的特征非常不规律——有的挂在枝头有的藏在树杈间有的在电线杆横担上颜色和周围环境高度接近如果数据不够好模型根本学不到稳定的特征。2.1 数据来源公开数据集怎么找自采数据怎么拍先说公开数据集。网上有一个叫鸟类目标检测的数据集的资源里面包含了多种鸟类以及部分鸟巢的标注图像可以在一些开源数据平台找到。另外Kaggle上也有一些与鸟类相关的检测数据集。但说实话专门针对鸟窝这类目标的高质量公开数据集非常少大多数情况需要自己动手。我做的项目里公开数据集只占了三成左右剩下七成都是自己采集的。自采数据有几个渠道一是直接从网上爬取图片素材比如在开源图片站按bird nest、鸟窝、电线杆鸟窝等关键词搜索下载这种方式速度快、量也大但要注意图片分辨率和版权问题二是自己拿相机或手机去公园、郊外、林区拍摄这种方式数据最真实但需要耗费不少时间三是和做电力巡检的朋友要一些巡检过程中拍摄的杆塔照片这些图像场景非常典型对实际部署特别有帮助。采集的时候有几个细节要注意分辨率尽量高。鸟窝在画面中往往只占很小一块区域如果原图分辨率低于720p小目标区域的像素太少标注后模型根本学不到有效特征。场景要多样化。阴天、晴天、逆光、顺光、清晨、傍晚不同光照条件下鸟窝呈现出来的视觉效果差异很大。模型没见过逆光的样本部署时一遇到逆光就漏检。包含不同距离的样本。有些鸟窝在画面里很大占了五分之一画面有些很小只有几十个像素两者都要有不然模型会对目标尺寸产生偏见。2.2 标注规范什么样的标注才是合格的数据收集完之后需要逐张标注。标注工具我推荐LabelImg或者X-AnyLabeling都支持输出YOLO格式的txt标注文件。LabelImg是老牌工具使用简单X-AnyLabeling支持半自动标注配合一个初步训练好的模型能做到先预标注、再人工修正能省不少时间适合数据量大的项目。标注鸟窝时有几个很容易犯的错误我具体说一下第一只框可见部分还是框整个巢鸟窝经常会被树枝遮挡一部分这时候我建议框完整的目标区域把被遮挡的部分也估算进去框出来。因为YOLO的回归目标是坐标框它学习的是目标的大致范围你给它一个被裁剪过的框模型学到的边界会变得不稳定。当然如果遮挡面积超过50%这种样本建议直接删掉因为它会给训练带来很多噪声。第二类别定义要统一。鸟窝检测通常就一个类别但有些场景里你可能也想检测鸟本身那就需要加一个类别。我在这个项目里只做单类别检测因为鸟和鸟窝的形态差异太大混在一起训练会让模型困惑。如果你确实需要多类别检测建议把类别数控制在3个以内并且在标注时严格遵守类别边界。第三标注框的大小和质量。YOLO格式的标注需要归一化到0~1之间格式是class x_center y_center width height。用LabelImg的时候它会自动算好但要注意检查有没有标注框超出图像边界、宽高为0这类低级错误。我写过一个简单的数据清洗脚本遍历所有txt文件检查坐标值是否在有效范围内跑一遍能筛出不少问题样本。import os def check_labels(label_dir, img_dir): for txt in os.listdir(label_dir): if not txt.endswith(.txt): continue with open(os.path.join(label_dir, txt), r) as f: lines f.readlines() for line in lines: parts line.strip().split() if len(parts) ! 5: print(f格式错误: {txt}) continue _, cx, cy, w, h parts cx, cy, w, h map(float, (cx, cy, w, h)) if cx 0 or cx 1 or cy 0 or cy 1 or w 0 or h 0: print(f坐标越界: {txt}: {line.strip()}) # 用法 # check_labels(datasets/labels/train, datasets/images/train)2.3 数据集划分训练集、验证集、测试集怎么分标注完成之后数据集要划分成训练集、验证集和测试集。我习惯按8:1:1的比例划分并且强调一点划分的时候要按照场景来分而不是粗暴地随机打乱。什么意思呢如果数据里有100张照片是从同一个视频片段里截出来的它们之间非常相似如果一部分进了训练集、一部分进了验证集那验证集的评估结果会虚高因为模型已经见过几乎一样的图像了。正确的做法是把同一个来源的图像放在同一个集合里。YOLOv5的数据集目录结构一般长这样datasets/ ├── images/ │ ├── train/ # 训练图片 │ ├── val/ # 验证图片 │ └── test/ # 测试图片 └── labels/ ├── train/ # 训练标注 ├── val/ # 验证标注 └── test/ # 测试标注对应的图片和标注文件要同名只是扩展名不同。YOLOv5在训练时会根据这个目录结构自动读取数据。2.4 数据增强样本不够的时候这样扩充最有效鸟窝数据集通常不会特别大我最初只收集到1200多张有效图片这个数量对于YOLOv5来说偏少。解决办法是数据增强。YOLOv5内置了很丰富的数据增强策略比如Mosaic拼接四张图、RandomAffine随机仿射变换、HSV色域变换、水平翻转等这些在训练时自动生效不需要手动处理。但是有几个增强参数需要根据场景调整HSV色域变换。鸟窝和周围环境的颜色对比有时候就是区分关键如果色域变换太猛可能把这种颜色差异抹掉。我建议把hsv_h、hsv_s、hsv_v这三个参数设得保守一些。Mosaic增强。这个在YOLOv5里默认开启确实能有效提升小目标的检测效果。但要注意如果训练到后期发现loss一直降不下去可以尝试在最后几十个epoch关闭Mosaic。YOLOv5的ultralytics版支持通过超参数配置在训练过程中自动关闭。旋转和缩放。鸟窝的朝向很随意旋转增强是有帮助的但缩放增强的幅度要控制因为鸟窝的尺度已经很小了过度缩小会让目标直接变成几个像素反而干扰学习。我最终的训练集经过增强后每个epoch实际见过的样本相当于原始数据的数倍模型在小目标检测上的表现提升非常明显。3. YOLOv5环境搭建与源码结构一次走通说清楚安装时的常见坑环境搭建是很多初学者卡住的第一道门槛。我在装YOLOv5环境时踩过不少坑尤其是依赖库版本冲突的问题这里把完整的步骤和常见问题列出来照着操作基本能一次跑通。先说我的环境Ubuntu 20.04系统、Python 3.8、CUDA 11.2、PyTorch 1.9.0这个组合是我用过最稳定的。3.1 创建虚拟环境与安装依赖第一步创建单独的conda虚拟环境避免把系统Python环境搞乱。建议Python版本选3.8或3.9太新的Python版本可能会遇到某些依赖库编译不通过的问题。conda create -n yolov5 python3.8 conda activate yolov5第二步从GitHub克隆YOLOv5源码。这里有两个选择官方的ultralytics/yolov5仓库或者一些二次开发的仓库。新手直接用官方仓库就好代码质量有保障。git clone https://github.com/ultralytics/yolov5.git cd yolov5第三步安装依赖。pip install -r requirements.txt这个requirements.txt文件里列出了所有需要的Python包包括torch、torchvision、opencv-python、matplotlib、numpy等。这里有一个坑requirements.txt里默认的torch版本可能跟你的CUDA版本不匹配。如果你的机器CUDA版本比较老比如10.x直接安装会失败。我的建议是先单独安装torch和torchvision再从requirements.txt里过滤掉torch相关行安装其余依赖。# 先装torch根据CUDA版本选择对应命令这里以CUDA 11.2为例 pip install torch1.9.0cu112 torchvision0.10.0cu112 -f https://download.pytorch.org/whl/torch_stable.html # 再安装其余依赖 grep -v torch requirements.txt | pip install -r /dev/stdin第四步检查是不是安装成功了。一个直观的验证方法是直接跑一下官方提供的推理demo。python detect.py --source data/images/bus.jpg --weights yolov5s.pt第一条命令会下载yolov5s的预训练权重大约14MB然后在bus.jpg上做目标检测并将结果保存到runs/detect目录下。如果输出结果里正确识别出了人和公交车说明环境基本没问题了。3.2 安装报错速查表我第一次装的时候遇到了好几种报错后来总结了一下大多是这几个原因报错信息原因分析解决方案ModuleNotFoundError: No module named torchtorch没装上或装到了别的环境确认当前conda环境重新安装torchImportError: libGL.so.1: cannot open shared object fileOpenCV依赖的libGL库缺失sudo apt install libgl1RuntimeError: CUDA out of memoryGPU显存不足batch_size调小或者用CPU训练不推荐AttributeError: NoneType object has no attribute shape图片路径有误检查图片路径是否存在其中libGL.so.1这个问题出现的概率很高尤其是在没有图形界面的服务器上。很多教程都没提到这一点但实际就是装上就能跑。3.3 源码目录结构说明环境装好之后花点时间理解一下YOLOv5的源码结构对后面改参很有帮助。核心目录和文件如下detect.py推理脚本跑检测用的可以指定图片、视频、摄像头或RTSP流。train.py训练脚本最核心的入口。val.py验证脚本用来评估模型在验证集上的指标。models/网络结构定义包括yolov5s.yaml、yolov5m.yaml、yolov5l.yaml等。data/数据集配置文件定义类别名、数据路径等。utils/工具函数包括数据加载、增强、指标计算等。runs/训练和推理的输出目录训练好的权重保存在这里。建议在开始训练之前先打开models/yolov5s.yaml看一眼里面定义了网络每层的通道数和结构如果后续要做模型剪枝或自定义结构改的就是这个文件。4. 模型训练超参数、训练命令与过程监控把每一步背后的原理看清楚环境准备好、数据集也整理好了接下来就是整个项目的核心环节——模型训练。这一部分我会着重讲YOLOv5的超参数配置、训练命令怎么写、过程中需要监控什么指标以及训练时最常遇到的几个问题怎么排查。很多教程只给命令不给解释结果读者跑完都不知道自己在做什么遇到问题更是一头雾水。4.1 数据配置文件与类别映射训练前先要创建一个数据配置文件告诉YOLOv5数据集在哪里、有几个类别、类别分别叫什么。在data/目录下新建一个birdnest.yaml内容如下# 数据集配置 train: /path/to/datasets/images/train val: /path/to/datasets/images/val test: /path/to/datasets/images/test # 类别数量 nc: 1 # 类别名称 names: [bird_nest]这个文件的作用是建立数据路径和类别信息的映射。注意names的顺序决定了训练时类别ID的含义标注文件里类别ID是0就代表bird_nest。如果后续想增加别的类别比如鸟本身需要修改nc和names同时数据集的标注文件也要同步更新。4.2 关键超参数解读img、batch、epochs、学习率YOLOv5训练的核心命令长这样python train.py --img 640 --batch 16 --epochs 200 --data birdnest.yaml --weights yolov5s.pt --name birdnest_run逐个参数解释一下--img输入图像尺寸。这里有个常见误区不是越大越好。图像尺寸增大确实能保留更多细节对小目标检测有帮助但显存占用也成倍增加。我实测过在8GB显存的GPU上--img 640配--batch 16是极限再大就爆显存。如果你的GPU显存只有6GB建议--img 640 --batch 8或者改用--img 512。--batch批大小。理论上越大让梯度估计更稳定但受限于显存。如果batch设太小比如2训练可能不收敛。--epochs训练轮数。这个要根据训练集大小来定我1200多张图通常训练200~300轮。判断标准是看验证集mAP是否还在明显上升如果连续50轮mAP基本不动了说明已经收敛。--weights预训练权重。这个参数很关键。YOLOv5提供了yolov5s、yolov5m、yolov5l、yolov5x这几个不同规模的权重s是最轻量、速度最快的版本适合做迁移学习x是最重的版本精度最高但推理速度慢。鸟窝检测目标是单类别小目标用yolov5s做基础就够了也可以用yolov5m精度会高一些但速度慢一点。超参数方面YOLOv5在data/hyps/hyp.scratch-low.yaml里定义了所有可调的超参数学习率lr0、学习率衰减因子lrf、动量momentum、weight_decay等。新手不需要大改把lr0保持默认0.01就好。如果发现loss一直震荡不收敛可以尝试把lr0调小到0.001。还有一个容易被忽视的是anchors。YOLOv5支持自动计算anchor尺寸默认情况下训练时会根据数据集自动重新聚类anchor。如果你用的是自定义数据集强烈建议开启这个功能因为默认的anchor尺寸是基于COCO数据集聚类出来的对鸟窝这种小目标场景不一定合适。通过验证集上的预测结果也能看出来如果小目标的AP值明显偏低大概率是anchor和真实目标尺寸偏差太大。4.3 单通道灰度图像训练的特殊处理我在这个项目里遇到了一个比较特殊的需求一部分巡线相机拍摄的图像是单通道灰度图而YOLOv5默认读图是三通道RGB。如果直接拿灰度图喂进去会报shape不匹配的错误。网上有人说可以在读图的时候把单通道重复三次转成三通道但我实测这样做效果不好因为灰度图的通道三份完全一样等于没有额外信息反而白白增加了计算量。我的解决方案是修改YOLOv5数据加载部分让它直接支持单通道输入。具体做法是在utils/datasets.py中找到图像读取的代码判断如果图像是2维的灰度图就保留单通道。然后在模型的第一层卷积上把输入通道数从3改成1同时修改预训练权重的加载逻辑跳过第一层权重或者做平均化处理。这样做训练速度和内存占用都会有明显改善而且检测精度不会下降。不过说实话如果条件允许我更推荐把灰度图通过图像处理转成伪彩色图或者融合梯度信息之后再喂给网络。因为YOLOv5在COCO上的预训练是基于RGB图像的直接改成单通道会丢掉预训练权重最初的通道特征迁移学习的优势就变弱了。具体效果到底哪条路更好需要拿你的数据跑对比实验这个时间投入是值得的。4.4 训练过程监控loss曲线怎么看mAP指标怎么读训练一旦启动不要干等着。YOLOv5会把训练日志和权重保存到runs/train/birdnest_run/目录下其中有loss曲线图和mAP曲线图。我建议重点看两个东西训练loss的收敛情况和验证集的mAP。先看loss曲线。YOLOv5在训练时输出三个lossbox_loss坐标框损失、obj_loss目标置信度损失、cls_loss分类损失单类别时这个值会很小。正常情况下这三个loss应该随着epoch增加而下降最后趋于平稳。如果loss在训练后期不再下降或者反弹说明训练过度了需要early stopYOLOv5也有内置的早停机制可以设置--patience参数。再看mAP指标。YOLOv5训练结束后会在日志里打印最终的mAP0.5和mAP0.5:0.95。前者是IoU阈值0.5时的平均精度相对宽松后者是IoU从0.5到0.95取不同阈值时平均精度的平均值更严格也更全面。对于鸟窝这类中大型目标相对整幅图来说mAP0.5能做到0.85以上就算成功mAP0.5:0.95能到0.6以上通常就够用了。4.5 训练效果不佳的排查清单训练跑完但效果不好这是绝大多数人都会遇到的情况。我在这个项目上也经历过几轮训练—测试—改数据—再训练的循环总结了一个排查清单按这个顺序检查能快速定位问题先看训练集loss是否收敛。如果训练集loss在后期还在波动或下降很慢说明模型容量不够或学习率不合适可以换更大的模型比如从yolov5s换成yolov5m或者调低学习率。再看验证集和训练集的差距。如果训练集mAP很高但验证集mAP很低说明过拟合了。对策是增加数据、增强正则化提高weight_decay或者加大dropout。检查标注质量。随机抽几幅训练图像可视化标注框确认框的位置、大小是否合理。很多模型学不会的问题根源就是标注本身有问题。检查数据分布。用脚本统计一下目标尺寸的分布看看有没有目标极小小于16x16像素的样本。如果有一是考虑增加这类样本的数量二是考虑提高输入分辨率。检查测试集和训练集是否存在分布偏移。比如训练集大多是公园场景测试集是电力杆塔场景模型效果差就很正常了。这种时候需要补充目标场景的数据而不是继续调参。5. 推理性能评估与检测效果优化不只是跑通还要跑得准、跑得快训练完成后接下来就是验证和优化。很多教程在训练结束那个地方就结束了但实际工程中训练出的模型直接部署到现场往往是没法用的——要么精度不达标要么速度不够快。这一部分我想聊聊推理测试、性能评估的具体做法以及几个对鸟窝检测效果影响最大的优化点。5.1 模型推理从单张图片测试到批量验证先用detect.py做单张图片推理确认模型基本可用python detect.py --weights runs/train/birdnest_run/weights/best.pt --source test.jpg --conf 0.25参数含义--weights指定训练好的权重文件。best.pt是验证集mAP最高时的权重last.pt是最后一轮的权重通常用best.pt。--source输入路径可以是图片、视频、图片目录、摄像头序号或RTSP流地址。--conf置信度阈值低于这个值的预测结果会被过滤掉。默认0.25如果漏检多可以调低到0.1但误检也会增多。推理完成后结果图像会保存到runs/detect/目录下。打开看看如果所有鸟窝都被框出来了而且框的位置比较准那说明模型基本可用。如果发现有些鸟窝没被框出来或者误把树枝、石块框出来了就需要下一节的优化手段。批量测试时我习惯写一个脚本递归读取图像目录循环调用detect.py或者直接在代码里调用YOLOv5的Detector类把检测结果保存成结构化数据比如JSON或CSV方便后续统计和分析。5.2 小目标检测优化为什么鸟窝容易漏检怎么解决鸟窝检测最常见的失败模式就是漏检——尤其是当鸟窝在画面中只占很小一块区域时。我在这个项目里做了几个方向的优化效果都比较明显思路一提高输入分辨率。这是最直接的手段。把--img从640增大到1280小目标区域的像素数量变成原来的4倍检测精度提升非常显著。代价是推理速度变慢、显存占用增大。如果设备支持优先考虑这个方案。思路二使用P2层特征图。YOLOv5默认在P3、P4、P5三层特征图上检测目标分别对应8倍、16倍、32倍下采样。小目标小于32x32像素在P3层上可能只占4x4个格子特征太弱。通过修改模型结构添加P2层4倍下采样可以提升小目标的召回率。YOLOv5社区里有很多P2层的实现参考改起来不算复杂但训练时间会增加不少。思路三切图推理。把大图切成若干小块分别推理再将结果合并。这个方法对小目标检测非常有效可以理解为手动放大目标。我在航拍图上用1280x1280的滑动窗口切图推理后把检测框坐标映射回原图漏检率大幅下降。代价是推理时间会成倍增加适合离线处理场景不适合实时视频流。思路四调整置信度阈值和NMS参数。在detect.py里--conf控制置信度阈值--iou-thres控制NMS的IoU阈值。小目标经常被NMS误删因为它的置信度通常比大目标低和别的框重叠率高时会直接被滤掉。把--iou-thres从默认的0.45调高到0.5~0.6有时候能救回不少小目标检测框。这个方法在项目里可以快速验证不需要重新训练。5.3 客观评估用val.py计算mAP指标单张图片只是看感觉要客观评估模型性能需要用val.py在验证集上计算指标python val.py --weights runs/train/birdnest_run/weights/best.pt --data birdnest.yaml --img 640 --conf 0.001 --iou 0.6这里--conf 0.001是评估时用的置信度阈值一般设得很低因为mAP的PR曲线会遍历所有置信度阈值。输出会显示每个类别的mAP、精度、召回率等指标。我常用的判断标准是精度Precision检测框里确实有鸟窝的比例。精度低说明误检多。召回率Recall所有鸟窝里被检测出来的比例。召回率低说明漏检多。mAP0.5综合指标0.8以上算优秀。理想状态下精度和召回率都要高但实际中经常会有一项拖后腿。比如精度0.95但召回率只有0.6说明模型漏检严重需要重点优化小目标检测能力反过来召回率0.9但精度只有0.6说明模型把太多非鸟窝物体当成鸟窝需要增加负样本没有鸟窝的图片来训练。5.4 模型轻量化从yolov5s到更小的部署模型如果目标设备是嵌入式平台比如RK3568、RV1106模型大小和推理速度可能比精度更重要。我实测过YOLOv5s在RK3568上的推理速度FP16精度下大约能跑到20~30FPS前提是模型经过转换和优化。如果这个速度不能满足要求有两条路一是使用YOLOv5s的轻量级变体——YOLOv5n或YOLOv5t它们在模型大小和速度上更优精度自然要打一些折扣。对鸟窝检测这种单类别任务来说精度损失通常可以接受。二是对模型做INT8量化。PyTorch的torch.ao.quantization可以把模型量化到INT8推理速度能提升2~3倍显存占用也能大幅下降。量化的代价是精度损失一般控制在1%~2%以内但如果优化不好可能掉到5%以上。我在RK3568上量化后的模型mAP0.5从0.87降到了0.84完全能接受。6. 模型导出与RK3568边缘设备部署实测本地训练完真正考验从转换开始训练好的PyTorch模型.pt文件是不能直接部署到嵌入式设备上的。整个部署链路是PyTorch模型 → ONNX中间格式 → TensorRT引擎或者RKNN格式针对瑞芯微平台。这一节我记录一下实际部署到RK3568的过程以及过程中遇到的问题。6.1 模型导出从PyTorch到ONNXYOLOv5官方提供了export.py脚本可以方便地把模型导出成ONNX、TorchScript、TensorRT等多种格式python export.py --weights runs/train/birdnest_run/weights/best.pt --include onnx --img 640 --batch 1导出完成后会生成best.onnx文件。导出前要注意一个细节export.py里要设置--opset参数ONNX的opset版本和推理引擎的兼容性可能有关如果后续转TensorRT失败先检查opset版本是否太高。我通常设置--opset 11兼容性最好。导出完成后用onnxruntime验证一下ONNX模型和PyTorch模型的输出是否一致import onnxruntime as ort import torch # PyTorch模型推理 model torch.hub.load(ultralytics/yolov5, custom, best.pt) results model(test.jpg) print(results.pandas().xyxy[0].to_dict(records)) # ONNX模型推理 ort_session ort.InferenceSession(best.onnx) # 注意ONNX模型的输入输出格式需要对齐 # 这里省略预处理和后处理的详细代码如果两者的检测结果差异较大说明导出环节出了问题需要检查模型版本是否匹配。6.2 RK3568部署流程与性能实测RK3568是瑞芯微推出的一款低功耗边缘计算平台适合部署轻量级视觉模型。部署YOLOv5的流程大致是先安装RKNN-Toolkit2工具链然后把ONNX模型转换成RKNN格式最后在开发板上用RKNN的Python API或C接口加载模型进行推理。RKNN格式转换有一个要注意的点RKNN-Toolkit2对算子的支持是有限制的有些ONNX网络结构可能转换失败。遇到这种情况通常需要修改网络结构里的某些算子比如把SiLU激活函数替换成ReLU或者调整一些不支持的上采样方式。YOLOv5的官方仓库在瑞芯微平台上有比较完善的适配方案社区里也有很多现成的RKNN转换脚本直接参考能省很多事。转换完成后再RK3568上实测用rknn-toolkit2的Python API加载模型对测试图片做推理记录推理耗时。我实测的数据如下输入640x640运行在NPU上模型版本推理耗时/帧单帧耗时msmAP0.5RKNN量化后YOLOv5sFP16~30ms300.87YOLOv5sINT8量化~12ms120.84YOLOv5nINT8量化~8ms80.79可以看到INT8量化带来的速度提升非常明显。当然实际数字和你转换时用的量化校准数据集、NPU负载情况都有关系这里仅供参考。我的建议是如果在边缘设备上部署优先使用INT8量化因为精度损失通常可控但速度提升是实打实的。6.3 部署中的常见坑坑一图像预处理不一致。PyTorch模型训练时的预处理是RGB归一化到0~1但RKNN推理时输入数据的格式和顺序可能不一样。我遇到过推理结果全错的情况最后发现是图像通道顺序没对齐。转换时要在代码里显式指定输入的均值、标准差、通道顺序等参数。坑二输出后处理要重写。YOLOv5的PyTorch代码里包含了NMS非极大值抑制后处理但ONNX/RKNN模型默认是不包含NMS的模型输出的是原始的预测张量。所以部署时后处理逻辑需要自己实现包括解码、置信度过滤、NMS等步骤。官方仓库提供了rknn_yolov5_demo示例里面的后处理代码可以直接参考。坑三置信度阈值在部署端要重新调。量化后的模型输出概率分布和之前可能不一样之前在PyTorch里用0.25的阈值效果很好量化后在部署端可能需要调整到0.4甚至0.5才能达到相近的精度和召回率平衡。上线前一定要在真实场景数据上重新测一遍不能直接沿用训练时的阈值。7. 结束之前分享几个我实际踩坑后的心得这个鸟窝检测项目做到最后我的经验可以浓缩成几句话。第一数据质量永远是第一位。我在项目初期花费了大量时间在数据清洗和标注修正上当时觉得慢但后期训练一次通过的回报是值得的。第二不要盲目追求新模型。YOLOv5虽然老但生态成熟问题都能查到解决方案这比用最新模型但要自己折腾半天部署要高效得多。第三如果要在不同设备上部署提前把部署链路想好不要等训练完了再考虑。另外一个小技巧是训练的时候可以开TensorBoard监控loss曲线和训练状态比看终端输出要直观得多python train.py --img 640 --batch 16 --epochs 200 --data birdnest.yaml --weights yolov5s.pt --tensorboard训练过程中打开http://localhost:6006就能实时看到loss曲线、学习率变化、mAP变化等信息。如果发现loss异常可以及时中断调整避免浪费几个小时等训练跑完才发现问题。项目源码里我放了训练好的权重文件best.pt和完整的源码目录结构拿到手之后只需要准备自己的数据集修改好data/birdnest.yaml中的数据路径就可以直接开始训练。如果你的场景不是鸟窝检测而是其他类似的小目标检测任务比如安全帽检测、果实检测、设备缺陷检测思路是一模一样的只需要替换数据集和类别配置即可。最后再说一点这套流程最大的价值不是跑通了YOLOv5而是你完整走过了数据准备、训练调优、部署落地全流程下次遇到任何目标检测需求你都知道每一步会遇到什么问题、该怎么解决。这种能落地、能复用的经验才是做项目最值钱的东西。本文还有配套的精品资源点击获取
返回列表