尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

YOLOv5实战:冬虫夏草生长检测的完整工程链路解析

YOLOv5实战:冬虫夏草生长检测的完整工程链路解析 简介本资源是一套面向计算机视觉初学者与农业AI应用开发者的YOLOv5目标检测实战项目聚焦冬虫夏草生长早期识别这一细分农业场景解决高分辨率田间图像中单类别微小目标精准定位难题。压缩包共1552个文件含748张640×482分辨率RGB训练/验证图像、615个YOLO格式标签txt、52个配置yaml、51个核心py脚本及训练好的.pt权重总大小189.89MB结构完整覆盖数据准备、模型训练、可视化分析全流程。已有273人学习下载资源内置20epoch训练结果mAP0.5达0.96、混淆矩阵、PR/F1曲线等评估产物并保留未收敛潜力便于用户继续优化。所有代码经实测可直接运行配套数据标注规范、目录层级清晰显著降低农业视觉项目复现门槛。 项目里最珍贵的不只是那套训练好的权重还有从零到一跑通整个流程的工程经验。这篇文章我会按“为什么做、数据怎么搞、模型怎么训、权重怎么用、坑怎么避”的顺序把YOLOv5做单类别冬虫夏草生长检测这件事的完整链路拆开讲清楚。整个过程没有玄学每一步都能落地。1. 项目拆解冬虫夏草生长检测到底在检测什么1.1 场景痛点与项目价值冬虫夏草是蝙蝠蛾幼虫被虫草菌侵染后形成的复合体野外状态下能被人眼直接观察到的是露出地表的那截子座。实际业务里不管你是做产区资源调查、人工抚育效果评估还是辅助采挖定位第一步都是同一个问题把草地里的冬虫夏草找出来。这事放在人眼面前不难但放到规模化场景里就麻烦了。一个调查样方可能几百平方米靠人蹲在地上逐块排查效率低且费腰如果用无人机或者全景相机采集图像回来人工数那更是灾难一张高分辨率影像里草、土、石头、枯枝和虫草子座混在一起人看一小时就视觉疲劳了。目标检测模型干的就是这个活把图像里属于虫草目标的区域框出来并且告诉你置信度有多高。这个项目最终确定“1类别”原因是核心业务只需要区分“虫草”和“背景”二分类语义。不需要区分产地、不用鉴别品级、也不需要识别子座和虫体的连接关系那么把模型复杂度降下来把单类别的精度做上去就是性价比最高的路线。1类别模型有一个天然优势类别间混淆的风险完全不存在模型只需要专注学习“虫草目标”相对背景的视觉差异性收敛难度比多类别模型小很多所需的标注量和训练轮次都更友好。另外你需要知道“生长检测”在这里有两层含义。第一层是静态检测即从单张图像里定位出虫草目标第二层是动态监测即通过不同时间点的检测结果对比判断虫草出土、生长、成熟甚至腐烂的阶段变化。本次项目交付的模型和权重核心覆盖第一层但按固定点位周期拍摄的思路来使用就能平滑支撑第二层应用。1.2 为什么选YOLOv5而不是更高版本或其他模型目标检测领域现在可选方案很多YOLOv8、YOLOX、SSD、Faster R-CNN摆在一起难免选择困难。我从项目实际角度说说为什么仍然选YOLOv5。第一生态成熟度高。YOLOv5从2020年发布到现在社区积累了海量的教程、调参经验、部署方案和踩坑记录。你遇到一个问题搜出来的答案很可能就是针对YOLOv5的这能极大缩短排查时间。模型选型不能只看性能指标还要看“出了事你有没有人可问”。第二工程化最顺手。数据格式、训练命令、权重管理、推理接口都封装得很干净。一个训练好的weights/best.pt配一个detect.py就能跑图片、视频、摄像头部署到服务端或者边缘设备都有成熟的导出路径。第三单类别场景下精度足够。冬虫夏草目标不算极端微小形态上子座呈细长棒状直立破土和背景有明确边界。YOLOv5s级别的模型在640分辨率下就能有很好的表现往上换m或l模型收益有限反而推理变慢。如果盲目用更重的模型在嵌入式设备上的部署成本会翻倍这是实际项目的隐性代价。做个简单对比可能会更直观方案优点在本项目中的劣势YOLOv5生态好、部署方便、单类别精度够结构相对经典新特性少YOLOv8结构更新、训练更方便部分老设备部署资料少改动成本高YOLOX精度不错、无锚框工程资料相对少调试门槛高Faster R-CNN精度上限高推理太慢不适合批量和实时巡检YOLOv5的推理速度在单类别任务上让我放心很多。实测一张1280x1280的野外巡检图用yolov5s的FP16模式在RTX 3060上推理时间大约在15到20毫秒即使只跑CPU也能做到每秒几张图这个效率是两阶段检测器给不了的。2. 动手之前环境搭建与数据工程2.1 运行环境配置与依赖安装拿到项目代码后第一步不是急着训练而是把环境铺好。这个项目基于YOLOv5官方框架改造依赖项集中在requirements.txt里。我建议用 conda 建一个独立环境避免把系统Python搞乱。conda create -n yolo-cordyceps python3.9 conda activate yolo-cordyceps cd yolov5 # 项目根目录 pip install -r requirements.txtrequirements.txt 里核心的包无非就是 torch、torchvision、opencv-python、numpy、matplotlib、pyyaml、tqdm 这些。需要特别注意PyTorch版本和你的CUDA版本匹配。直接用官方默认的requirements安装会自动装CPU版还是GPU版不一定最好根据显卡驱动手动安装对应版本的PyTorch。我遇到过不少人在这一步卡住训练时报“Torch not compiled with CUDA enabled”就是因为装成了CPU版。建议先跑一行命令验证环境python -c import torch; print(torch.__version__, torch.cuda.is_available())输出里True才是GPU环境False的话就算能训练也是龟速。还有一点如果显存紧张可以适当降低batch size这个后面训练参数部分细说。2.2 数据采集与标注规范数据是检测项目的粮食冬虫夏草这种垂直场景没有现成公开数据集只能自己拍或者合作方提供。我先说采集环节的几条经验采集时尽量覆盖不同生长阶段、不同光照条件、不同背景复杂度。清晨和傍晚的光线、阴天和晴天的色温差异非常大如果只在晴天中午拍模型很容易把光线特征当成目标特征泛化能力会很差。我建议一个简单的配比晴天60%、阴天30%、弱光10%多角度俯视为主、侧视为辅拍摄。拍摄设备不必追求高端像样的手机就行但要注意分辨率不能太低建议不低于1080p。因为虫草子座相对细小图像太小的话目标在图中可能只有几十个像素标注和检测都困难。标注工具推荐LabelImg或者X-AnyLabeling都是开源免费工具。这个项目是单类别检测标注时统一打一个标签比如cordyceps不需要细分。但有个关键点边界框怎么画直接影响训练效果。冬虫夏草的子座是细长型的如果严格按照外接矩形框框大多数情况下都是扁长条长宽比可能到5:1甚至8:1。YOLO的锚框机制对极长宽比目标不算友好训练时容易出现定位偏差。我的实践做法是子座外露部分紧密框住但不要把虫体部分地下部分算进去同时允许上下各留2%左右的边距避免截断子座尖端。这么做可以稍微降低长宽比的极端程度让模型收敛更稳定。标注完成后每个txt文件里是归一化后的坐标class_id x_center y_center width height。建议写个小脚本检查数据import os for label_file in os.listdir(labels/train): with open(os.path.join(labels/train, label_file), r) as f: for line in f: parts line.strip().split() assert len(parts) 5, f{label_file} 格式错误 x, y, w, h map(float, parts[1:]) assert 0 x 1 and 0 y 1, f{label_file} 坐标越界 assert 0 w 1 and 0 h 1, f{label_file} 宽高越界坐标越界这类问题很隐蔽训练时不一定会报错但会严重污染loss导致模型不收敛。2.3 dataset.yaml 配置与数据划分YOLOv5框架通过yaml文件告诉训练脚本三件事训练集路径、验证集路径、类别数量。这个项目的配置文件大概长这样train: data/cordyceps/images/train val: data/cordyceps/images/val nc: 1 names: [cordyceps]数据目录结构按YOLOv5要求组织data/cordyceps/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/数据和标签必须严格同名比如img_001.jpg对应img_001.txt否则训练时这张图会因为没有标签而被自动忽略。训练集和验证集的划分我习惯按9:1来如果样本量特别少少于500张可以试8:2但不要低于7:3否则训练数据不够很容易过拟合。划分图片时建议用脚本随机拆而不是手动拖文件夹。顺手生成一个train.txt或val.txt的路径列表也可以不过YOLOv5按目录方式读取已经足够不必额外生成。提示验证集要保证“没被模型见过”千万别把训练集里同一张图的不同裁剪也放进去否则验证指标虚高换真实场景立刻打回原形。我自己就吃过这个亏数据增强后的图片混进了验证集mAP从0.95掉到0.72排查了半天。3. 模型训练与权重使用全解析3.1 迁移学习与预训练权重选型训练YOLOv5时最忌讳的就是从零开始训。随机初始化的模型在几千张图上要同时学习特征提取、目标定位和类别判别收敛慢且容易过拟合。这个项目我强烈建议用COCO预训练权重做迁移学习。yolov5s.pt、yolov5m.pt这些预训练权重是在COCO数据集上训练好的已经能提取比较通用的视觉特征比如边缘、纹理、颜色分布、局部形状。冬虫夏草虽然不在COCO的80类里但作为视觉目标它同样由基本的边缘和纹理组合而成。迁移学习相当于让模型带着“已经会看东西”的基础来学新任务只需要微调后面几层就能适配新类别。选哪个规模的预训练权重看你的算力和目标大小。yolov5s最轻量显存占用小适合快速迭代yolov5m更重但特征提取能力更强。对于单类别检测yolov5s是首选yolov5m只是备选。如果训练中发现小目标漏检严重优先调整分辨率和锚框而不是盲目上大模型。下载好的权重放到项目根目录命名保持yolov5s.pt即可训练命令中会自动识别。如果因为网络原因下载不下来可以用你本地已有的任意YOLOv5权重文件只要结构是对应的都能作为预训练起点。3.2 训练命令与关键超参数解释训练入口是train.py项目的核心训练命令如下python train.py --data data/cordyceps.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 150 --name cordyceps_run1每个参数背后都有讲究我逐个说--img 640表示输入图像分辨率。YOLOv5会等比缩放输入图像到640x640不足部分补灰边。冬虫夏草子座是细小目标如果用640明显感觉漏检多就上1280但显存占用会变成原来的4倍实测RTX 3060 12G显存下yolov5s batch 8能跑1280再大就悬了。冬虫夏草目标大概占图像面积的0.5%到5%我个人建议如果硬件允许直接上1280小目标检测效果提升非常明显。--batch 16是每个batch的图像数量。显存是硬约束batch太大直接OOM。与其纠结理论最优值不如用“能跑最大batch的70%”作为一个稳键起点。batch太小小于8会让BN层统计不稳定训练震荡明显。--epochs 150是最大训练轮数。单类别模型收敛比较快一般80到120轮就能达到稳定状态150轮是给足余量。YOLOv5自带早停机制如果连续50轮验证集指标没有提升会自动停止你不需要一直守着。开启方式是在train.py里指定--patience 50。可以用一批关键超参数体验一下参数默认值本项目推荐原因--img640640或1280目标较小分辨率优先--batch1616或8看显存--epochs300150单类别收敛快--patience10050避免无效等待--cacheFalseTrue小数据集加载更快--cos-lrFalseTrue余弦退火更稳--cache True是让数据预加载到内存里对几千张图的数据集来说能显著减少训练过程中读盘的等待时间。3.3 训练好的权重加载与推理训练结束后runs/train/cordyceps_run1/weights/下会出现两个文件best.pt和last.pt。best.pt是验证集上表现最好的权重last.pt是最后一轮的权重。日常使用必须选best.pt这基本是共识。单张图片推理用detect.pypython detect.py --weights runs/train/cordyceps_run1/weights/best.pt --source data/test/images/img_001.jpg --conf 0.5 --img 640输出结果会保存到runs/detect/exp目录。--conf 0.5是置信度阈值低于该值的预测框会被过滤。野外场景的稀疏目标建议阈值设0.4到0.5宁缺毋滥减少误报。如果你的系统里没有detect.py或者想集成到自己的程序里可以用torch.hub加载import torch model torch.hub.load(ultralytics/yolov5, custom, pathweights/best.pt, force_reloadTrue) model.conf 0.5 model.iou 0.45 results model(test_img.jpg) results.show() results.print()用torch.hub方式加载的训练权重不需要重新安装YOLOv5就能直接运行对生产环境接入比较友好。需要注意hub加载会自动联网检查仓库版本离线环境可能有问题需要提前把库clone到本地并设置sourcelocal。摄像头实时推理也简单python detect.py --weights weights/best.pt --source 0 --conf 0.5这会打开电脑摄像头对每一帧实时做检测。如果落地到野外巡检这个模式配合USB摄像头或者网络摄像头RTSP流都能用RTSP流的source填rtsp://ip:port/stream即可。4. 结果怎么看评估指标与模型调优4.1 训练日志里的关键指标解读训练跑完后打开runs/train/cordyceps_run1/results.png会看到一整套训练曲线包括loss曲线、Precision曲线、Recall曲线、mAP0.5曲线、mAP0.5:0.95曲线。我逐一看这些指标。loss曲线分三部分box_loss框回归损失、obj_loss目标置信度损失、cls_loss分类损失。对于单类别模型cls_loss本来就趋近于0重点看box_loss和obj_loss是否稳定下降并收敛。Precision精确率表示所有被模型预测为“虫草”的框中真正是虫草的占比。Recall召回率表示所有真正的虫草中被模型成功找出来的占比。这两个指标天然互斥调阈值时只能二选一权衡。在冬虫夏草巡检场景我个人倾向于保Recall因为漏掉一株虫草可能意味着漏掉一个样本点后期人工补采成本太高多框几个非目标后期人工复核成本相对低。mAP0.5是IoU阈值0.5下的平均精度这是最常用的综合指标。单类别任务中mAP0.5能达到0.9以上就算非常优秀了。mAP0.5:0.95是更严格的指标IoU从0.5到0.95每隔0.05取一次平均值它更关注边界框定位的精细程度。如果你做的是科研任务mAP0.5:0.95是论文里绕不开的指标如果只是业务部署mAP0.5够用了。4.2 单类别模型的调优方向训练完发现指标不行先别急着调参用几个方向排查第一先看验证集效果图。运行detect.py后打开标注了预测框的图片观察错误类型。如果目标被漏检得很均匀说明模型泛化不足可能是数据不够或者数据分布太单一需要补充更多样性的数据。如果目标被框出来了但框的位置偏移明显说明回归损失还没收敛可以增加训练轮次或调低学习率。第二针对小目标优化。冬虫夏草子座细长直接提高--img到1280往往最简单有效。但随之而来的显存压力可以配合降低batch size解决。还有一种思路是给模型单独计算自适应锚框YOLOv5默认会从数据里自动重新聚类锚框不用担心手动配置。如果想手动开启训练时加--noautoanchor会禁用这个功能不建议新手动。第三调整置信度阈值。训练后的权重默认conf阈值是0.25。如果推理时假阳性太多把草叶、枯枝当成虫草把--conf提到0.5甚至0.6。反之如果漏检太多就降到0.2以下。这个参数只需推理时调整不需要重新训练性价比极高。第四数据增强已经是YOLOv5默认配置里的一部分Mosaic、仿射变换、HSV扰动等不需要额外设置。但如果数据量很少少于300张建议把Mosaic增强关掉或降低比例因为数据太少时大比例拼接反而会让模型学到不真实的特征。调优并不是越复杂越好。这个项目的数据和任务规模下20到30组有效图片配合yolov5s已经可以训练出能实际使用的模型。高手和新手的差距往往体现在对数据的理解上而不是模型结构上的花活。5. 实战踩坑常见问题与排查技巧5.1 训练阶段的高频问题不夸张地说训练阶段80%的报错集中在这几类先把这些整明白能省非常多的时间。CUDA out of memory这是最经典的一个。YOLOv5默认会自动开启Mosaic增强并且训练时图像是带上下文的显存占用比推理时高不少。解决优先级先降低batch到8或4还不行就降低imgsz到480或512再不行换yolov5n更轻量。不建议一开始就关闭Mosaic它对你的训练效果帮助很大。Dataset not found / 路径错误YOLOv5用的是相对路径还是绝对路径取决于你的yaml文件怎么写。如果你的项目从A目录拷贝到B目录yml里的相对路径就失效了。我的建议是在data/cordyceps.yaml里直接写绝对路径虽然不够优雅但绝对不出错。labels格式不对导致训练时所有图都没有目标YOLOv5要求标签文件是YOLO格式的txt每行对应一个目标。如果你用VOC格式的xml标注直接用脚本转换时容易把坐标算错像素坐标和归一化坐标搞混。转换后务必用可视化脚本画一遍框检查不要只管“能训练”。训练速度极慢如果不是GPU版本没装对那就是数据读取成了瓶颈。建议加--cache True把数据一次性缓存到内存。另外确认你的数据是jpg不要用pngpng解码更慢且占用内存更大。5.2 推理与部署阶段的隐藏坑训练完成后权重的使用阶段也有几个容易翻车的地方。模型加载报KeyError这通常是因为用不同版本YOLOv5训练的权重加载到另一个版本的代码里。YOLOv5的模型状态字典在不同commit间会有字段差异。解决办法很简单用训练时的那个项目代码做推理别混版本。推理结果为空但训练指标正常这是置信度阈值和NMS阈值设定不合理。检测时默认--conf 0.25但野外低对比度图像上模型输出的置信度普遍偏低建议批量测试时用一个动态阈值脚本找到适合你场景的最优值。我通常的做法是拿50张已经人工标注好的图跑一遍记录每个预测框的置信度分布再选取精确率和召回率平衡的那个点。批量推理内存溢出用大分辨率图像做批量推理时如果一次把上千张图塞进一个list再推理内存会先爆。推荐写个简单的生成器逐批读取、逐批推理、逐批释放。虽然多几行代码但可以省去频繁重启的麻烦。下面是一个排查速查表可以直接收藏使用症状直接原因优先处理方案CUDA OOMbatch太大 / 分辨率太高降低batch降低imgsz训练loss降不下去标注坐标错误 / 学习率过高检查标签调低lr到0.001无检测结果conf阈值过高 / 训练过拟合调低conf检查epochs是否过多有误检但漏检少背景复杂、假阳性多调高conf补充负样本验证集mAP高实测差过拟合、数据分布单一增加数据多样性降低epochs显存够但训练慢数据增强耗时 / 缓存未开加cache检查CPU核心数再补充一个非常容易忽略的问题YOLOv5的Mosaic增强在最后10个epoch会默认关闭这是官方行为为了让模型在接近真实分布的数据上稳定收敛。如果你发现训练末期mAP有小幅波动不用紧张那是正常现象。在推理时还有个很容易被忽略的小决定权重文件是FP32还是FP16。best.pt默认是FP32推理速度够用。如果你需要部署到边缘设备或追求极速可以把weight转成TensorRT的engine格式或ONNX格式yolov5自带export.py脚本 python export.py --weights weights/best.pt --include onnx --opset 12 转ONNX后可以用onnxruntime或TensorRT做推理速度快不少。但要注意ONNX导出后如果遇到动态输入尺寸的问题多半是你之前训练时固定了imgsz导出时也指定相同尺寸即可解决。6. 项目复盘数据、代码、权重之外的收益做这个项目时我踩过最大的坑其实不在技术上。第一次训练时我拿到的数据只有200多张而且全部是晴天正午拍摄的。模型训练完验证集mAP到了0.91看着很漂亮。结果拿到阴天场景一试漏检率直接飙升到30%以上。后来补充了不同光照、不同背景的图片重新训练后才真正可用。这个教训让我意识到单类别检测项目里数据的“覆盖度”远比数量重要。200张覆盖完整的图效果胜过500张单一场景的图。你不需要一口气把数据集弄到几千张但一定要保证场景的多样性。代码层面这份项目代码最好的地方在于“改得动”。YOLOv5官方仓库本身就是模块化设计无论是改数据加载逻辑、加回调函数还是替换骨干网络都有清晰的接口。我后来在部署时把detect.py的批量推理逻辑抽出来写成了一个简单的API服务前后只花了两小时这也是基于YOLOv5生态做二次开发的优势。权重文件是整个项目的最终资产。拿到权重之后如果你想长期运营这个检测服务要养成记录训练超参数、数据版本和指标的习惯。给每个权重文件命名时带上日期和数据版本比如best_20240612_v2.pt不要直接保留last.pt否则半年后回来看你根本不知道这个权重是从哪批数据训出来的。这个习惯在团队协作时尤其重要。最后分享一个后续扩展方向在单类别检测的基础上如果业务上需要区分冬虫夏草的生长阶段如刚出土、子座成熟、开始腐烂可以在数据标注阶段增加类别标签把单类别检测升级为多类别检测任务。你不需要换模型框架把nc: 1改成nc: 3或nc: 4调整标注类别重新训练即可。前期的数据采集、环境搭建、训练流程全部可以复用这也是选择一套成熟框架来做项目最舒服的地方——它给你留了足够多的升级空间。本文还有配套的精品资源点击获取
返回列表