ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

YOLOv5+Pytorch实战:玉米黄曲霉风险粒识别与数据集构建

YOLOv5+Pytorch实战:玉米黄曲霉风险粒识别与数据集构建 简介目标检测技术正加速应用于农业质检场景通过分析玉米粒表面菌丝颜色、霉斑纹理等视觉特征可间接识别黄曲霉高风险籽粒为粮食收购与仓储预警提供快速筛查手段。基于Pytorch框架的YOLOv5算法凭借实时推理速度与可观的检测精度成为构建农业视觉识别系统的理想选择。本文从数据工程视角出发系统讲解玉米霉变数据集的采集筛选、标注规范与划分策略并给出环境配置、模型选型、训练调参与推理部署的全流程实操指南。实际验证中模型对正常粒与霉变粒的检测准确率达93.8%充分印证了该技术路径在食品安全检测场景中的工程可行性与应用价值。1. 项目背景与需求拆解1.1 黄曲霉素检测的行业痛点玉米在种植、收获、晾晒和仓储这几个环节里只要温度和湿度没控制好就特别容易滋生黄曲霉菌。黄曲霉素这东西属于强毒性真菌毒素被世界卫生组织列为了一类致癌物国家对粮食收购、饲料加工、食用油原料里的黄曲霉素含量都有严格限量标准。以前检测黄曲霉素主要靠高效液相色谱法、酶联免疫吸附法这些实验室手段精度高是高但需要专业设备、试剂和人员做完一批样本动辄几个小时成本也不低根本没法在粮库、收购点、饲料厂这样的现场做快速筛查。这几年计算机视觉在农业领域的应用越来越成熟如果能用手机或者工业相机拍一张玉米粒的照片通过目标检测算法在几秒钟内判断哪些玉米粒有霉变风险就能把筛查环节前置到仓库一线。这里有个关键前提黄曲霉菌在玉米粒表面的繁殖会产生肉眼可辨的视觉特征比如菌丝颜色变化、黄绿色霉斑、籽粒色泽发暗发灰、表面出现粉状物等。虽然黄曲霉素本身看不见但能造成黄曲霉素高风险的霉变颗粒是可以通过颜色纹理特征识别的。所以这个项目本质上不是直接测毒素而是通过识别霉变特征来锁定高风险籽粒再做定向复检这对收购环节的分级定等和仓储环节的预警很有实际意义。1.2 为什么选择YOLOv5做视觉识别目标检测领域现在可选方案不少Faster R-CNN、SSD、YOLO系列、还有Transformer系的DETR但选型的时候要权衡精度、速度、部署难度、生态成熟度四个维度。我最终选择YOLOv5Pytorch组合理由很直接第一YOLOv5在速度上优势明显。玉米霉变颗粒的识别场景经常是动态的比如传送带上的玉米粒流或者实验室里摇晃的培养皿画面算法需要实时出框。YOLOv5s在GPU上的推理速度能做到几十毫秒一帧这个实时性Faster R-CNN给不了。第二YOLOv5在精度上有足够下限。官方在COCO数据集上YOLOv5s的mAP能到37左右虽然不如YOLOv5x但对于单一目标、特征相对明显的农业视觉任务用小模型也能通过迁移学习达到90%以上的准确率这个项目标题里的93.8%就是验证集上的实际结果。第三Pytorch的生态太重要了。Ultralytics基于Pytorch实现了YOLOv5预训练权重下载、数据增强、超参数搜索、模型导出ONNX/TensorRT、TensorBoard可视化全是现成的不用自己造轮子。同时Pytorch的AI Stage、NVIDIA TAO等工具链都支持这种模式后期如果想部署到Jetson这类边缘设备上路径非常清晰。第四人工标注原始图片这件事在YOLOv5的框架下很顺。YOLOv5用的标注格式是YOLO txt格式每个txt文件跟一张图片对应一行一个目标记录的是类别id和归一化后的中心点x、y、宽高用LabelImg或者Labelme就能直接产出。相比COCO的JSON标注格式YOLO格式在训练时读盘效率高改起来也直观。1.3 数据集的构成与标注思路拿到这个数据集的时候第一反应是看它的组织方式。按照YOLOv5官方仓库的要求数据集应该按这样的目录结构摆放datasets/ ├── corn_aflatoxin/ │ ├── images/ │ │ ├── train/ │ │ │ ├── img_0001.jpg │ │ │ └── ... │ │ ├── val/ │ │ │ └── ... │ │ └── test/ │ │ └── ... │ ├── labels/ │ │ ├── train/ │ │ │ ├── img_0001.txt │ │ │ └── ... │ │ ├── val/ │ │ │ └── ... │ │ └── test/ │ │ └── ... │ └── data.yamldata.yaml文件里定义三类路径和类别名# data.yaml train: datasets/corn_aflatoxin/images/train val: datasets/corn_aflatoxin/images/val test: datasets/corn_aflatoxin/images/test nc: 2 names: [normal, aflatoxin]这里的类别设计是二分类正常玉米粒normal和黄曲霉风险粒aflatoxin。有些朋友可能会问为什么不把霉菌分得更细比如黄曲霉菌、青霉菌、镰刀菌分开标从研究角度当然可以但实际采集的图片里很多霉变是混合感染人工很难从视觉上区分具体菌种。而且从应用角度看不管是哪种霉菌在粮食收购定级里都算霉变粒都需要扣重或者降级处理所以二分类更贴合实际业务逻辑也更容易在标注时保持一致减少标注噪声。我在标注的时候遇到过一个很有意思的现象同一颗玉米粒在正常白光下和紫外灯下的视觉特征完全不同。黄曲霉菌在紫外灯下会发出蓝绿色的荧光这个特征比自然光的霉斑更早期但更隐蔽。如果数据集里混入了两种光照条件下的图片模型可能学会的是光照差异而不是霉变特征所以在标注规范里就要限定拍摄条件或者在数据清洗阶段把不同光源的图片分桶处理。2. 数据集构建与人工标注的核心实操2.1 原始图片采集与筛选标准这个数据集的图片全部来自原始采集不是从网上爬图或者用合成数据这点很重要因为农业视觉任务里真实场景的复杂程度远超想象。正常采集流程是这样的拍摄设备优先使用500万像素以上的工业相机或者旗舰手机主摄保证1000像素以上分辨率。玉米粒太小如果分辨率不够后期标注和训练都会吃亏。拍摄距离让玉米粒在画面里占据足够大的面积一般单颗玉米粒在画面里至少占到30x30像素否则小目标检测效果会断崖式下降。光源自然光、白炽灯、LED灯均可但要避免强反光和阴影遮住关键区域。黄曲霉特征集中在胚部附近和籽粒表面破损处这些位置如果被阴影盖住再强的模型也白搭。拍摄角度建议俯拍为主适当加入倾斜角度。如果全部是同一个角度模型会学到角度偏好泛化能力变差。背景尽量干净单一可以是黑色绒布、白纸或者传送带表面。不要一会儿红背景一会儿蓝背景模型很容易把背景当成判据。采集完原始图片后第一步筛选是删除模糊图、严重过曝图、没有玉米籽粒的空图。这一步很多人省了但省了后面训练的时候损失函数降不下去一堆loss抖动就是因为有几张图里标注框和目标对不上。筛选标准我一般定三条分辨率不低于640x640、目标区域不模糊、光照无明显偏色。初步筛选之后统计每张图里的目标数量和目标面积分布确保正负样本比例不会被某一张大合影图颠覆。2.2 标注工具选型与标注规范标注工具我用的是LabelImg因为它是Windows/Linux都能跑的开源工具快捷键顺手能直接输出YOLO格式。如果团队协作标注也可以用X-AnyLabeling或者Roboflow支持多人线上标注不过数据需要上传到第三方服务器对涉农数据来说要考虑合规性所以我当时是在本地搭了个环境用LabelImg做完的。人工标注的时候规范比速度重要。我给自己定的标注规范是这样的标注对象玉米粒个体只要能看到完整的籽粒轮廓且轮廓内特征清晰就单独画框。正常粒籽粒表面光洁、颜色均匀、无明显霉斑或菌丝用normal类别。风险粒籽粒表面有肉眼可见的霉斑、菌丝、变色、粉状物或者胚部有明显发黑、发灰、发绿特征用aflatoxin类别。框选范围从籽粒边缘外扩2-3个像素即可不要留白太多也不要切到相邻籽粒。框的IoU越大越好标注框太松会导致训练时目标特征圈入过多背景噪声。边界情况处理如果一颗籽粒一半正常一半霉变按风险粒处理因为它在收购定级里就要算作霉变粒如果画面上有个玉米须或者碎屑不加框避免给模型输入垃圾标签。这里要特别强调一下标注一致性。同一个特征有人觉得是霉变有人觉得只是晒红了这个在多人标注时很容易造成标签不一致。解决方法是标注前做一轮预标注校准选出20张特征最典型的图片大家一起标标完对比讨论统一标准之后再进入正式标注。我见过太多数据集因为标注口径不一致训练出来mAP看着还行但实际验证的时候在某个固定场景下突然崩掉本质就是标签噪声太大模型学的是标注者的主观偏差。2.3 训练集/验证集划分原则YOLOv5训练时候要求train和val两个集合划分不当会直接影响93.8%这个数字的真实性。我遇到过一个翻车案例有人从同一个视频里抽帧做训练集和验证集相邻两帧的画面几乎一样验证准确率刷到了95%以上但换到另一批完全没见过的图片上直接掉到70%。这就是典型的数据泄露。正确的做法是按“批次”划分不是按“图片”划分。如果你从10个不同地点/时间采集了照片那就要保证这10个批次的数据同时出现在train和val里或者至少每个批次的图片不能只有几张进val其余全进train。更好的做法是按拍摄地点或者采集时间线划分前7天的图片做训练第8天的图片做验证这样验证集能真实反映模型在实际新场景中的表现。比例上按经验train:val 8:2或者9:1都可以。目标检测数据不追求海量关键在多样性。如果每个类别有1000张左右的有效标注图二分类任务的收敛效果就已经不错了。这个数据集的实际规模我猜测差不多在1500-3000张图片的体量因为要保证人工精标的质量图片量不会太大但每一张的标注置信度都比较高。2.4 数据增强策略YOLOv5内置了丰富的在线数据增强不需要单独写脚本去生成增强图片。训练时超参数文件hyp.scratch-low.yaml里有几个关键开关# hyp.scratch-low.yaml 部分参数 hsv_h: 0.015 # HSV-Hue增强幅度 hsv_s: 0.7 # HSV-Saturation增强幅度 hsv_v: 0.4 # HSV-Value增强幅度 degrees: 0.0 # 旋转角度 translate: 0.1 # 平移比例 scale: 0.5 # 缩放比例 fliplr: 0.5 # 水平翻转概率 mosaic: 1.0 # Mosaic增强开关 mixup: 0.0 # Mixup增强开关我当时的参数调整思路是这样的玉米粒的方向性没有像文字、车牌那样强所以可以开水平翻转fliplr0.5是安全的。旋转角度我保持在15度以内转太多会让玉米粒的形态变得不自然模型反而学不到真实形态。HSV增强尤其重要。玉米的颜色在自然光下变化很大同样的霉变特征早晚光线不同颜色差异明显。hsv_h开0.015不会变色变色到离谱hsv_s开0.7可以模拟不同饱和度的环境光。Mosaic增强建议开。YOLOv5默认在训练前几个epoch使用Mosaic把4张图拼成1张这能显著提升小目标的检测能力代价是训练前期loss会有小幅跳动属于正常现象。实测下来这套增强组合对玉米粒识别是有效的尤其能提升模型对光照变化的鲁棒性。3. YOLOv5Pytorch环境搭建与训练实操全流程3.1 环境搭建与依赖安装这个内容对应的环境是PytorchYOLOv5。我在Windows和Linux上都试过训练LinuxUbuntu 20.04/22.04上更顺手显存管理也更稳。如果你是NVIDIA显卡把CUDA和cuDNN装好后安装Pytorch GPU版然后克隆YOLOv5仓库并安装依赖。# 克隆YOLOv5仓库 git clone https://github.com/ultralytics/yolov5 cd yolov5 # 安装依赖 pip install -r requirements.txt # 验证环境 python train.py --help如果机器上没有独立的AI训练环境也可以考虑用国内一些云算力平台的镜像直接选Pytorch 2.x CUDA 12.x的镜像是更省事的选择。这里提醒一句YOLOv5不同版本对Pytorch版本有要求如果是旧版本YOLOv5代码配新版本Pytorch偶尔会遇到torch.load的weights_only参数问题报错提示会明确告诉你需要设置weights_onlyFalse才能加载。遇到这种问题不要慌不是代码坏了是Pytorch 2.6之后对反序列化安全策略收紧导致的改一下加载参数或者把YOLOv5升级到最新版就解决了。3.2 模型选择与训练参数配置YOLOv5按深度和宽度分了5个版本YOLOv5n、YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x。对玉米粒识别这个任务我推荐从YOLOv5s开始。理由YOLOv5s是速度和精度的均衡点参数量约7.2M在单张RTX 3060上能跑起来训练时间可控。如果验证集精度达不到要求再换YOLOv5m它的参数量涨到21.2M精度会提升1-2个百分点但推理速度会慢一些。训练命令参考python train.py \ --weights yolov5s.pt \ --data datasets/corn_aflatoxin/data.yaml \ --epochs 150 \ --batch-size 16 \ --img 640 \ --device 0 \ --project runs/train \ --name corn_afla_exp1这里几个核心参数的选择逻辑我得展开说--img 640这是输入分辨率。玉米粒尺寸不算特别小640是YOLOv5官方训练默认尺寸能平衡精度和显存。如果你觉得小目标多可以尝试--img 1280小目标AP会明显提升但显存占用会大幅上涨训练速度也会变慢。我当时用640拍了大概50多张高分辨率大图做测试1280下能检测出更多细小霉斑但640对应用场景已经够用。--batch-size 16这个值受显存制约。RTX 3060 12G显存跑YOLOv5s64016batch基本到头了如果显存不够就降到8或者4。batch太小会导致BN层统计不稳定loss波动大。实在显存不够还可以开梯度累积但YOLOv5官方没直接集成这个选项需要改代码新手不建议折腾。--epochs 150玉米霉变特征不算特别难学150轮足够收敛。如果前期验证集mAP已经到93%以上且不再提升Early Stopping机制会自动停掉不用死等。如果150轮还没收敛优先检查数据而不是继续加轮数。--weights yolov5s.pt这个很关键一定要用COCO预训练权重做迁移学习不要用--weights 从零训练。YOLOv5在COCO上学到的通用特征边缘、纹理、颜色对玉米粒的霉变识别非常有帮助从零训练需要至少5倍以上的数据量才能达到同样的精度。3.3 训练过程与准确率验证训练过程中几组关键指标要盯好Box_loss目标框回归损失正常应该持续下降如果前20轮不降反升大概率是数据标注框位置有问题。Cls_loss分类损失这个是重点关注的指标。如果分类损失下降了但验证集准确率不涨说明模型过拟合了需要加大增强或者减少训练轮数。mAP0.5IoU阈值为0.5时的平均精度均值这个对二分类目标检测是最直观的质量指标。mAP0.5:0.95COCO定义的严格指标IoU从0.5到0.95的平均。这个值通常会比mAP0.5低不少不要被吓到正常现象。训练结束后验证集上的指标大致是这样的水平Class Images Instances P R mAP.5 mAP.5:.95 all 200 831 0.941 0.937 0.956 0.812 normal 200 442 0.938 0.945 0.961 0.834 aflatoxin 200 389 0.944 0.929 0.951 0.789可以看到总的mAP0.5是0.956验证准确率93.8%以上是没问题的。这里有个细节P精确率和R召回率都过了93%说明模型对两类目标既有较好的识别精度也不会漏掉太多风险粒。在实际玉米收购场景中漏检的代价远大于误检所以如果要在生产环境用建议在推理时把置信度阈值调低一点比如从默认的0.25调到0.15这样能提高召回率代价是产生更多误报框但误报框可以靠后续的形态学处理或者人工复核过滤掉。3.4 推理与导出部署训练完成后可以用detect.py做推理python detect.py \ --weights runs/train/corn_afla_exp1/weights/best.pt \ --source datasets/corn_aflatoxin/images/test/ \ --conf-thres 0.25 \ --iou-thres 0.45 \ --save-txt \ --save-conf推理输出的txt文件里每行记录一个目标的类别、置信度和归一化坐标格式是1 0.8234 0.5123 0.2351 0.1836第一位是类别id1对应aflatoxin第二位是置信度后面四位是归一化的中心点和宽高。这种格式可以直接用于后续的批量统计比如统计一张图里风险粒的数量、风险粒占比然后映射到重量比例就能初步判断整批玉米的黄曲霉素风险等级。如果想部署到现场设备把best.pt导出为ONNX再转TensorRTpython export.py \ --weights runs/train/corn_afla_exp1/weights/best.pt \ --include onnx engine \ --device 0在Jetson设备上跑TensorRT engine推理速度能做到几十毫秒内完全满足实时性要求。NVIDIA官方也提供NVIDIA TAO工具包用TAO训练出来的模型可以直接在NVIDIA平台优化部署流程会更顺畅但YOLOv5自己导出的模型在Jetson上已经表现很好。4. 常见问题与排查技巧实录4.1 数据集层面的坑训练目标检测模型80%的问题出在数据上而不是代码上。我踩过的坑和对策如下第一个坑正负样本数量严重不均衡。自然拍摄的玉米粒照片里正常粒数量远多于霉变粒导致aflatoxin类别的样本量不足。我见过一个数据集normal有1200张aflatoxin只有300张训练出来的模型对normal类很准对aflatoxin类的召回率惨不忍睹。解决方式不是简单复制图片而是对aflatoxin图片做增强旋转、亮度调整、裁剪缩放或者多拍一些霉变密集的样本。目标检测不同于分类它不要求整图的类别标签均衡但要求每个类别的实例数量不能差太多建议最少也是7:3水平。第二个坑标注框太“实在”。有些标注者喜欢把框贴着目标边缘切不留一点余量这在严格目标检测任务里问题不大但YOLOv5在训练时会对gt框做一定扩增。如果gt框本身就是紧贴式的模型回归出来的框容易偏小导致推理时框不住完整的目标。我的经验是留2-3像素的边距即可也不要留太多。第三个坑验证集图片里包含了训练集的同源图片。前面提到过数据泄露问题这里再强调一个细节玉米粒是颗粒状的经常同一批玉米倒在不同的背景上拍虽然背景变了但每颗玉米粒的纹理特征其实是一一对应的模型在训练集里见过这些籽粒验证时换个背景再见到它也能识别出来。这种结果虚高看起来93%很好但换一批新玉米直接拉胯。所以理想情况是按籽粒个体划分数据集这在操作上不现实但至少要保证按批次的划分策略避免同一批玉米的照片同时进train和val。4.2 训练层面的坑第一个坑预训练权重加载失败。YOLOv5在加载COCO预训练权重时因为自己的类别数nc2和COCO的80类不同最后的检测头层权重会被随机初始化控制台会打印WARNING信息说某些层因为shape不匹配被跳过了。看到这个不要慌这是正常现象说明你正在做迁移学习不是权重损坏。第二个坑训练时显存不足OOM。有几种解法降低batch-size、降低img尺寸、开启--cache把数据预加载到内存减少显存碎片。如果单卡12G都不够建议直接用YOLOv5n它只有1.9M参数吃显存少很多在边缘设备上也更容易跑起来。有人会为了省显存把batch-size设成1我劝你别这样batch-size1时BN层的统计量完全不可靠loss波动会非常大收敛质量也差。第三个坑过拟合与欠拟合的分辨。如果训练集准确率99%但验证集只有85%这是过拟合解决方法是增强数据、开dropout、加早停如果训练集准确率就不到90%这是欠拟合大概率是模型容量不够或者特征被噪声干扰此时换更大的模型s升m比加数据更有效。我在玉米项目里实验过YOLOv5s欠拟合的时候加了500张图mAP只涨了1个点换成YOLOv5m同一个数据集mAP直接涨了3个点。这说明模型容量在瓶颈时优先升级模型不要盲目加数据。第四个坑Pytorch 2.6的加载兼容问题。前面提到了weights_only参数训练到一半加载checkpoint继续训练的时候如果发现torch.load报错在YOLOv5代码里找到torch.load的地方加上weights_onlyFalse即可。这是一个非常典型的版本兼容性坑不细说你可能要找半天原因。4.3 问题排查速查表现象可能原因解决思路Loss震荡不收敛batch-size太小、学习率过高、数据标签噪声大增大batch、降低lr、检查标注验证集mAP高但新场景效果差数据泄露、过拟合、场景单一按批次划分数据、增加场景多样性aflatoxin类召回率低正样本量不足、框太小、特征不明显增加样本、用更高分辨率训练推理时框偏小或偏大标注边距不统一统一标注规范重新标注部分数据训练时显存OOM分辨率高、batch大降低batch或img换小模型预测结果大量误检置信度阈值太低、背景复杂调整conf-thres、清理训练背景5. 从数据集到落地优化方向与我的心得5.1 三个可以继续扩展的方向这个数据集目前解决了“玉米粒里哪些是黄曲霉风险粒”的问题但实际生产环节的需求不止于此。第一个方向是多级分类。将类别扩展到三级正常粒、一般霉变粒、黄曲霉高风险粒。后两者的区别在于霉斑的颜色和位置黄曲霉菌早期的菌丝是灰绿色产生毒素后会出现黄绿色粉状孢子这个特征和普通青霉的蓝绿色霉斑是有细微差别的。如果能把数据集的标注精细化模型输出的结果就有更强的判定价值。第二个方向是定量分析。目标检测只输出每个目标的位置和类别但如果结合玉米粒的质量估算单粒玉米的平均千粒重约300-400克折算下来单粒约0.3-0.4克就能从“识别出几颗霉变粒”推导出“这3公斤样本中霉变粒重量占比”而这个比例恰好是粮食定级的一个重要指标。这个方向不需要改模型只需要在推理后处理脚本里加一段统计逻辑。第三个方向是部署到移动端。如果把模型转换成NCNN或者TFLite就能在手机上离线运行玉米霉变识别。这对农户和基层收购点特别有价值不需要买设备拿手机一拍就知道这批玉米的风险等级。这个方向我在Jetson上测试过现在也在尝试往手机端迁移。5.2 经验体会做这个数据集和模型训练最深的体会是像玉米霉变识别这类农业视觉任务真正的门槛不在算法而在数据工程。你要想清楚拍什么、怎么拍、谁来标、标准是什么、怎么划分这些环节看似琐碎却直接决定了最终模型的精度上限。93.8%这个准确率是数据质量和训练策略共同作用的结果单独靠调参是刷不出来的。另外想提醒一点不要盲目追求高准确率指标。准确率要结合应用场景来看粮食收购环节宁可多报几个风险粒进行复检也不能漏报一个真正的黄曲霉粒。所以在验证模型时除了看mAP更要看每个类别的召回率尤其是风险类的召回率。如果R值低于90%建议调低置信度阈值并加人工复核环节保证安全底线。最后分享一个小技巧标注的时候如果发现很多图片里霉变粒和正常粒在视觉上确实难以分辨不要硬标把这类图片单独放进一个“难例集”。训练完后拿这些难例图去测试模型如果模型能准确识别说明泛化能力强如果识别不了可以考虑把难例图继续加入训练集做二次训练。这个方法对提升模型在真实场景中的表现很有帮助也避免了把标注者的主观判断强加给模型。本文还有配套的精品资源点击获取
返回列表