拓冰建站拓冰建站
首页 / 资讯中心 / 正文

YOLOv11草莓成熟度检测实战:从数据集构建到边缘部署的完整方案

草莓成熟度检测这件事看起来是个很窄的农业视觉任务但真正做过的人都知道它比通用目标检测要麻烦得多。通用检测里“车就是车、人就是人”类别边界清晰而草莓的成熟度是一个连续渐变过程青果、白果、转色果、半红果、全红果之间的视觉差异有时候连人眼都要犹豫一下。再加上大棚里叶片遮挡、反光、果柄朝向不一致、光照忽明忽暗一个模型想稳定区分五六个成熟阶段难度并不低。我这次用 YOLOv11 从头搭了一套草莓成熟度检测系统包含数据集构建、标注策略、训练调参、推理部署和结果保存的完整链路中间踩了不少坑也总结出一些和常规教程不太一样的做法。这篇文章会把整个流程拆开讲清楚适合已经跑通过 YOLO 基础训练、想把它落到具体农业场景的读者也适合正在做毕业设计或课程项目、需要一套可复现方案的朋友。1. 为什么草莓成熟度检测不能直接套用通用检测思路1.1 成熟度是连续量但检测输出是离散类别这是整个项目最核心的矛盾。草莓从坐果到全红颜色变化是渐进的但 YOLO 的输出必然是离散的类别标签。你不可能让模型输出“成熟度 0.73”这种连续值除非改成回归任务但回归在遮挡场景下极不稳定。所以第一步要做的是把连续过程切成几个有农艺意义的档位。我最终采用的是五级分类青果、白果、转色、半红、全红。这个划分不是拍脑袋定的而是参考了采摘标准——青果和白果基本没有商品价值转色果需要再等几天半红果可以提前采摘用于短途运输全红果是即食或深加工级别。切档位的时候有个经验档位之间必须有足够大的视觉差异否则标注一致性会崩。我试过把“半红”和“全红”合并成“红果”再细分结果标注员之间的一致率从 92% 掉到 78%模型学出来的边界也很模糊。提示如果你的应用场景只关心“能不能摘”其实三级分类未熟、将熟、成熟就够了类别越少模型越稳标注成本也越低。不要为了显得“精细”而硬凑类别。1.2 遮挡和反光是这个场景的两大天敌大棚草莓是贴地生长的叶片、果柄、相邻果实之间的遮挡非常严重。我统计过一批实拍图单张图里完全无遮挡的草莓占比不到 35%。更麻烦的是反光——大棚膜透下来的散射光打在草莓表面会形成高光斑红色通道直接饱和模型很容易把高光区域误判成“白果”或“转色”。针对这个问题我在数据采集阶段就做了控制尽量在上午 9 点到 11 点、下午 3 点到 5 点拍摄避开正午强光同时用偏振镜减少表面反光。后期还做了一轮高光抑制的预处理把过曝区域用邻域颜色做了一次简单修复。这一步看起来是“数据清洗”但对最终 mAP 的提升比换模型结构还明显实测提升了约 4 个百分点。1.3 小目标占比高锚框和输入尺寸都要重新考虑草莓在整株图像里往往只占很小一块尤其是远景拍摄时。我最初用 640×640 输入发现小果实的召回率很低。后来把输入尺寸提到 960×960同时调整了 YOLOv11 的检测头感受野配置小目标召回率明显改善。但代价是显存占用和推理时间上升需要在精度和速度之间做权衡。这里有个实操细节YOLOv11 默认的 anchor 是基于 COCO 聚类的对草莓这种“扁圆形、尺寸集中”的目标并不最优。我用训练集重新跑了一次 K-means 聚类把 anchor 数量设为 5得到的平均 IoU 比默认值高了 6% 左右。这个改动很小但收益很直接。2. 草莓成熟度数据集的构建与标注策略2.1 数据采集数量不是关键分布才是很多人一上来就想着“我要拍一万张”。我实际做下来3000 到 5000 张高质量图像配合合理的数据增强已经能训出很稳的模型。关键不在于数量而在于分布要覆盖真实场景的各种变化。我按以下几个维度做了分层采集维度覆盖范围目的光照顺光、逆光、阴天散射光、补光灯避免模型对单一光照过拟合角度俯拍、侧拍、低角度覆盖不同果柄朝向密度单果、双果、簇生测试遮挡下的分离能力成熟阶段五级各占比均衡防止类别不平衡背景地膜、稻草、裸土减少背景干扰特别要提醒的是成熟阶段一定要均衡。自然状态下全红果最多青果最少如果直接按自然分布采集模型会严重偏向“全红”类。我的做法是每个类别至少保证 600 个实例不足的通过定向补拍补齐。2.2 标注规范边界框画到哪里直接决定模型学什么标注这件事最怕的是标准不统一。我制定了一套明确的规则边界框紧贴果实可见轮廓不包含果柄和萼片被遮挡超过 60% 的果实直接标为“忽略区域”不参与损失计算相邻果实如果边界重叠以可见分界线为准宁可留一点缝隙也不要重叠转色果如果红绿各半按“转色”类标注不要拆成两个框。这套规则我写成了一页纸的标注手册所有标注员先标 50 张做一致性校验一致率低于 90% 就重新培训。实测下来标注一致性对最终模型性能的影响比换优化器大得多。2.3 数据增强哪些能用哪些会帮倒忙YOLOv11 自带的增强里Mosaic 和 MixUp 对小目标检测帮助很大但在这个场景里要小心。Mosaic 会把四张图拼在一起如果拼接后草莓的成熟度语义被破坏比如半红果被拼到全红果旁边模型会学到错误的颜色上下文。我的做法是Mosaic 概率设为 0.5MixUp 设为 0.1并且关闭了 HSV 的色相抖动。色相抖动为什么关掉因为成熟度的核心判别特征就是颜色色相一抖青果可能变成偏黄全红可能变成偏紫直接破坏标签语义。饱和度抖动可以保留但幅度要小控制在 ±10% 以内。亮度抖动可以大一点用来模拟不同光照。另外我加了一个自定义增强随机遮挡块。在果实区域随机贴几个小矩形模拟叶片遮挡。这个增强让模型在遮挡场景下的召回率提升了约 5%。3. YOLOv11 模型配置与训练调参实战3.1 模型选型n/s/m 怎么选YOLOv11 提供了 n、s、m、l、x 五个尺度。草莓检测这个任务我实测下来 s 和 m 是甜点区。n 太快但精度不够小目标召回明显偏低l 和 x 精度有提升但推理速度掉得厉害部署到边缘设备上不现实。最终我选了 YOLOv11m 作为主模型输入 960×960在单张 RTX 3060 上训练batch size 设为 8大约 120 个 epoch 收敛。如果算力有限YOLOv11s 配合 800×800 输入也能到可用的精度mAP50 大概差 2 到 3 个点。3.2 关键超参数学习率和损失权重YOLOv11 默认的学习率是 0.01但那是针对 COCO 这种大数据集的。草莓数据集规模小我用了余弦退火初始学习率降到 0.005warmup 设为 3 个 epoch。这样训练更稳不会在前期震荡。损失权重方面box 损失和 cls 损失默认是 7.5 和 0.5。因为成熟度分类是核心我把 cls 权重提到 1.0让模型更关注分类边界。同时因为小目标多我把 box 损失里的 CIoU 换成了 SIoU收敛更快定位也更准。# 训练配置片段data.yaml 和超参 # data.yaml path: ./strawberry_dataset train: images/train val: images/val nc: 5 names: [green, white, turning, half_red, full_red] # 训练命令 # yolo train modelyolo11m.pt datadata.yaml epochs120 imgsz960 batch8 lr00.005 cos_lrTrue warmup_epochs3 cls1.03.3 训练过程中的坑过拟合和类别坍缩小数据集训练最容易遇到两个问题。第一个是过拟合训练 loss 一直降验证 mAP 到 60 epoch 后开始掉。我的对策是加强正则dropout 设 0.1weight_decay 提到 0.0005同时早停 patience 设为 20。第二个是类别坍缩模型把所有偏红的都预测成“全红”把偏绿都预测成“青果”中间的“转色”和“半红”几乎学不到。这个问题根子在类别边界模糊。我的解决办法是引入标签平滑把 one-hot 标签软化让模型不要对边界样本过于自信。标签平滑系数设 0.1效果很明显中间类别的召回率提升了 8% 左右。注意标签平滑不是万能的如果类别本身定义就有问题平滑也救不了。先确保标注规范清晰再谈调参。4. 推理、结果保存与部署落地4.1 推理结果保存别只存画框图很多人推理完只保存一张画了框的图这在项目里是不够的。我实际需要的是结构化数据每张图里每个草莓的类别、置信度、边界框坐标。所以我用 YOLOv11 的save_txt和save_conf选项同时输出可视化图和 txt 标注文件。from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) results model.predict( source./test_images, imgsz960, conf0.35, iou0.5, saveTrue, save_txtTrue, save_confTrue )置信度阈值我设的是 0.35比默认的 0.25 高。原因是草莓场景里背景干扰多低阈值会引入大量误检。0.35 是实测下来精度和召回比较平衡的点。NMS 的 IoU 阈值设 0.5因为草莓之间重叠不多不需要太激进的抑制。4.2 边缘设备部署Jetson 上的实测表现如果要把系统落到大棚里的边缘设备上Jetson 系列是常见选择。我把 YOLOv11m 导出成 TensorRT 引擎在 Jetson Orin Nano 上实测960×960 输入下单帧推理约 45ms换算下来 20 FPS 左右足够做实时检测。导出时有个细节FP16 量化几乎不掉精度但 INT8 量化需要校准集如果校准集代表性不够中间类别转色、半红的精度会掉得比较明显。我建议先用 FP16除非你对速度有极致要求。4.3 一个容易被忽略的点结果的后处理逻辑模型输出的是一个个独立的检测框但实际业务需要的是“这株草莓现在能不能摘”。所以我在推理之后加了一层业务逻辑统计每张图里各类别的数量如果全红果占比超过阈值就输出“建议采摘”。这层逻辑很简单但它是从“检测”到“决策”的关键一步很多项目就卡在这里没有闭环。5. 实测效果与几个反直觉的发现5.1 精度数据mAP50 和各类别表现在自建测试集上YOLOv11m 的 mAP50 达到了 0.91mAP50-95 为 0.68。分类别看青果和全红的 AP 最高都在 0.95 以上转色和半红最低在 0.85 左右。这个分布符合预期因为中间类别本身边界就模糊。类别AP50召回率备注青果0.960.94颜色特征明显白果0.920.90易与高光混淆转色0.850.82边界模糊半红0.860.83边界模糊全红0.950.93颜色特征明显5.2 反直觉发现一提高输入尺寸的收益有上限我试过把输入从 960 提到 1280mAP 只涨了 0.5 个点但推理时间翻了近一倍。原因是草莓本身尺寸集中960 已经能覆盖大部分实例的像素需求再大就是浪费。所以不要盲目追求大输入先看你的目标尺寸分布。5.3 反直觉发现二数据增强不是越多越好我做过一组对照实验把增强开到最猛Mosaic 1.0、MixUp 0.5、HSV 全开结果 mAP 反而掉了 3 个点。原因是过强的增强破坏了成熟度的颜色语义。后来把增强调温和精度才回来。这个教训是增强要服务于任务语义不能为了“看起来更鲁棒”而乱加。5.4 反直觉发现三类别不平衡比想象中更致命前面提到我强制每类至少 600 个实例。如果偷懒按自然分布来全红果可能是青果的 5 倍模型会严重偏向全红中间类别几乎学不到。我试过用 focal loss 来缓解但效果不如直接补数据。所以最靠谱的办法还是从数据层面解决平衡问题。6. 从检测到系统把模型变成能用的工具6.1 系统架构轻量但完整整套系统我拆成三层采集层摄像头/手机拍照上传、推理层YOLOv11 模型服务、应用层结果展示和采摘建议。推理层用 FastAPI 包了一个 HTTP 接口接收图片返回 JSON 结果。这样前端可以是网页、小程序或者简单的桌面程序解耦得很干净。6.2 接口设计返回什么字段很关键接口返回的 JSON 我设计了这些字段图片 ID、检测框列表含类别、置信度、坐标、各类别计数、采摘建议。采摘建议是根据全红果和半红果的比例算出来的。这个设计让前端不需要懂模型直接展示结果就行。{ image_id: straw_001, detections: [ {class: full_red, conf: 0.93, bbox: [120, 80, 210, 170]}, {class: turning, conf: 0.87, bbox: [300, 150, 380, 230]} ], counts: {green: 2, white: 1, turning: 3, half_red: 4, full_red: 6}, suggestion: 建议采摘 }6.3 持续迭代线上数据回流系统上线后我会把置信度低或者人工修正过的样本回流到训练集定期重新训练。这个闭环很重要因为大棚环境会随季节变化光照和品种都可能不同模型需要持续适应。我一般每两周做一次增量训练用旧模型权重做初始化学习率调小避免灾难性遗忘。7. 给准备做类似项目的人几条实在建议第一先把标注规范定死再动手标数据。我见过太多项目因为标注标准反复改导致前面标的全废了。花半天时间写清楚规则比后面返工一周划算得多。第二不要迷信大模型。YOLOv11m 在这个任务上已经够用换成 l 或 x 收益很小但部署成本高很多。先把数据和标注做扎实模型结构是最后才考虑的事。第三颜色相关的任务慎用色相增强。这是我在这个项目里踩得最深的坑色相一抖成熟度语义就乱了。饱和度、亮度可以动色相尽量别碰。第四中间类别是难点也是价值点。青果和全红谁都能分真正体现系统价值的是转色和半红的识别。如果这两个类别做不好整个系统的实用性会大打折扣。多花时间在这两个类别的数据上值得。第五别忘了业务闭环。检测出框只是第一步把框变成“能不能摘”的决策才是系统真正落地的地方。这层逻辑不复杂但没有它模型就只是个玩具。最后分享一个我在实际部署中总结的小技巧如果大棚里光照条件变化大可以在推理前加一个简单的自动白平衡校正把图像颜色拉回标准光照下的分布。这一步几乎不增加计算量但能让模型在不同时间段的表现更稳定。我实测下来加了白平衡之后早晚时段的误检率下降了约 15%。这个细节在论文里通常不会写但在真实场景里非常管用。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门