ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

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

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-CNN+FPNDINO-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:业务指标才是验收的准星

技术指标上,我用mAP@0.5:0.95、AP@0.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基线上,我的改进版在自建验证集上的mAP@0.5:0.95提升了约4个百分点,其中AP_small提升最明显,大约涨了6个百分点。这个提升幅度看起来不是翻天覆地,但要考虑到基线本身已经是DETR系里精度很高的模型,棉田数据上的每一步提升都在回应业务指标。

五类目标里,吐絮铃的召回率从82%拉到了91.5%,终于越过了90%的验收线。蕾和花的计数误差稳定在8%以内,青铃的误报主要来自叶片边缘的类铃形纹理,这是目前已知最难缠的残留问题,可能要等引入时序信息做前后帧消歧才能根治。

7.2 最容易翻车的几类田间情况

如果让我给后来者排一个“翻车优先级”,排第一的是大雨之后的泥土地反光,第二是午后长阴影造成的大量半个目标,第三是无人机高速飞行带来的运动模糊。这三类情况在增强阶段很难完全模拟,只能靠补充真实采集数据来硬磨。

另一个容易被忽视的是相机焦段差异。我前期所有训练数据都来自固定的无人机镜头,后来有用户用低空手机拍摄的近景图上传系统,尺度和纹理分布直接偏离训练域,检测效果肉眼可见地变差。多源数据统一做过归一化、按目标像素尺寸重采样到相近范围,才把跨设备带来的精度损失压到可接受范围。

7.3 后续迭代的几个方向

下一步我打算做三件事。一是接入视频流做时序目标跟踪,用帧间关联信息把单帧漏检的目标补回来,顺便解决重叠区域的计数重复问题。二是做跨地块迁移,把光照和土壤背景做风格迁移式增强,提升模型在不同棉区的泛化能力。三是把半自动标注流程做成系统里的内建模块,用当前模型对新采集图像做预标注,人工只负责修正,把标注成本再降一个量级。

农业视觉项目很少能一套模型跑到底,真正值钱的是那份从数据到部署的工程闭环。DINO-4scale只是这条链路上一个性能更匹配的切入点,不是银弹,但至少让我在“数蕾、数花、数铃”这件事上交出了一份靠谱的答卷。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进