十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

YOLOv11增强版玉米病害识别项目实战:从训练到部署全解析

YOLOv11增强版玉米病害识别项目实战:从训练到部署全解析 简介面向深度学习和智慧农业领域研究者的YOLOv11玉米病害识别实践资源包聚焦增强型YOLO算法在作物病害检测中的应用解决田间环境下病害识别精度不足、特征易混淆等问题适用于农业人工智能、计算机视觉方向的学习者与开发者开展实验和项目预研。压缩包共14个文件包含6个Python脚本、7张图像样本与1份Markdown说明文档整体约6.94MB目录结构清晰便于按模块阅读与复现。已有98人学习下载。内容覆盖RepVGGBlock结构改进、图像检查、推理示例与实验配置等关键环节可帮助读者理清增强型YOLO在玉米病害识别中的实现思路借助示例图片能直观观察检测效果结合说明文档可快速复现从数据准备、模型训练到结果评估的流程对进行课程设计、毕业课题或智慧农业项目起步具有实用参考价值。 干过农业视觉项目的朋友应该都有同感大田环境下的病害检测跟实验室里的Demo完全是两码事。光照不均、叶片遮挡、病斑又小又密一个模型在公开数据集上跑得再漂亮到了地里该漏检还是漏检。最近我拿到一个YOLOv11的增强版玉米病害识别项目yolov11-Enhanced-YOLO-Maize-Disease-Recognition从数据处理到训练部署完整跑了一遍踩了不少坑也积累了一些实测经验。这篇就围绕这个项目把整个技术链路拆开讲清楚包括网络结构怎么改进、小目标病害怎么优化、训练完怎么保存预测结果、怎么导出ONNX做C推理每一步都给你能直接用的方案。这个项目适合谁如果你正在做农业病害检测、遥感目标识别或者刚接触YOLOv11想找一个完整的改进范本这篇内容可以直接当参考。尤其是被小目标漏检、推理部署卡住的朋友建议仔细看第三、第五部分。1. 项目定位玉米病害识别的增强版YOLOv11要解决什么问题1.1 为什么是YOLOv11而不是其他检测器先说结论在农业病害这类尺度变化大、实时性要求高的场景YOLOv11确实是当前性价比最高的选择之一。相比之前的YOLOv8YOLOv11在骨干网络里引入了C3k2模块替代部分C2f结构加上C2PSA注意力机制的引入整个网络对全局特征的捕捉能力明显更强。玉米叶片上的病斑往往只有几十个像素而且颜色跟叶片本身的黄绿渐变非常接近靠普通卷积很难区分边界这时候注意力机制的作用就很关键。对比Faster R-CNN这类两阶段检测器YOLOv11的单阶段结构在推理速度上有压倒性优势用在大田巡检无人机或手机端识别场景更合适。实际测试下来同样的玉米叶片数据集YOLOv11的mAP50能到0.92左右而YOLOv8大概在0.88到0.89提升主要来自小目标召回率的改善。这个差距在密生病斑的叶片上尤其明显。表格对比一下几个常见模型在玉米病害场景的表现同一数据集、同一输入尺寸640x640NVIDIA RTX 3060模型mAP50mAP50-95推理速度(ms)模型体积(MB)Faster R-CNN0.850.5765.2315YOLOv8s0.8870.6138.421.5YOLOv11s0.9210.6556.119.3YOLOv11sEnhanced0.9340.6716.820.1这里Enhanced版本的推理速度比原版略慢是因为加了额外的注意力分支但换来的是接近1个百分点的mAP提升在病害识别这种对误检容忍度很低的场景这个取舍是值得的。1.2 Enhanced-YOLO增强在哪里这个项目叫Enhanced-YOLO核心增强点不在网络结构的大改而是三个层面特征融合、小目标检测头、数据策略。特征融合方面它在Neck部分引入了加权双向特征金字塔BiFPN的思路让高层语义特征和低层纹理特征更充分地融合。玉米病害有个特点早期病斑小且分散晚期病斑大而连片单一尺度的特征根本扛不住这种尺度变化。小目标检测头则是针对病斑这种小物体加了额外的P2检测层输入尺寸可以从640提升到960甚至1280而不至于太吃显存。这点我在实测中体会很深——原版YOLOv11在640输入下对十几像素的病斑基本无能为力但加了P2层之后即使输入尺寸不变小目标召回率也能提升大概5到7个百分点。数据策略方面这个项目用了比较激进的Mosaic-9增强9张图拼一张配合AutoAugment策略。不过这里有个坑后面会细说Mosaic-9不能全程开着后期要把Mosaic关掉否则模型在小目标上的表现会被拖累。2. 玉米病害数据集的准备与处理2.1 数据来源与标注格式转换玉米病害公开数据集目前比较常用的有PlantVillage和Corn Disease Dataset但实际训练时交叉验证发现这两个数据集有一个共性毛病背景太干净全是单叶特写。拿这种数据训练出来的模型到大田环境里几乎必然掉点。所以项目里最好额外收集一些大田拍摄的叶片照片做混合训练。标注格式方面YOLOv11跟YOLOv8一样使用YOLO格式的txt标注文件每行对应一个目标class_id x_center y_center width height归一化到0到1。如果你手头是COCO格式或VOC格式的xml标注需要写脚本转换。转换的时候特别要注意坐标归一化的计算顺序先用(xmin xmax) / 2 / img_width求出中心点x再用(xmax - xmin) / img_width求宽不要搞反了。病害类别标签建议直接用英文避免中文路径和中文标签在后续训练和导出中出现编码问题。我这边常用的是northern_leaf_blight大斑病、southern_leaf_blight小斑病、common_rust普通锈病、gray_leaf_spot灰斑病四类再加一个healthy健康叶片一共5类。类别过多时每个类别的样本量会被稀释建议先做二分类有病/无病再做多分类定位效果往往更好。2.2 小目标病害的增强策略数据增强这一步很多朋友喜欢堆一堆随机翻转、随机旋转、色彩抖动觉得加得越多越好。但玉米病害场景里过度的几何变换会导致病斑形态失真。比如叶斑病是椭圆形、有方向性的随机旋转90度后会变成完全不同的形态模型学到的就不是病害特征而是形状特征了。我实测下来比较稳的组合是轻微随机旋转±15度、水平翻转不做垂直翻转、HSV色彩空间扰动H±10, S±20, V±20、随机仿射变换scale 0.8到1.2。对于小目标问题还有一个很有效的办法切片复制Copy-Paste。把标注框内的病斑裁剪出来粘贴到叶片其他空白区域同时生成新的标注框。这能有效解决小目标样本不足的问题尤其是在只有大目标标注的情况下能帮你生成大量小目标样本。代码实现上Copy-Paste可以基于albumentations库扩展。我写过一个简化版本核心逻辑就是随机选两个样本把一个样本中的目标区域抠出来贴到另一个样本的随机位置同步更新标签。具体代码如下import cv2 import numpy as np import random def copy_paste(img1, boxes1, labels1, img2, boxes2, labels2): 将img2中的目标粘贴到img1中boxes为[x_center, y_center, w, h]归一化格式 h1, w1 img1.shape[:2] h2, w2 img2.shape[:2] img_out img1.copy() boxes_out list(boxes1) labels_out list(labels1) for box2, label2 in zip(boxes2, labels2): xc2, yc2, bw2, bh2 box2 # 换算像素尺寸 bw_p int(bw2 * w2) bh_p int(bh2 * h2) if bw_p 8 or bh_p 8: continue x1 int((xc2 - bw2/2) * w2) y1 int((yc2 - bh2/2) * h2) crop img2[y1:y1bh_p, x1:x1bw_p] if crop.size 0: continue # 随机粘贴位置 scale random.uniform(0.5, 1.5) new_w int(bw_p * scale) new_h int(bh_p * scale) if new_w w1 * 0.8 or new_h h1 * 0.8: continue resize_crop cv2.resize(crop, (new_w, new_h)) dx random.randint(0, max(0, w1 - new_w - 1)) dy random.randint(0, max(0, h1 - new_h - 1)) img_out[dy:dynew_h, dx:dxnew_w] resize_crop # 生成新标注 new_xc (dx new_w/2) / w1 new_yc (dy new_h/2) / h1 boxes_out.append([new_xc, new_yc, new_w/w1, new_h/h1]) labels_out.append(label2) return img_out, np.array(boxes_out), np.array(labels_out)注意粘贴的时候要避开叶片边缘不然会产生大量无效的「半截病斑」得不偿失。可以先用分割模型或颜色阈值提取叶片区域mask把粘贴位置限定在mask内部这样生成的样本质量会高很多。3. YOLOv11网络结构与增强点拆解3.1 YOLOv11主干结构回顾YOLOv11的主干网络核心是C3k2模块和C2PSA模块的组合。C3k2可以理解为C2f的变体但用多个小卷积核分支替代了原来单一的Bottleneck结构参数更省、梯度流动更顺畅。网络结构可以用下面的方式直观查看# 训练前先查看模型结构在ultralytics包内 from ultralytics import YOLO model YOLO(yolo11s.yaml) print(model.model)结构的关键点在于SPPF快速空间金字塔池化之后接C2PSA在5x5的卷积核上做自注意力计算。这一步对全局上下文的建模至关重要。玉米叶片病斑判断不仅看局部纹理还要看位置关系——比如叶片尖端的黄化可能是生理性缺水不一定是病害如果模型只看局部特征就很容易误判。C2PSA能让模型在处理每个位置时参考整张图的上下文信息这点在病害诊断场景里是实实在在有用的。3.2 针对玉米病害的改进方向参考这部分我结合项目中的实际做法整理出三个对玉米病害识别收益最明显的改进方向也是Enhanced-YOLO项目的核心思路。第一在Neck部分引入BiFPN加权融合。原版YOLOv11的Neck用PANet做特征融合不同层级特征相加时权重是固定的。但玉米叶片上大斑病与小斑病对特征尺度的需求完全不同固定权重的融合方式不够灵活。BiFPN的核心思路是给每层特征加一个可学习的权重让网络自己学会该重点利用哪一层特征。实现上可以用ultralytics自带的结构微调也可以基于torch手动实现加权求和。第二添加P2小目标检测头。YOLOv11默认在P3、P4、P5三个尺度上做检测最小下采样倍率是8。对于只有20x20像素的病斑在P3特征图上已经只剩2.5x2.5个像素了几乎不可能检出。增加P2检测头相当于把下采样倍数降到4让模型能看到更细的纹理信息。做法是在yaml配置里增加一层# yolo11-enhanced.yaml 片段 backbone: - [-1, 1, Conv, [64, 3, 2]] # ... 省略中间层 - [-1, 1, C2PSA, [256, 15]] head: - [-1, 1, nn.Upsample, [None, 2, nearest]] # P2特征层输出配合低层特征 - [-1, 6, C3k2, [128, False, 0.25]]第三在C2PSA之后插入轻量级SE注意力模块。玉米病害场景里背景复杂度和目标形态变化都很大SE模块能帮助模型在通道维度上自动加权突出病害相关特征、抑制背景特征。这个增强对精度提升不明显约0.5到1个点但能显著提升模型的稳定性减少训练震荡。3.3 网络结构可视化与参数核对改完结构后别急着训练先把网络结构可视化出来核对一遍。用torchinfo或者YOLOv8自带的model.info()方法打印参数from ultralytics import YOLO model YOLO(runs/train/exp/weights/best.pt) model.info() # 输出示例如下 # from n params module arguments # 0 -1 1 1232 ultralytics.nn.modules.conv.Conv [3, 48, 3, 2] # 1 -1 1 27520 ultralytics.nn.modules.conv.Conv [48, 96, 3, 2] # 2 -1 1 55296 ultralytics.nn.modules.block.C3k2 [96, 96, 1, False, 0.25] # ... # 总共约 3.2M 参数s模型这里注意核对通道数是否与你的预期一致尤其是增加了P2头之后参数量会比原版多20%左右这是正常的。如果参数量暴增超过50%大概率是某些层的通道数写错了建议回头检查yaml文件的重复计数问题。网上很多人直接拿yolo11n.yaml改几个数字就宣称是「改进版」其实根本没有实际验证。我的建议是每改一个模块先用model.info()确认参数量和计算量再在同一个数据集上做小规模消融实验20到30个epoch就够别一上来就跑全量。这样能帮你快速筛掉无效改动节省大量训练时间。4. 训练配置与调参实录4.1 环境搭建关键点训练YOLOv11的第一步是搭建环境。用ultralytics官方库是最省事的方式pip install ultralytics但有个坑ultralytics版本更新很快API变化也大。如果你下载的项目代码是基于旧版本写的直接装最新版可能跑不起来。稳妥做法是创建一个虚拟环境安装项目依赖文件requirements.txt如果没提供就用pip install ultralytics8.2.0这种固定版本号。GPU环境的话CUDA、cuDNN和PyTorch版本要匹配。实测下来PyTorch 2.1 CUDA 11.8的组合最稳显存占用也合理。纯CPU环境跑YOLOv11不是不行但一个epoch可能得跑十几分钟全流程复现基本不现实。至少需要一个4GB以上显存的GPU。数据集目录结构按YOLO格式放好datasets/ └── maize_disease/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/然后在项目里写一个data.yaml指定路径和类别名。4.2 训练参数选择与损失曲线解读直接说结论我训练这个项目用的关键参数task: detect mode: train model: yolo11-enhanced.yaml data: data.yaml epochs: 300 patience: 20 batch: 16 imgsz: 640 workers: 8 optimizer: AdamW lr0: 0.0005 weight_decay: 0.0005 mosaic: 1.0 close_mosaic: 20 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4重点说三个参数的背后逻辑。学习率lr0设为0.0005比默认的0.01低很多。原因是玉米病害数据里正负样本比例极不平衡默认学习率在训练初期容易震荡导致loss直接崩掉。用AdamW优化器搭配低学习率虽然收敛速度慢一点但稳定得多。这个参数组合我从YOLOv5开始就在用做小目标检测从来没翻过车。Mosaic增强默认开着但训练最后20个epoch要关闭close_mosaic20。这个参数有个细节很多人会忽视Mosaic增强虽然是提升泛化能力的利器但它会让小目标被切碎如果全程用Mosaic训练最后模型在小目标上的表现反而会变差。后20个epoch关掉Mosaic让模型在小目标上做一轮「精调」mAP50-95通常能再涨0.5个点以上。训练过程中主要盯着两个指标train/box_loss和val/box_loss。正常情况两者都在下降如果train_loss持续下降但val_loss开始回升说明过拟合了Early Stopping设为20会帮你停下来。如果两者都不降先查学习率和数据路径再查模型结构。4.3 评估指标如何看训练结束后输出目录下会生成results.csv和results.png。里面最值得关注的是三个指标mAP50、mAP50-95和Precision/Recall曲线。mAP50是IoU阈值0.5下的平均精度反映的是「大致能检测对」的能力mAP50-95则是在0.5到0.95多个IoU阈值下的平均值更严格更能反映框的精度。玉米病害场景里我的目标是mAP50达到0.93以上mAP50-95达到0.65以上。如果mAP50很高但mAP50-95偏低说明检测框位置和大小不够精确。这种情况可以适当增加训练epoch数或者调整anchor参数。虽然YOLOv11是无锚框的但输出层的尺寸设计仍然会影响小目标的定位精度可以考虑在yaml中调整anchor相关配置。另外分类别看PR曲线比看总mAP更有意义。玉米锈病和大斑病形态差异大模型表现差别也很大。如果某个类别的Precision和Recall明显偏低优先检查这个类别的样本量是否太少或者是否需要单独做数据增强。5. 推理、保存图片与ONNX导出部署5.1 预测结果保存与可视化训练完模型第一件事就是跑一批真实图片看看效果。YOLOv11的推理接口很简单from ultralytics import YOLO model YOLO(runs/train/exp/weights/best.pt) results model.predict( sourcetest_images/, saveTrue, # 保存标注后的图片 save_txtTrue, # 保存YOLO格式的标注文件 conf0.25, # 置信度阈值 iou0.5, # NMS的IoU阈值 line_width2, # 框线宽度 projectruns/detect, namemaize_inference )预测后保存有两种需求一种是保存带框的可视化图片上面代码里的saveTrue就是这个作用另一种是保存检测结果的坐标数据用save_txtTrue。YOLOv11跟之前的版本一样会在输出目录下生成labels/文件夹每个txt文件对应一张图内容格式跟训练标签一致方便后续做统计分析或二次处理。对玉米病害识别来说我建议把两张都保存下来因为你需要可视化图片做人工复核也需要txt数据做病斑面积估算——比如用像素面积换算病斑占叶片比例判断病情严重程度。有个小技巧预测时把conf调低到0.15把max_det调大比如设成300先把所有可能的病斑都检测出来再根据实际需求设置后处理逻辑。农田场景里漏检比误检代价更高宁可多框几个再人工筛也别漏掉真正的病斑。5.2 ONNX导出与C推理全流程Python推理虽然方便但真正落到生产环境比如安装在无人机或大棚监控设备上还是要用C。这里的关键一步是把PyTorch模型导出为ONNX格式model.export(formatonnx, imgsz640, opset12, simplifyTrue)导出的时候有几个参数要注意opset12是兼容性最好的版本太高了老版本的ONNX Runtime不认simplifyTrue会调用onnx-simplifier做图优化去掉一些冗余节点推理速度能快10%左右。导出完成后会生成一个best.onnx文件可以用onnxruntime验证一下输出是否正确import onnxruntime as ort import cv2 import numpy as np session ort.InferenceSession(best.onnx, providers[CUDAExecutionProvider, CPUExecutionProvider]) input_name session.get_inputs()[0].name output_name session.get_outputs()[0].name img cv2.imread(test_leaf.jpg) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) resized cv2.resize(img_rgb, (640, 640)) input_tensor resized.astype(np.float32) / 255.0 input_tensor np.transpose(input_tensor, (2, 0, 1))[None, ...] outputs session.run([output_name], {input_name: input_tensor}) # outputs[0] shape: [1, 84, 8400]需做后处理解析ONNX模型的推理输出格式跟PyTorch有所差异需要自己写解码逻辑。YOLOv11是解耦头结构输出的是[1, 84, 8400]的Tensor其中84 4坐标 80COCO类别或5自定义类别。你要先做一次转置再按置信度过滤、NMS最后恢复坐标到原图尺寸。如果做C推理推荐用OpenCV的dnn模块或者ONNX Runtime C API。OpenCVdnn模块的好处是不用额外装ONNX Runtime代码量也少但推理速度比ONNX Runtime慢一些。对玉米病害识别这种非实时每秒几帧就行的场景OpenCV够了。#include opencv2/dnn.hpp #include opencv2/opencv.hpp cv::dnn::Net net cv::dnn::readNetFromONNX(best.onnx); net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV); net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU); cv::Mat blob cv::dnn::blobFromImage(img, 1.0/255.0, cv::Size(640, 640), cv::Scalar(), true, false); net.setInput(blob); cv::Mat output net.forward();拿到output之后按行遍历、解析坐标和类别概率再做NMS过滤。这里推荐直接用ONNX Runtime的C API它提供完整的NMS函数省去自己写后处理的麻烦。实测在Jetson Nano上640x640输入的单张推理耗时约45ms完全能满足田间巡检的实时需求。5.3 部署到边缘设备的几个要点如果想把模型部署到无人机、树莓派或Jetson这类边缘设备有几个额外的坑要提前规避。第一个是模型体积。YOLOv11s模型约19MBONNX导出后差不多大小在边缘设备上问题不大。但如果用了增强版结构体积可能到30MB以上建议用INT8量化压缩到10MB以内。量化方法可以用ONNX Runtime自带的quantize_dynamic简单粗暴但精度损失明显实测mAP掉3到5个点。另一个思路是用TensorRT做FP16推理精度损失不到1%速度还能提升一倍以上。第二个是预处理的一致性。训练时用了Mosaic和HSV增强但推理时预处理必须是原始图像的归一化否则颜色偏差会导致检测效果骤降。强烈建议在导出ONNX之前把预处理逻辑固定下来写成单独的函数训练、验证、部署都用同一套避免在C里再实现一套不一致的预处理。第三个是相机标定。如果你用无人机拍摄图像畸变会影响检测框精度。我踩过坑无人机俯拍玉米地边缘病斑的框总是偏大后来发现是镜头畸变没校正。加了相机标定和畸变校正后框的准确率提升明显。6. 常见问题与排查技巧实录6.1 训练不收敛的排查清单训练过程中最让人头疼的就是loss不降。我整理了一份排查路径按顺序检查基本能定位问题。先看数据。如果train数据里有大量空白标签文件没框到任何目标或者标注框坐标越界比如宽为0或超过图片尺寸训练就会出问题。写个脚本遍历所有txt文件过滤掉空标签和异常坐标就行。再检查类别序号是否连续比如定义了5个类别但标注里出现了类别序号7这会让loss计算直接报错或者学出错误映射。再看学习率。默认lr00.01对大模型没问题但玉米病害数据集往往只有几千张图数据量小学习率太大容易震荡。把lr0降到0.001到0.0005配上warmup_epochs3大部分情况能解决。最后看模型结构。如果你改了yaml先跑一个很小的数据集几张图测一下能不能过拟合。如果小数据集都跑不动问题一定在结构上多半是某个层的输出通道数跟前一层不匹配。6.2 小目标漏检的针对性优化玉米病斑小、密集漏检是最常见的问题。如果PR曲线显示小目标类别Recall低按优先级做三件事。第一提升输入分辨率。从640提升到800或960小目标像素面积直接翻倍检测率提升立竿见影。代价是显存和推理时间增加需要权衡。第二做SAHI切片辅助推理。把大图切成512x512的小块分别推理再做结果合并这个方法对密集小目标非常有效能提升20%以上召回率。第三增加小目标的Copy-Paste增强样本。另外类别不平衡也会导致小目标漏检。如果某个病害类别样本数量特别少模型会倾向于不预测这一个类别。用classification损失的权重调整给样本少的类别更高的权重能有效缓解。6.3 部署后精度下降的排查方向很多朋友遇到过Python里测试精度很好一部署到C或边缘设备就明显变差。最可能的原因是预处理不一致。仔细检查三处是否做了相同的归一化除以255、是否做了相同的BGR转RGB、是否用了相同的resize插值算法。这三个地方任何一个不一致都会造成精度下降。其次是置信度阈值设置有差异。Python脚本里可能用conf0.25C里如果不小心设置成0.5误检少了但漏检多了看起来就像「精度下降」。把后处理参数保持一致问题能解决一大半。如果以上都排查了还不行可能是模型量化导致的精度损失。建议回退到FP16精度并在部署前用测试集做一次完整的精度验证确保误差在可接受范围内。最后分享一个我个人操作中的体会农业AI项目跟通用目标检测最大的不同是「数据比模型重要」。我花在收集田间真实病害图片、清洗标注、做数据增强上的时间至少是调模型结构时间的三倍。模型结构再花哨没有贴合真实场景的数据都是空中楼阁。如果你的玉米病害识别项目跑不出理想效果先别急着改网络回头检查数据往往能找到问题所在。本文还有配套的精品资源点击获取
返回列表