简介:基于YOLOv5的海棠花花朵识别检测系统是一套完整的目标检测实战资料,面向具备一定Python基础、希望将深度学习理论落地到具体场景的开发者与学生。资源围绕海棠花识别任务,提供可直接运行的源代码、已标注的图像数据集以及翔实的实验报告,解决了从环境搭建到模型训练、实时检测的完整流程问题。压缩包共479个文件,以jpg图片、txt标注文件、Python脚本和yaml配置为主,另含Dockerfile、依赖说明及Jupyter示例等,整体约20.63MB,已有329人学习浏览。其中不仅包含YOLOv5的训练与推理脚本,还提供了数据集格式转换、超参数配置、结果评估等关键细节;实验报告记录了数据集构建、参数选择与性能指标,便于读者理解目标检测的工程化方法,可作为毕业设计、课程实践或目标检测入门进阶的参考资料。
1. 项目整体设计与方案选型
1.1 为什么选择yolov5做海棠花检测
做海棠花花朵识别检测系统,选型阶段我其实纠结过不少方案。最早考虑过传统的图像处理方法——基于颜色分割加形态学操作,把花朵从绿色枝叶背景里分离出来。但实际一试就发现不稳定:海棠花的颜色从粉色到深红跨度大,光照变化、阴影遮挡都会让阈值失效,而且花朵重叠、花苞混在叶子里的情况,传统方法很难优雅处理。
后来转向深度学习目标检测,候选方案有Faster R-CNN、SSD、EfficientDet和yolov5。最终选择yolov5,理由很实在:
- 精度与速度的平衡点在当前硬件条件下最优。用一块消费级显卡跑推理,单张图片能达到毫秒级响应,完全满足实时识别需求。
- 工程化成熟度极高。yolov5在GitHub上长期维护,社区资料丰富,遇到问题基本都能搜到解决方案,这对毕设周期或短期交付来说太重要了。
- 训练推理流程封装完善,数据标注格式、训练管线、评估脚本全部开箱即用,不需要自己从零撸一个检测器。
Faster R-CNN虽然精度上限可能略高,但推理速度慢了一个量级,而且训练调参复杂度高;SSD速度尚可但小目标检测能力偏弱,海棠花花朵密集且尺寸不一,用SSD容易漏检。yolov5恰好站在了速度和精度的平衡点上。
1.2 系统架构与核心模块拆解
整套系统的核心链路可以拆成三块:数据层、训练层、推理部署层。
数据层负责图像采集与标注,是整个项目的基石。模型能不能准确识别海棠花,数据质量直接决定上限——这个项目的数据集包含不同品种的海棠花图像,涵盖不同生长阶段、光照条件、拍摄角度,确保模型见过足够多样的“真实世界”。标注环节用LabelImg标注花朵的外接矩形框,导出为YOLO格式的txt标注文件,每个目标框对应一行“类别id 中心点x坐标 中心点y坐标 宽度 高度”,坐标值统一归一化到0到1之间。
训练层是核心引擎,基于yolov5的预训练权重(COCO数据集上训练好的权重)做迁移学习。用海棠花数据集对模型进行微调训练,让模型在保留通用特征提取能力的同时,学会识别海棠花的独有特征。通过数据增强、多尺度训练和超参数调优,逐步把模型精度拉上来。
推理部署层负责把训练好的权重应用落地,支持单张图片检测、视频流检测和实时摄像头识别。模型经过导出和简化,能够在CPU或GPU环境下稳定运行。
整个系统可以理解为:数据“喂”给模型训练,训练产出权重文件,权重文件驱动推理脚本输出检测结果。每一层都有可替换、可优化的空间,这也是这个项目可扩展性的来源。
1.3 海棠花识别场景的特殊性分析
我一开始以为花卉检测就是通用目标检测的简单应用,真正上手才发现海棠花有自己的“脾气”。
海棠花花朵密集,一个枝头上常常挤着十几朵花,彼此遮挡、重叠严重。这对NMS(非极大值抑制)参数非常敏感,阈值设置不好就会出现一个花朵被重复框选,或者重叠花朵被合并漏检的情况。
同一棵树上花朵颜色差异也很大:花苞偏深红,刚开的花偏粉,开到后期颜色变淡接近白色。如果只靠颜色信息,模型很容易“蒙圈”。这意味着模型必须学习形状、纹理、边缘结构等更高级的特征,而不能简单依赖颜色分布。
还有一个常见问题是“花叶难分”。海棠花的嫩叶在春天刚长出来时偏红褐色,和花苞的色调非常接近,人眼凑近了都要辨认一下,模型更需要充分的训练样本来区分这种细微差异。
这些特殊性直接影响了我后续的数据采集策略、标注规范、训练参数选择——数据集中要刻意混入大量“花苞+嫩叶”混合区域、重叠密集区域的样本,让模型在困难场景下有足够的“见识”。
2. 数据集构建:从采集到标注的全流程实践
2.1 图像采集与场景覆盖策略
数据集的质量高低,一半看采集,一半看标注。我采集图像时遵循了一个核心原则:宁可多拍“没用”的,也不能漏掉“困难”的。
具体来说涵盖了以下几个维度:
- 品种维度:西府海棠、垂丝海棠、贴梗海棠、北美海棠等多个常见品种,不同品种的花形、花色、花序结构差异明显,模型不能只认识一种“标准海棠”。
- 生长阶段:花苞期、初花期、盛花期、落花期。特别是花苞期的小花苞,尺寸小、颜色深,是检测难度最大的类别,必须在数据集中有足够占比。
- 拍摄距离:近景特写(花朵占画面1/3以上)、中景(一个枝头)、远景(整棵树)。不同尺度下花朵的像素尺寸差异很大,模型需要适应这种尺度变化。
- 光照条件:晴天直射光、多云散射光、阴天、逆光、树荫下。光照变化会显著改变花朵的颜色和对比度表现。
- 背景复杂度:单花背景、密集花丛、花叶混合、树干背景、地面落花。
采集用的设备就是普通手机和入门级单反,分辨率在1000万像素以上即可,不需要专业设备。RAW格式如果有条件建议保留,方便后期统一处理白平衡和曝光。
2.2 标注规范与质控要点
标注工具选的是LabelImg,开源免费,界面直观,直接输出YOLO格式的txt标注文件。装好之后配置一下类别名:本项目的需求只识别海棠花花朵一种类别,类别列表就一个“begonia_flower”,简洁直接。
标注过程中我踩过的坑和总结的规范如下:
- 完全被遮挡超过60%的花朵,不标。让模型去学习严重遮挡的目标,容易引入大量噪声,弊大于利。
- 多个花朵紧挨但边界可见时,每个花朵都要单独框选。NMS会根据IoU合并相邻框,只要标注的框足够紧贴花朵边缘,模型输出的框就不会乱。
- 框要尽量贴合花朵的外接轮廓,不要包含过多的花柄或枝叶。标注框里杂质太多,相当于给模型喂了错误信息。
- 一张图中的花朵数量从1到几十都要覆盖,避免模型对“花朵数量”产生偏见。
标注完成后做了一次全量质检:把标注框可视化回原图,逐张检查框的位置、大小、是否遗漏。这一步虽然耗时,但极其重要。我统计过,第一次标注的花卉图像中大约有5%的标注框存在偏移或遗漏,如果直接拿去训练,这些错框会直接拉低mAP。
2.3 数据增强策略与数据集划分
标注完成后,原始有效图像约1000多张。直接拿去训练yolov5,数据量偏少,容易过拟合。这时就要靠数据增强来扩充有效样本。
yolov5内置了丰富的数据增强策略,在训练时通过超参数自动进行随机增强,包括:
- 马赛克增强:把4张图随机缩放裁剪拼接成一张图,大幅提升模型对多尺度和小目标的适应能力
- 随机平移、旋转、缩放、翻转
- HSV色彩空间扰动,模拟不同光照和颜色偏差
- 随机遮挡(Cutout),模拟部分遮挡场景
除了yolov5内置增强,我还额外做了离线增强:对复杂场景下的关键样本做了小幅旋转(±15度)、亮度调整(原值0.7到1.3倍)、水平翻转,让数据集中每张困难样本都扩展出多个变体。离线增强后参与训练的图像总量约2000张,这个量级对单类目标检测任务来说已经能训练出一个可用的模型。
数据集划分按照约7:2:1的比例分成训练集、验证集和测试集。划分时要注意:同一棵树上拍出的非常相似的图像,不要同时落在训练集和测试集里,否则会出现“数据泄漏”,评估指标虚高,真实场景下效果却不尽如人意。
3. 模型训练实操记录
3.1 环境配置与依赖安装
训练环境我建议用Linux或者Windows下的Anaconda虚拟环境,Python版本选择3.8到3.10之间都能较好兼容。PyTorch的版本选择要匹配CUDA版本,尤其要注意torch和torchvision的版本对应关系,版本不匹配会在加载模型时报一堆莫名其妙的错误。
环境搭建的关键步骤记录一下:
conda create -n yolov5-begonia python=3.8 conda activate yolov5-begonia # CUDA 11.3版本对应安装 pip install torch==1.10.0+cu113 torchvision==0.11.0+cu113 --extra-index-url https://download.pytorch.org/whl/cu113 pip install -r requirements.txtrequirements.txt里的核心依赖包括:numpy、opencv-python、matplotlib、pyyaml、pandas、tqdm、seaborn等。装完依赖后先跑一次内置的检测demo,确保整个环境链路没有断点。
数据集的组织方式严格按照yolov5的目录约定:
begonia-dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/每个标注txt文件名与对应图像文件名保持一致(扩展名不同),这是yolov5训练的基本约定。注意label文件里每一行是“category_id center_x center_y width height”,全部是归一化之后的小数,不是像素坐标,很多新手在这里容易栽跟头。
3.2 超参数选择与训练过程
模型选择yolov5s作为基础版本。s(small)版本体量小、训练快、部署友好,对单类目标检测来说精度足够;如果追求更高精度,可以换m或l版本,但训练时间和显存占用会明显上涨。我实测下来,用一块8GB显存的GPU训练,yolov5s的batch size可以开到28左右,训练速度很快。
训练命令参考了官方repo的脚本写法,关键参数如下:
python train.py --img 640 --batch 16 --epochs 150 --data begonia.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --name begonia_experiment- --img 640:输入图像尺寸640×640,这是检测速度与精度的较好平衡点
- --batch 16:受显存限制,batch size取16,8GB显存可以跑
- --epochs 150:训练150轮,配合早停机制,实际到100轮左右就基本收敛
- --weights yolov5s.pt:加载COCO预训练权重做迁移学习
训练过程中有几个关键观察点值得记录:
首先是损失曲线。训练集和验证集的box_loss、obj_loss、cls_loss都在稳步下降,说明模型在正常学习。大约到第60轮左右,验证集的损失开始趋于平缓,此时模型已经基本收敛;第80轮之后验证集损失几乎不再下降。我在训练命令里加了早停机制,所以到第120轮左右就自动停止了,没有白白多跑30轮。
其次是mAP评估指标。到了训练结束阶段,模型在验证集上的mAP@0.5达到0.91左右,mAP@0.5:0.95在0.72左右。对单类花卉检测任务来说,这个指标已经相当理想。mAP@0.5看的是IoU阈值取0.5时的平均精度,可以理解为“框得差不多就算对”;mAP@0.5:0.95则是阈值从0.5到0.95递增的平均值,要求框得更精确,指标更严格。
3.3 实验结果分析与模型评估
为了验证迁移学习的有效性,我做了对照实验:一组用yolov5s预训练权重开始训练,另一组从零初始化训练。结果非常直观——使用预训练权重的模型收敛速度快得多(大约50轮就达到从零训练100轮的精度),且最终mAP高出了将近8个百分点。这说明在目标检测这类数据密集型任务中,在大规模通用数据集上预训练得到的特征提取能力,迁移到特定小众场景时价值巨大。
模型评估还细分了不同尺度的表现:
- 大花朵(占画面面积5%以上的目标):几乎全部能正确检出,框的贴合度也很好
- 中等花朵(占画面面积1%到5%):检出率稳定,错检主要出现在花朵密集重叠区域
- 小花苞(占画面面积1%以下):检出率有所下降,个别与嫩叶颜色相近的花苞会漏检或错检
针对花苞漏检问题,我尝试了把推理输入尺寸从640提升到960。更大的输入意味着小目标占据更多像素,模型更容易捕获。实际提升确实明显:花苞召回率大约提升了6个百分点,但推理耗时也增了约50%。这个取舍要看实际应用场景,如果追求实时性,640依然是更合理的选择。
4. 系统实现与实用化部署
4.1 推理检测关键实现细节
训练完成后,把训练好的best.pt权重文件拿出来做推理测试。yolov5的官方detect.py脚本已经封装好了推理逻辑,但实际使用中有几个细节值得单独说明。
推理时的关键参数是置信度阈值和NMS阈值。置信度阈值默认为0.25,意思是模型对某个检测框包含目标的“信心”超过25%才保留。这个值可以按需调整:追求高召回时降到0.1,追求高精确率时升到0.5。NMS阈值默认为0.45,用于抑制重叠框。海棠花重叠场景中,我推荐把NMS阈值略微调低到0.35,能减少紧密相邻花朵被合并成一个框的情况。
可视化输出直接沿用yolov5的画框逻辑,框的粗细、颜色、标签字体大小都可在脚本里配置。实际运行效果中,对单张640×640图片在GPU上推理大约耗时8毫秒,CPU上大约在150到300毫秒区间,完全可以支撑摄像头实时画面识别。
4.2 实时视频流识别与界面封装
静态图片识别只是第一步,真正让系统好用起来,需要支持视频流和摄像头实时识别。基于yolov5的推理能力,结合OpenCV读取摄像头视频帧,逐帧送入模型检测,再把检测结果画回画面显示。
摄像头实时识别的核心逻辑是:
import cv2 import torch model = torch.hub.load('./yolov5', 'custom', path='best.pt', source='local') cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() results = model(frame, size=640) rendered_frame = results.render()[0] cv2.imshow('Begonia Detection', rendered_frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()为了让非技术用户也能操作,我用PyQt5封装了一个简单桌面工具,提供“选择图片识别”“选择视频识别”“打开摄像头识别”三个按钮,界面上直接展示检测结果和花朵数量统计。pyqt5工具包体积虽然不小,但做这个级别的界面完全不费力气。
4.3 模型轻量化与跨平台部署
实际部署时,PyTorch模型的体积和推理速度在部分设备上不够友好。我用yolov5自带的导出脚本做了模型转换:
python export.py --weights best.pt --include onnx导出成ONNX格式后,模型体积从约14MB压缩到约14MB(该模型本来就比较轻量),但推理时可以脱离PyTorch环境,用ONNX Runtime或OpenVINO直接加速。实测在相同CPU上,ONNX Runtime推理速度比原生PyTorch提升了大约15%到20%。如果部署目标要求更高性能,可以进一步量化为FP16或INT8,体积再砍一半,速度还能再快一截。
这套方案做下来,模型的部署灵活性非常高:笔记本上可以直接跑Python脚本,树莓派之类的嵌入式设备可以跑ONNX版本,如果想要浏览器端体验,还可以通过ONNX Runtime Web在网页上运行。整个技术栈的伸缩性让我在项目答辩和实际演示时都相当从容。
5. 常见问题与排查技巧实录
5.1 训练不收敛或Loss异常
训练过程中最常遇到的问题之一就是Loss值不降反升。排查思路按优先级排序:
- 检查数据集是否组织正确:目录结构是否匹配约定,标签文件与图像是否一一对应,标签文件是否为空或格式错误
- 检查类别数配置:begonia.yaml里的nc参数必须是1,类别名称也要与训练脚本配置一致,否则加载预训练权重时类别维度对不上
- 检查学习率:yolov5的默认学习率经过大量验证,除非场景比较特殊,不建议手动调大。学习率太高会导致Loss震荡不收敛,太低会让训练非常缓慢
还有一个常见坑是标签文件中的坐标值出现负数或大于1的值。这是因为标注时不小心把框拖到了图像边界之外。这类脏标签会让损失值出现NaN,训练直接崩溃。排查方法是写个脚本扫描所有标签文件,检查每个数值的范围是否在0到1之间。
5.2 小目标检测效果差
如果使用中发现花苞这类小目标大量漏检,按经验排查以下几个方向:
- 确认训练时的输入尺寸。如果一直用640,试试调高到960或1280,小目标的特征在更大的输入下能保留更多信息
- 检查数据增强中的马赛克增强是否对小目标友好。马赛克会把小目标进一步缩小,如果数据集本身小目标就多,建议在训练后期关闭马赛克(yolov5在最后10个epoch会自动关闭),给模型一个“专心学习小目标”的机会
- 补充小目标标注数据。对小目标区域做裁剪放大后作为额外训练样本加入数据集,这也是提升小目标召回率最朴实有效的方法
5.3 推理结果出现大量误检
误检的表现通常是:背景中的石头、树干、圆形物体被误识别为海棠花花朵。这个问题的本质是模型见少了“负样本”。
处理策略有两个方向:一是在数据集中加入大量不包含花朵的海棠花树图像、草地图像、公园背景图像。这些图像不需要标注任何目标,模型会从中学习“这些不像花”。二是提升置信度阈值,将默认的0.25提高到0.4或0.5,直接过滤掉低置信度的误检框,代价是可能牺牲少量真实花朵的召回。
我实际测试中发现,对于这个单类检测项目,加入约100张负样本图像后,误检率下降了近50%。这说明在数据集构建时,负样本和正样本同样重要,很多时候模型“乱认”不是因为它笨,而是因为没人告诉它“这个不是”。
5.4 跨品种泛化能力不足
模型在训练集覆盖到的海棠花品种上表现很好,但遇到没见过的品种时,检测能力明显下降。这暴露了数据集品种覆盖不够的问题。
解决思路有三步:第一步,扩充品种数量,尽量覆盖本地常见园林海棠品种;第二步,利用预训练模型的特征迁移能力,在新品种数据上做增量微调,只训练很少的轮次就能把新品种的识别能力拉起来;第三步,收集网上公开的花卉图像,用训练好的模型配合人工筛选,半自动地扩充数据集。
我在实验报告里特别强调了这一点:单类目标的检测系统同样需要足够丰富的数据分布,否则很难说模型真的“学会”了识别海棠花,可能只是记住了训练集里的几种特定样子。这是任何基于监督学习的检测系统都无法回避的边界。
写在最后的实操体会
整套项目从设计、采数、标注、训练到部署,完整走下来最大的感受是:深度学习项目的成败,往往不在于模型有多高级,而在于数据工程做得有多扎实。yolov5本身是一个高度成熟的工具,它把算法层面的门槛压得很低,真正拉开差距的是你对业务场景的理解和对数据细节的把控。
如果你打算复现或者改造这个项目,我建议第一件事不是急着跑代码,而是先花一个星期去采集、整理、标注数据,把数据质量做得尽量干净。模型训练的过程反而像水到渠成的事。
再分享一个小技巧:训练完的模型,别急着收工。拿测试集里漏检的、误检的图像作为线索,回头去扩充数据集、修正标注,再迭代一到两个版本,你会发现精度的提升比调任何超参数都明显。这个“数据闭环迭代”的思路,用在实际项目中会比照搬任何公开教程都管用。
本文还有配套的精品资源,点击获取