DINO-4scale农业视觉落地记:棉田目标检测从选型到部署

发布时间:2026/10/20 13:32:47
DINO-4scale农业视觉落地记:棉田目标检测从选型到部署 做农业视觉项目绕不开一个尴尬现实算法论文里刷分的“花瓶”场景拿到大田里第一时间就露怯。棉花这种作物更是典型——每株上几十个蕾、十几朵花、七八个铃叠在一起叶子和茎秆一遮远处看就是一片绿。我这一年多时间在做棉田作物生长监测与识别系统模型基线选来选去最后落在改进的 DINO-4scale 上才把漏检和错误计数的问题真正压下来。这篇文章不做论文复读而是把我从需求拆解、模型选型、数据标注到训练部署的完整过程记录下来给准备在农业视觉方向上做检测落地的朋友一个可参考的路线。1. 棉花监测到底要解决什么事从田间痛点拆需求1.1 物候期识别是一整套系统的地基棉花从苗到吐絮农事决策跟着物候期走。现蕾前要控旺促根花铃期要防虫防病吐絮期要根据吐絮进度安排打脱叶剂、定采收时间。传统做法是技术员下地按五点取样法数蕾、数花、数铃一亩地折腾一上午。我接触的几位棉农反馈都一样数得慢、数不准、年轻人不愿意干。所以这个项目的第一需求不是“识别棉花”四个字而是把株上的器官形态和数量变化自动量化。通俗讲就是回答五个问题这棵棉株上有多少蕾、开了多少花、结了多少青铃、有多少成铃开始膨大、有多少铃已经吐絮。这几个数字一旦能按田块、按时间自动统计出来后面所有的施肥、化控、虫情预警和采收安排就都有依据了。沿着这个需求往下拆系统必须做到三件事一是能从田间拍摄图像中定位出单个棉株器官二是能把蕾、花、青铃、成铃、吐絮铃这五类区分开三是能稳定输出每类目标的计数和分布信息。前两条靠检测模型解决第三条需要把检测结果做成统计报表。整个系统的地基就是目标检测不是图像分类也不是语义分割。1.2 为什么分类和分割模型在这个场景里都靠不住我最早试过图像分类的思路把一张图片直接判定为“现蕾期”或“花铃期”。做出来发现实用性很差。大田环境里一株进入初花期另一株还在现蕾一张无人机俯视图里可能同时混着好几种物候状态。分类结果只能告诉我“整体大概在哪一期”根本回答不了“这一行棉株有多少铃开得合适”这种精细化问题。语义分割也试过效果中规中矩但有一个致命麻烦棉铃、蕾、花在颜色和形状上非常接近分割图里相邻器官的边界老是糊在一起计数时得额外做连通域分析和形态学处理误差越滚越大。而且分割标注的人工成本比检测标注贵出一大截。算完账之后我彻底放弃了分割路线方案收敛到目标检测用矩形框把人眼看得清的器官框出来再按类别计数。1.3 需求清单落地的具体指标做系统之前我和需求方把验收口径也定了下来这些指标后来直接影响模型选型和训练策略。类别定义方面我把棉株器官分成五类蕾bud、开花flower、青铃young_boll、成铃mature_boll、吐絮铃open_boll。实际标注中还会补充一个“背景难例”类别用来收集容易造成误报的杂草、枯叶、滴灌带反光等干扰物但最终统计时不算作物器官。精度要求方面需求方给出的核心业务指标是吐絮铃类的召回率不低于90%蕾和花的计数误差控制在10%以内。至于mAP这类学术指标只作为技术选型上的参考不作为验收口径。这给我提了个醒做工程落地业务方只关心“你吐絮铃漏了几个”“你蕾数多了还是少了”不关心mAP小数点后面几位。运行环境方面无人机在田间采集图像后可以在农户电脑或边缘设备上批量处理也可以传到一台有GPU的服务器上跑推理。这意味着模型需要在不太夸张的算力条件下保持合理速度单张2000万像素图像处理时间控制在几秒内比较理想。2. 为什么基线选了 DINO-4scale从DETR到DINO的路线逻辑2.1 4scale到底指什么先说结论DINO-4scale不是一个模型名称而是DINO检测器使用4个特征尺度参与解码的一种配置。要理解它得从DETR这条线说起。传统目标检测器大多基于卷积和锚框像Faster R-CNN、YOLO检测头需要在特征图的每个位置枚举大量候选框再做分类和回归。DETR系列走的是另一条路把目标检测看作集合预测问题让模型直接输出一组框和类别通过二分图匹配算损失。它用Transformer的注意力机制建立全局关系不再需要锚框生成和NMS后处理。DETR早期的问题有两个训练收敛特别慢对小目标不友好。Deformable DETR引入了可变形注意力只让每个query关注参考点周边的少量采样点计算量降下来收敛也快了。再到DINO在Deformable DETR基础上又加了对比去噪训练、混合查询选择、查询去噪这些trick把训练稳定性和最终精度推上一个台阶。“4scale”指的是向编码器提供的特征层级数量。默认backbone输出C3、C4、C5三层特征分辨率依次是输入图像的1/8、1/16、1/32。很多检测模型只用C4和C5或者只用C5。DINO-4scale则把C3、C4、C5再加上一个通过下采样得到的C6分辨率1/64总共四层特征一起喂进跨尺度Transformer编码器让模型对多变尺度目标都有感知。这套设计对棉田场景的结构性优势很明显。棉株上的蕾、花、青铃尺寸差异极大无人机在25米高度拍到的蕾可能只有20个像素左右而成熟棉铃横跨上百像素四尺度特征天然适配这种尺度跨度。另外Transformer解码器通过注意力迭代精修框回归对遮挡和密集堆叠目标有一定容错能力这正对症棉花器官相互遮挡的难题。2.2 密集堆叠和小目标这两关卡住了多少模型我在自采数据上做过横向对比最有说服力的是把YOLO系列拉出来跑了一轮。YOLO工程生态好、部署资料多初测mAP也不差但一细化到小目标和密集场景就露馅。棉株俯视图里蕾和蕾之间经常只有一线分隔花簇和青铃叠在一起YOLO的锚框匹配策略在密集场景下容易把两个目标并成一个框或者一个目标被赋予两个框。加上NMS后处理在视觉歧义区域经常误删真框吐絮铃和白色花朵同时出现时NMS表现相当不稳定。Faster R-CNN也有问题。它本身精度不低但两阶段结构做这套任务时RPN阶段要在数千个候选框中筛来筛去棉花叶面纹理复杂候选框噪声很大。最要命的是两阶段框架的工程复杂度高后来改DETR系方案时我几乎没犹豫。DINO-4scale的优势体现在查询式解码上。它让每个目标用一个可学习的query表示通过层层解码逐渐聚焦到真实位置天然具备“迭代修正”能力。4scale编码器又能把全图语义背景和局部细节融合起来判断“这团白色是棉絮还是白花”时模型可以参考周围环境而不是只看局部纹理。这种全局上下文理解能力是卷积检测器不太擅长的地方。2.3 基线算账精度、算力和工程成本三者平衡选基线不能只看跑分要算全家账。我的账是这样算的对比维度YOLO系列Faster R-CNNFPNDINO-4scale检测精度上限常规场景够用较高高密集场景优势明显小目标能力一般易漏检依赖FPN配置4scale多尺度编码器表现更稳后处理复杂度需调NMS、多标签冲突需调NMS查询式解码省去NMS训练成本低中较高但可比部署成熟度高高中高导出推理需额外处理面对密集重叠目标容易合并漏检候选框冗余多迭代精修效果最稳最后定DINO-4scale不是因为它在学术benchmark上刷了多少分而是因为它把棉田场景最要命的“小目标密集遮挡”问题解决得最直接。算力方面DINO-4scale比YOLO吃资源但田间批量推理不是实时视频流一个带GPU的节点就能扛住。我需要的是精度换来的可靠性不是几毫秒的实时性。3. 我实际动了哪几刀面向棉田场景的三个针对性改进3.1 跨尺度加权融合把浅层细节真正喂进编解码器DINO-4scale虽然用了四层特征但默认配置里不同尺度特征的贡献基本平权。这个设置在COCO那种目标尺度分布比较均衡的数据集上没问题可棉田场景里蕾和幼铃大量集中在较小尺度高分辨率特征应该占据更大权重。我做的第一个改动是在编码器输入端加了一层跨尺度加权融合模块。不是简单把特征图相加而是给每层特征学习一个可训练的空间权重和通道权重。具体做法是把C3、C4、C5、C6四层特征先做统一通道投影再接一个轻量的门控卷积对不同层乘以逐通道的sigmoid权重。这样模型可以根据图像内容自适应决定是主要依赖高分辨率的C3去抓蕾还是更多依靠语义更强的C5去判断大目标。这个融合结果再送入原有的可变形注意力编码器。改动量不大但小目标一类的AP明显回升。原理也很好解释蕾和幼铃尺寸本就小于模型预设的有效感受野如果不主动强化浅层细节检测器很容易把“小目标”当成“大目标周围的纹理噪声”而丢掉。3.2 物候先验引导的查询初始化让解码器少走弯路DINO的解码器里有两类query一类叫位置查询负责提供候选框位置另一类叫内容查询负责编码目标语义。默认配置下这些查询在训练初期基本是“盲猜”全靠解码器一层层把信息迭代出来。棉田场景有个可以明用的先验物候期之间在时间和空间上有强相关性。比如现蕾期棉株上几乎不会同时出现大量吐絮铃花铃期白花的比例会骤升。如果把“当前图像大概率属于什么物候背景”这个先验作为查询初始化的一部分解码器就能更快收敛到合理答案。我做的第二个改动是给位置查询加了一个轻量的物候上下文向量。在编码器输出端对整图特征做一次全局池化压成一个128维的物候特征再与原始位置查询做线性融合让不同位置的查询携带全局背景信息。实测算下来训练收敛速度大概提前了10个epoch左右中后期的mAP波动也变小了。背后逻辑不复杂模型在解码早期就知道“这一片大概率是花铃期”就不会把焦点浪费在搜索“有没有成铃”上。3.3 损失函数调整类别不平衡和小目标难例要区别对待棉田五类目标的数量分布极不均衡。青铃和蕾在盛期数量巨大白花和吐絮铃相对稀少初开的吐絮铃甚至整片地里只有几个。直接用默认的二分图匹配损失模型注意力会被“数量多的类别”绑架白花和吐絮铃因为样本太少梯度贡献被压到几乎为零。我引入类别的代价矩阵到匈牙利匹配里对样本稀少的类别给出更高的匹配代价权重让模型在匹配阶段就优先照顾这些类别。具体数字不贴了思路就是“按类别频次倒数的平滑版本”来调整代价矩阵。同时原始损失里分类用的是标准交叉熵。我换成了带focal性质的变体对容易分类的前景样本降低梯度权重把模型的学习重心往“难分难辨”的目标上引——比如被叶片挡了一半的成铃、和背景反光亮度几乎一致的白色吐絮铃。这套组合拳打完之后白花和吐絮铃两类的召回率提升尤其明显。4. 数据是棉田模型的隐形天花板采集、标注与增强4.1 采集规则无人机和地面相机各跑一摊模型再强也扛不住数据本身拉胯。我在数据采集上定的规则就三条光线稳定、角度多样、物候完整。无人机在晴天上午9点到11点之间拍摄避免正午顶光造成的阴影和过曝。飞行高度控制在20到25米单片覆盖面积和单个目标的像素尺寸都比较合适。地面机位则用手持设备贴近棉行主要收集细节纹理用于补充变化较大的目标形态。更重要的是按全生育期跟踪采集。从6月上旬现蕾前开始每周一次的频率一直拍到9月中旬吐絮期结束。中间遇到大风倒伏、病虫害导致的叶片卷曲也会额外加采一轮。只有让模型见够“整个生长季的样子”它才能在不同物候状态下都保持稳定识别。4.2 标注体系小目标保留、遮挡兜底、背景难例单列标注规范是踩过坑之后反复改出来的。第一版规范太粗标注员对只有四五个像素的小蕾经常直接跳过导致小目标样本空洞化。后来源码规定了两条硬性规则一是像素尺寸大于等于4x4的可见蕾花铃目标必须标注防止小目标被系统性漏标二是遮挡程度不超过30%的目标必须标注超过30%但能确认类别的也要标注为“遮挡难例”当作困难样本保留。吐絮铃和白色花朵的视觉相似度极高是标注出错的重灾区。前期我单独标了一类背景难例专门收集滴灌带反光、白色塑料残膜、枯黄叶片这类目标让模型学会“这不是棉花器官”。这个动作看起来跟检测无关实际上让白花类的误报率下降了将近一半。4.3 增强策略不止是翻转和颜色抖动常规的随机翻转、颜色抖动我都在用但真正起作用的是两类针对性增强。第一类是Copy-Paste增强。把标注出来的吐絮铃目标随机裁剪粘贴到另一张不相关背景图的空白区域人为制造更多开花和吐絮样本解决极不平衡问题。为了模拟真实感粘贴时只保留棉桃区域的RGB像素边缘不做锐利切割而是叠加一个透明度渐变防止模型通过边框痕迹“作弊”。第二类是块状遮挡模拟。在训练图像上随机挖掉几个矩形区域用周围像素的平均值填充模拟叶片遮挡、茎秆交错的情况。这么做是让模型在解码阶段提高对不完整目标的容错能力。实测下来验证集里遮挡程度较高的目标检测率确实涨了一截。5. 训练实战从收敛徘徊到稳定提升的调参记录5.1 关键训练配置和加载细节我的基础环境用的是原生PyTorch实现加载DINO在COCO上发布的预训练权重。这里有个容易翻车的点预训练权重里的类别数是80我的类别是5加1个背景难例加载时最后一层分类头和匹配代价矩阵必须重新初始化不能直接沿用。训练参数上输入分辨率固定为800x800单卡batch size设到4多卡并行梯度累计等效batch size为16。优化器用AdamW初始学习率1e-4主干网络学习率乘0.1倍权重衰减设为1e-4。一共训80个epoch其中在60个epoch时把学习率降到原来的十分之一。数据增强用了随机裁剪、随机翻转、Copy-Paste和块状遮挡但随机裁剪的裁剪范围限制在原始图像的80%以上防止切掉过多上下文导致模型学偏。5.2 训练曲线分析三个典型的翻车信号第一次训练就翻车了三个地方拿出来单独说。第一个信号是训练损失下降正常但验证集小目标AP一直不涨。排查后发现是浅层特征参与度太低跨尺度加权融合的参数初始化偏保守浅层特征权重几乎为零。解决办法是给融合模块单独初始化一个偏大的偏置强制浅层特征在前几个epoch先“说话”。第二个信号是白花和吐絮铃的损失项震荡剧烈。分析匹配矩阵发现这两类因为样本少匈牙利匹配时经常匹配不到query导致好一阵子没有梯度。加了代价矩阵权重之后震荡立刻缓解。第三个信号最有意思把包含滴灌带反光的背景难例塞进训练后模型整体mAP反而小幅下降。查了原因是硬负样本数量太多把模型对真实目标的注意力冲淡了。后来把背景难例的比例从10%调到5%并保证每batch里都有一定比例的正常目标问题才消掉。5.3 不能只看mAP业务指标才是验收的准星技术指标上我用mAP0.5:0.95、AP0.5、AP_small像素小于32x32的目标和mAR做横向比较。但真正指导训练的其实是业务指标每类别的召回率、每图的计数误差、吐絮铃的误报率。这里我踩过一个教训前期只看mAP模型整体分数好看但吐絮铃一类的业务召回率只有82%完全达不到验收线的90%。原因就是mAP是五个类别的平均数量多的类别把分数抬上来了。后来我把每类召回率单独打印出来按类别分别设置收敛阈值才逼着模型把最难的吐絮铃类也拉到90%以上。6. 从模型到系统推理管线与田间部署的硬骨头6.1 大图切块推理怎么切才不漏检不重框无人机拍出来的单张照片动辄2000万像素直接整图送进模型会因为显存限制和分辨率缩放导致小目标丢失。我采用的方案是大图切块推理把原图按960x960的窗口、10%重叠率切成若干块每块独立推理。切块带来的问题是同一个目标在重叠区可能被检出两次。我在后处理里写了一个去重合并逻辑先基于类别和IoU做一次框的聚类同一类别且IoU大于0.5的框保留置信度最高的一个。这个逻辑比传统NMS温和因为它不限制一个目标只能有一个框而是只处理重叠区域的重复框保留边缘区域独立检出的结果。切块还有一个细节边缘目标被切掉一半很容易漏检。我在切块时给每块扩展了20像素的边界padding并在后处理时裁剪掉对应区域避免padding带来的位置偏移。6.2 部署架构服务拆成两段系统分成了离线分析和轻量服务两段。离线分析用于处理无人机田间采集的大批量图像跑在有GPU的服务器上按批次提交任务结果写进数据库。轻量服务供农户或技术员随时上传单张照片获取当季物候诊断跑在一个更轻量化的推理实例上启动快、显存占用小。后端推理服务我用的FastAPI模型导出后走ONNX推理输入输出封装成标准接口。前端展示除了画框叠加图还有按类别的柱状统计、按时间序列的物候变化曲线以及和上一期数据的对比差异。这一层是给使用者看的界面不需要花哨但数据要能一眼读懂。6.3 实际跑通中躲不开的条件限制部署后另一个头疼问题是运行环境差异。农户的电脑千奇百怪有的根本装不上深度学习运行环境。我最后的妥协方案是模型推理部署在固定服务器或边缘节点上前端只做浏览器访问避免在目标用户的本地环境里安装任何复杂依赖。田间图像还存在严重的场景漂移。不同地块土壤背景不同灌溉方式不同甚至同一块地不同行间光照条件都不同。这导致模型换地块之后精度下降明显。为此我保留了“在线反馈-增量修正”的机制系统对置信度低于阈值的检测结果进行人工复核复核数据定期回流做小规模微调。这一看就是长期主义的设计但在农业场景里没有这个闭环系统生命周期基本撑不过一个生长季。7. 效果复盘与还没解决的硬问题7.1 自建验证集上的结果对比在原版DINO-4scale基线上我的改进版在自建验证集上的mAP0.5:0.95提升了约4个百分点其中AP_small提升最明显大约涨了6个百分点。这个提升幅度看起来不是翻天覆地但要考虑到基线本身已经是DETR系里精度很高的模型棉田数据上的每一步提升都在回应业务指标。五类目标里吐絮铃的召回率从82%拉到了91.5%终于越过了90%的验收线。蕾和花的计数误差稳定在8%以内青铃的误报主要来自叶片边缘的类铃形纹理这是目前已知最难缠的残留问题可能要等引入时序信息做前后帧消歧才能根治。7.2 最容易翻车的几类田间情况如果让我给后来者排一个“翻车优先级”排第一的是大雨之后的泥土地反光第二是午后长阴影造成的大量半个目标第三是无人机高速飞行带来的运动模糊。这三类情况在增强阶段很难完全模拟只能靠补充真实采集数据来硬磨。另一个容易被忽视的是相机焦段差异。我前期所有训练数据都来自固定的无人机镜头后来有用户用低空手机拍摄的近景图上传系统尺度和纹理分布直接偏离训练域检测效果肉眼可见地变差。多源数据统一做过归一化、按目标像素尺寸重采样到相近范围才把跨设备带来的精度损失压到可接受范围。7.3 后续迭代的几个方向下一步我打算做三件事。一是接入视频流做时序目标跟踪用帧间关联信息把单帧漏检的目标补回来顺便解决重叠区域的计数重复问题。二是做跨地块迁移把光照和土壤背景做风格迁移式增强提升模型在不同棉区的泛化能力。三是把半自动标注流程做成系统里的内建模块用当前模型对新采集图像做预标注人工只负责修正把标注成本再降一个量级。农业视觉项目很少能一套模型跑到底真正值钱的是那份从数据到部署的工程闭环。DINO-4scale只是这条链路上一个性能更匹配的切入点不是银弹但至少让我在“数蕾、数花、数铃”这件事上交出了一份靠谱的答卷。