1. 项目概述
做农业视觉项目这几年,我一直觉得无人机巡检是个又香又难啃的领域。香在哪儿?它把传统人工下地数苗的活儿搬到了天上,效率差距是数量级的——一亩地人工清点得蹲半个小时,无人机飞一遍只要几十秒。难在哪儿?数据。
最近完成了某智慧农业项目里的一块核心工作:烟草出苗率识别数据集的构建与模型验证。从无人机采集、数据清洗、标注规范到RTDETr和YOLO系列算法的对比训练,整个流程跑通之后,我把这次实操的完整记录整理出来。围绕“烟草出苗率识别”这个场景,涵盖了数据采集方案的选型逻辑、标注标准的制定、模型训练的关键参数、出苗率的计算方式,以及我在这个过程中踩过的坑和排查思路。
这个活儿适合谁参考?一种是刚入门智慧农业、想了解无人机图像数据怎么落地到实际农情判断的开发者;另一种是已经在做目标检测、想了解RTDETr与YOLO在特定业务场景(比如田间出苗、病虫害计数)下如何选型和调参的算法工程师。我会把从原始图像到最终“出苗率”这个数字的完整链路拆开讲,尽量把每个环节的“为什么这样做”说清楚。
2. 需求分析与方案选型
2.1 业务痛点的本质
烟草出苗率这个指标,在烟叶种植的整个生产周期里属于头一关的“质量卡口”。出苗率不合格,后面的移栽、水肥管理、采收计划全部要跟着调整。传统做法是农技员拿着卷尺在育苗棚或大田里数苗、量间距、估算缺苗率。一个熟练工人一天大概能巡查十几亩地,效率不高不说,人眼估算的主观偏差也很大。同一个地块,不同人统计出来的出苗率可能差五个百分点以上。
从技术角度来看,这个任务的本质是“识别并计数单株烟草幼苗”。听起来就是标准的目标检测问题,但田间环境和实验室差异巨大:苗期植株小(叶片展开也就几厘米)、土壤背景颜色杂、光照变化剧烈、无人机飞行高度导致的尺度差异等等。这些因素叠加在一起,对检测模型的泛化能力要求非常高。单纯拿一个公开数据集训出来的模型直接上无人机图像,大概率效果不好。
2.2 为什么选无人机+可见光方案
当时摆在我们面前的有三条路线:卫星遥感、地面定点相机、无人机低空巡检。
卫星遥感看大范围的作物长势确实有优势,但出苗期植株尺度太小,卫星影像的空间分辨率根本不够——烟草苗期单株冠层直径通常只有5到15厘米,商业卫星的分辨率即使做到亚米级,也很难稳定识别单株。地面定点相机倒是能拍到高分辨率细节,但覆盖范围有限,一大片烟田需要架设几十个点位,成本和维护都是问题。
无人机低空巡检是三者间的平衡点。飞行高度控制在15到40米,搭载的可见光相机可以做到单像素对应地面1到2厘米,清晰分辨单株幼苗完全没问题。单架次续航30分钟左右的四旋翼,一个起降可以覆盖30到50亩地,配合航线规划软件按网格自动飞行,一天采集几百亩影像不费劲。
有一点值得留意:我们在方案阶段就明确了“可见光”作为唯一传感器。多光谱相机确实能提供额外波段信息,对植被指数分析有帮助,比如NDVI这种指标,但对标“出苗率识别”这个任务来说,成本上去了一大截,收益却很有限。出苗率的核心是单株检测,RGB图像已经包含足够的颜色和纹理特征,不需要多光谱那套“杀鸡用牛刀”的方案。
2.3 算法选型与工具链说明
算法层面,最终可选范围锁定在YOLOv8、YOLOv9、RTDETr和YOLOv11这几个主力模型之间。这里我得先说明一下版本问题,YOLO系列迭代很快,v8到v11这个区间内,结构的演进主要集中在C2f/C3模块替换、注意力机制的引入和训练策略的优化。RTDETr相对特殊,它是百度提出的实时检测Transformer模型,走的不是 anchor-based 路线,而是基于 DETR 的端到端检测思路,去掉了 NMS 后处理。这两类模型各有优势:
- YOLO系列:成熟稳定,部署生态好,推理速度快,社区资料多,适合快速落地。
- RTDETr:精度天花板更高,transformer 结构对全局特征的建模能力强,换个损失函数和优化器就能用在检测头上。同样规模参数下精度往往优于CNN类检测器,代价是显存占用更大、训练时间更长。
工具链上我用的组合是:Python 3.10 + PyTorch 2.1 + Ultralytics 框架,显卡是单张 RTX 4090,显存24G。数据标注用的是 X-AnyLabeling 和 Labelme 混用,脚本转换格式。整个流程跑下来,从图像预处理到最终模型导出,已经形成一套可以复用的SOP。
2.4 整体pipeline设计
整个项目分五个阶段:数据采集与清洗、标注标准制定、数据增强与划分、模型训练与评估、出苗率换算与应用。每个阶段都有独立的产出物和验收标准,阶段之间环环相扣。尤其数据采集和标注这两个环节,虽然技术含量看起来不如模型训练高,但实际决定整个项目上限的是它们——模型再强,喂的数据是脏的,结果照样稀碎。这个理念贯穿了我们整个项目执行。
后面几节我按这个流程逐步展开,每个环节都会列出实际的参数配置和经验教训。
3. 数据集构建过程
3.1 无人机采集方案的细节
采集时间窗口的选择是最先要卡死的。烟草出苗期大概在播种后10到15天,此时幼苗刚出土,叶片还没完全展开,是“见苗”的最佳窗口期。等植株长到4片真叶以上,叶片互相遮挡,单株分割难度会明显上升,模型精度会下降。我们的采集窗口设定在播种后第12天到第18天,每天上午9点到11点、下午3点到5点各飞一次。这个时间段光照角度合适,光斑和高光区域最少。
无人机选的是大疆经纬M300RTK这类商用级的设备,搭载了可见光云台相机。为什么不用便携的入门级无人机?第一,RTK定位模块能提供厘米级的定位精度,这对后期拼接正射影像和图幅套合非常关键;第二,M300的机械稳定性好,在高空有风环境下图像拖影明显改善;第三,可换镜头设计让我能用35mm定焦镜头拍出更清晰的细节,单株分辨率更高。
飞行高度、重叠率和航速这三个参数是航线规划时反复调节过的重头戏。最终确认的配置是:飞行高度25米,航向重叠80%,旁向重叠70%,航速6米每秒,云台俯仰角-90度垂直拍摄。这个配置下单张影像覆盖的地面范围大约是45米乘30米,单株烟草苗在图像上占据的面积大概是40到70个像素——刚好处于检测模型最擅长识别的尺寸区间。
两个结合得很好的细节值得补充。一是我们每条航线都设置了仿地飞行功能,因为烟草田经常不是绝对平整的,有田埂和沟壑,仿地飞行让无人机保持固定相对高度,避免局部区域因高度变化导致的尺度突变。二是每次飞行前都做了反射率标定板测试——这本来是做遥感影像用的,但我发现用它对白平衡和光照一致性做初步检查非常有效。
3.2 原始影像的筛选与预处理
采集完的原始照片不能直接进标注环节,中间有一道清洗工序。我们当时一个批次大概采集了4800多张原始航片,清洗后剩余4100张左右可用,清洗率约15%。
清洗分三个层面:
- 剔除有严重运动模糊的照片。判别标准很简单,用拉普拉斯算子计算图像方差,低于设定阈值的都判为模糊。这批照片里大概有6%的这个比例,主要集中在风速超过4级的时段。后来我们把飞行风力上限从6级调低到4级,问题大幅缓解。
- 剔除光照异常图像。正午时段飞行的照片(当时为了赶进度试过中午飞)普遍存在高光过曝问题,叶片反射强烈导致纹理丢失。这种图留下的只是噪声,没有标注价值。
- 剔除植被覆盖率过低的无效图。部分航线的边缘区域因为降落和转弯出了拍摄区域,图像几乎全是泥土背景。这类图占比不小,直接删掉避免浪费标注人力。
预处理阶段我需要做两件事:一是按位置信息把相邻航片做初步的序列化归档,方便后续理解图像间的空间关系;二是做分辨率统一。我用的办法是把图像统一缩放到1920x1080,这个尺寸下标注效率比较高,模型训练也跑得起——原始4:3画幅按这个分辨率缩放后,植株尺寸略微变小,但检测任务通常没问题。
3.3 标注标准的制定与执行
标注是整个数据构建过程中最需要“较真”的环节。我们在项目初期就明确了两个目标:一是保证单株幼苗的框标注精确——不遗漏、不过度合并;二是统一标注口径,使不同的标注员之间的标注风格保持一致。
针对烟草苗的特点,我定义了三条硬性标注规则:
- 单株幼苗用一个水平包围框标注。框的上边沿贴近叶片最高点,下边沿贴近叶片与土壤的交界处,左右两侧紧贴冠层最外缘。核心是“宁大勿小”——宁可框外扩3到5像素,也不要截断叶片边缘,因为训练模型时被截断的边缘会产生严重的负梯度影响。
- 叶片重叠但根茎可辨的两株幼苗,按两株独立标注。这点是反复向标注员强调的。很多标注员看到叶片连在一起就习惯性标成一株,导致模型后期学到的目标定义混乱。判断依据是观察基部是否有明显分离点。
- 缺苗区域不标注。这里的“缺苗”指的是种子没有出芽,形成明显的空穴。要求标注师在这个位置打一个“缺苗点”标签,不与检测框混合。这样出苗率计算时就有了“有苗”和“缺苗”两个互补信号。
标注格式用的是YOLO格式,即每个图像的.txt文件中记录类别编号、中心点x、中心点y、宽度w、高度h,全部归一化到0到1。这个格式的好处是所有主流检测框架直接支持,不需要写转换代码。标注工具选择了X-AnyLabeling作为主力,配合Labelme做复核,标注效率比纯Labelme高了不少,特别是自动分割模型的辅助半自动标注功能,对大田场景省了不少力气。
第一轮标注完成后,我们做了一次全员抽检复核。四个标注员各抽20张图交叉检查,以框的IoU一致性为指标。阈值定为0.7,低于这个数值的框回到标注员手上修正。这一轮执行下来,标注一致性从最初的0.61提升到了0.82。后面统计模型性能时,明显感觉到干净标注带来的收益——同样的模型结构,干净数据比之前用自动标注器一键生成的伪标签数据在AP上高出10个百分点都不止。
3.4 数据增强与训练集划分
烟草苗期图像的一个显著难题是正负样本不均衡。大田图像里绝大部分区域是土壤背景,正样本(烟苗)面积占比通常只有1%到3%。这种数据分布对目标检测模型不算友好,容易导致收敛速度慢、误检率高。
我的处理策略有三板斧:
第一,离线裁剪。把1080p原图按512x512滑窗切成小块再做训练,每块图像中保证至少包含一株烟苗或一个缺苗点。这样既提高了有效样本密度,又天然做了数据增强。
第二,在线增强。训练时使用了Mosaic(4张图拼1张)、MixUp(两张图混合)、HSV扰动、随机翻转和随机缩放五类增强手段。Mosaic对提高小目标的检测能力帮助很大,因为这个操作迫使模型在裁剪和拼接的图上学会定位不同尺度的目标。实际训练中我把Mosaic概率设到0.5,注意在最后20个epoch降为0,因为Mosaic产生的伪图像特征会干扰最终收敛阶段。
第三,训练集/验证集/测试集的划分按“地块隔离”原则。也就是说,同一个地块的图像不能同时出现在训练集和验证集中。如果只是随机划分图像,模型很可能在记忆地块特征而非烟苗特征,验证指标虚高,到了新地块上就现原形。我们总计使用了约35000张512x512的切片,训练集:验证集:测试集比例是7:2:1。这个比例对大样本场景下是合理的选择。
4. YOLO与RTDETr训练实操
4.1 RTDETr与YOLO的结构对比与选型依据
既然数据集已经建好了,接下来进入最“博客体”的环节——模型训练对比。RTDETr和YOLO之间的选择,实际是一个结构差异驱动的决策。这里我需要重点解释一下RTDETr的设计思路,因为很多人对Transformer检测器存在“慢”的刻板印象,但RTDETr改变了这个局面。
RTDETr的核心卖点是“实时+端到端”。它把传统DETR的object query机制和CNN的高效骨干进行了融合。损失计算直接基于匈牙利匹配的集合预测损失,不像YOLO那样需要锚框匹配和NMS后处理。这样整个训练和推理流程更加干净,模型在训练时能够直接优化“一张图里最终输出的检测框”与“真值框”之间的匹配质量,而不是经过多层中间代理。
RTDETr与同参数量YOLO在精度上没有绝对输赢——普遍感知是RTDETr在中等以上的目标上精度略高,而在很小目标的检测上不一定超过YOLO。我们的场景中烟苗属于中小目标,两者差距没有想象中那么大,但RTDETr在遮挡区域的检测连续性上表现更好,因为它的自注意力机制天然建模了上下文信息,而YOLO的局部感受野做不到这种跨区域关系建模。
选型上我最终CPU配置了四组对比实验:
| 模型 | Backbone | 输入尺寸 | 初始学习率 | Batch Size | 训练Epochs |
|---|---|---|---|---|---|
| YOLOv8n | CSPDarknet | 640 | 0.01 | 16 | 120 |
| YOLOv8x | CSPDarknet | 640 | 0.01 | 8 | 120 |
| YOLOv11n | CSPDarknet | 640 | 0.01 | 16 | 120 |
| RTDETr-l | ResNet-50 | 640 | 0.0001 | 8 | 120 |
这个配置表背后有几个考虑:n版(nano级)是验证整套流程可行性用的,x版(超大级)作为效果上限参考,v11用来验证最新结构收益,RTDETr-l作为精度候选。所有模型都加载了COCO预训练权重做微调,这是这类模型快速收敛的关键操作。
4.2 训练过程中最关键的参数调节细节
训练模型的坑我踩了不少,这里把最有价值的几条经验拎出来说。
批次大小对显存消耗的影响大于分辨率。YOLOv8x在640输入、batch size 8时显存接近满载,RTDETr-l在同样配置下batch size只能压到6,否则直接OOM。这个在单卡24G的机器上尤其明显,做实验前先确认显存余量,不要盲目抄别人参数。
学习率策略要分模型类型区别对待。YOLO系列用SGD优化器配0.01的初始学习率效果很好,配合线性Warmup加余弦退火,120个epoch训练下来Loss曲线非常平滑。RTDETr则完全不同,它底层用的AdamW,学习率默认只有0.0001,还带权重衰减。如果照搬YOLO那套学习率,模型基本不收敛。这也是很多新手第一次跑RTDETr时最容易犯的错误。
Mosaic增强虽然好用,但在最后阶段一定要关。这是我在多个项目里验证过的经验。之前有一次没关Mosaic,最终AP值停留在0.83左右上不去,排查了很久发现就是Mosaic拼接产生的“假样本”干扰了收敛。正确的做法是最后20个epoch把增强降级为仅HSV扰动和翻转,这样模型能完全适应真实图像分布。
EMA(指数移动平均)必须开启。所有训练中我统一使用EMA衰减因子0.9999,它对最终AP的提升大约是1到2个点。几乎零成本的小操作。
标签平滑系数设为0.01。烟草苗这种“目标紧贴背景”的场景,标签平滑能减轻模型对精确边框的过拟合,缓解置信度饱和问题。这个参数设在0.01到0.05之间效果都不错,太大反而损伤精度。
框回归损失的权重我保持默认,但分类损失权重调整到了0.7。原因是我们的目标单一(就烟草苗一个类别),分类分支太强会导致模型对背景区域产生过高的假阳性概率,把权重压低一点,让回归分支主导优化方向,误检率有明显下降。
4.3 四组模型的结果对比与解读
训练完成后,评估标准用COCO风格AP(IoU阈值0.5和0.75)、AR和推理速度一起来看,这样能平衡精度和落地可行性。最终数据如下:
| 模型 | AP@0.5 (%) | AP@0.75 (%) | 推理速度 (ms/帧) | 模型大小 (MB) |
|---|---|---|---|---|
| YOLOv8n | 89.2 | 72.1 | 3.2 | 12 |
| YOLOv8x | 93.8 | 81.5 | 18.6 | 246 |
| YOLOv11n | 90.1 | 74.6 | 3.0 | 13 |
| RTDETr-l | 94.6 | 83.2 | 21.4 | 224 |
几个有意思的发现是:YOLOv8x与RTDETr-l的AP@0.5差距只有0.8个百分点,但AP@0.75差距拉大到1.7个百分点——这印证了RTDETr在“精确定位框”上的优势。而YOLOv8n到YOLOv8x的提升幅度达到4.6个百分点,说明模型容量在这个数据集上还没有饱和,还有上涨空间。不过这一切提升都是以推理速度为代价的。
部署时还有一个细节:端到端RTDETr不需要NMS,而YOLO系列即使是使用autoanchor也仍然需要NMS这一步。在批量推理和落地部署场景中,NMS的耗时不可忽略,RTDETr端到端干净利落。这也是我们最终主模型选RTDETr-l的原因之一——虽然单帧慢一点,但省掉的NMS时间和精度的综合收益是正的。
4.4 模型剪枝与TensorRT加速的尝试
部署之前还做了一轮工程优化,目标是减少模型体积同时尽量保留精度。我们尝试了一种结构化剪枝手法,通过缩放因子对BN层进行剪枝。整体流程分三步:稀疏化训练(在训练末期给BN层的缩放因子加L1正则)—> 按阈值剪枝(将缩放因子低于0.01的通道移除)—> 微调恢复(保留原始未剪枝权重初始化)。
在YOLOv8x上做了50%比例的剪枝,效果是模型从246MB降到120MB,但AP@0.5从93.8%掉到了91.2%,掉幅2.6个百分点。剪枝后的模型又用原始数据集做了50个epoch微调,恢复了0.8个点,最终到92.0%左右,与未剪枝版本仍差约1.8个点。这笔账算下来我觉得不太划算——项目对模型大小没有极端要求,精度损失换来的体积缩减不匹配。最终没有采用剪枝版模型。
TensorRT加速倒是很值得做的。用官方工具把RTDETr-l的ONNX导出为FP16引擎,推理速度从21.4ms下降到8.7ms,精度损失几乎可以忽略(AP@0.5只掉了0.3个点)。这个优化让RTDETr在边缘算力设备上的部署成为现实,也为后续大范围推广扫清了算力障碍。
5. 出苗率计算逻辑与业务落地
5.1 从检测框到实际出苗率的换算原理
模型输出的检测框不能直接当出苗率用,中间还隔着一道坐标系转换和数据转译的工序。
这一步的原理牵扯到像素坐标与实际地理坐标的对应关系。无人机采集时每个航点都记录了GPS+RTK的定位信息和IMU姿态数据,每张影像除了像素内容还带位置元数据。只要知道飞行高度、相机焦距和传感器尺寸,就能算出每个像素对应的地面实际尺寸。常用公式是地面采样间隔GSD = (飞行高度 × 传感器宽边物理尺寸) / (焦距 × 图像宽边像素数)。
举个例子,我们常用的配置是飞行高度25米、焦距35毫米、传感器尺寸13.2毫米、图像宽边5472像素。代入公式算出来GSD约为1.72厘米/像素。也就是说,一个30乘30像素的检测框,对应的实际地面面积大约是半平方米左右。
但这里有个坑要注意:无人机在飞行中并不是绝对水平,云台虽然能补偿一部分姿态角,但存在残留的倾斜。每个像素对应的地面尺寸在近端和远端会有一点差异,严格来说需要做一个正射校正,把中心投影影像变换成垂直投影。如果只做粗略的出苗率统计,可以忽略这个校正误差,但要每株苗的坐标距离做精确计算,就必须做正射校正了。我们在项目中用无人机自带的POS数据做了轻量级的畸变校正和仿射变换,基本满足需求。
5.2 出苗率统计的两种业务口径
出苗率这个指标的定义在不同生产阶段是有分歧的。按照烟草种植规范,有一种是“穴盘育苗出苗率”——以穴盘格数为分母,出苗孔数为分子,算的是育苗阶段的质量。另一种是“大田出苗率”——以计划移栽株数为分母,出苗存活株数为分子,算的是移栽后的成活情况。我们项目做的是后者,即大田场景下的出苗率。
大田出苗率在具体计算时还涉及一个抽样问题。一垄烟田几百米长,不可能逐一统计所有植株。实际操作中按地块划网格,每个网格抽取若干代表性区域统计出苗株数,再外推到全田。无人机巡检的意义正是把这个人工抽样变成全田普查——模型对整块田逐图像检测后,把检测框坐标投影到田块坐标系中,做空间拼接和去重,最终得到全田的苗株分布热力图。
这时我们前面提到的“双信号”就起作用了。检测框是“有苗”信号,缺苗点是“无苗”信号。出苗率计算公式写出来是这样:
出苗率 = 1 - (缺苗点数量 / (检测到的苗数 + 缺苗点数量))
这个公式看起来简单,但有个隐含前提——模型对缺苗点的识别必须足够准。否则地里明明有苗但苗太小模型没检出,同时缺苗点又漏标,算出来的出苗率会严重失真。所以模型评估时不只看检测AP,还单独计算了缺苗点类别的召回率,保证这个分母的合理性。
5.3 可视化输出与决策支持
模型跑完一通,光输出几个数字对农场管理人员来说是不够的。我在落地时做了一个前端可视化页面,功能包括三块:
第一块是总览热力图。农技员打开页面能看到整块田的出苗率热力图,颜色从深红到深绿代表出苗率从低到高的渐变。单独一个地块出苗率低的区域标红,配合地图底图,管理者一眼就知道哪些区域需要补苗。
第二块是明细统计表。每个地块按播种批次、移栽批次、负责人等维度汇总出苗率,支持按阈值筛选(比如出苗率低于85%的地块单独列出),导出Excel交给现场人员去安排补苗计划。
第三块是时间序列对比。我们把同一个地块在出苗后第10天、14天、18天分别飞行的数据拉出来做成曲线,可以看到出苗率的动态变化趋势。这个功能最初是额外做的,没想到农场用户非常喜欢——因为它能直观看到“这片地苗长得快、那片地苗长得慢”,对水肥管理的指导价值甚至超出了出苗率本身。
5.4 边缘部署与推理管线
实际部署地点在农场,不可能把每张图传回云端处理再返回结果——农场网络条件不稳定,延迟不可控。我们的方案是把训练好的模型部署在一台边缘计算盒子(NVIDIA Jetson Orin)上,与无人机遥控器连接,形成“飞行—采集—推理—出图”的闭环。
推理管线设计时要考虑的细节不少。首先是队列管理:无人机每秒产生一帧高分辨率图像,实时推流给计算盒子。如果推理速度跟不上采集速度,就会累积延迟。我们采用的是“采集流水线+独立推理线程+结果缓存”结构,采集线程只负责收图入队,推理线程从队列取图执行检测,检测结果带时间戳和位置信息写入结果库,供后端统计调用。
实时性上,以RTDETr-l的TensorRT FP16版本为例,单帧推断8.7ms加上图像预处理(缩放、归一化、通道变换)约3ms,整体单帧耗时控制在10到12毫秒以内,完全跟得上采集节奏。
这个部署方案证明了即便在农业这样基础设施较弱的场景下,边缘AI也完全具备可行性。部署时唯一需要反复测试的是散热——野外高温环境下Jetson Orin满载运行温度很容易到85摄氏度以上,会触发降频。后来加装了散热风扇支架,问题才解决。这个坑,后面做农村现场部署的朋友值得提前注意。
6. 训练过程中的常见问题与排错实录
6.1 数据标注质量参差不齐导致的AP偏低
项目初期第一次训练完,AP@0.5只有76.3%,远低于预期。开始以为是模型结构问题,换了更强的backbone依然没有明显起色,后来怀疑到数据头上。
排查过程是这样的:随机抽出200张训练图像,把标注框可视化叠加在原图上肉眼检查。结果发现问题非常集中——两株重叠的烟苗被大量标注成单框,且框的贴近度普遍偏松。回到标注规范上,我把“重叠但根茎可分”这一条重新做了图解示例附在标注手册里,要求标注员逐张严格按“根部是否可分离”来判定,并在复核阶段增加了这类的定向复查。
修改后的标注集重新训练,AP@0.5一次性从76.3%提升到88.7%。这事给我的教训是:标注标准的可执行性直接决定项目天花板,做标准时要可视化、要有示例、要定义边界情况,不能停留在文字描述层面。
6.2 小目标漏检严重时的调优策略
烟草苗在图像上属于中小目标,初版模型在GSD变大(比如无人机飞高到40米)时,漏检率显著上升。排查后发现这背后有多个因素:锚框尺寸预设不合理、小目标特征在高分辨率下被pooling层弱化、训练时的Mosaic操作对小目标不够友好。
解法的组合拳是:把输入分辨率从640提到960,让幼苗在图上占据更多像素;把Mosaic概率从0.5调到0.7,同时加入copy-paste增强(把检测出来的幼苗随机复制到背景图上);针对小目标类别单独计算损失权重,提高其在总损失中的贡献。
调整后重新训练,AP@0.75从74.6%提升到了80.2%,可以说核心收益来自输入分辨率和针对性增强。这两项调整增加的计算开销不小,但配合TensorRT部署完全在可接受范围内。
6.3 多机训练时的BatchSize与学习率scale问题
为了加快实验进度,后来我们用两台RTX 4090做了分布式训练。这里有个经典坑:Batch Size翻倍后,如果学习率不跟着调整,收敛速度和最终精度都受影响。实践上我遵循线性缩放规则——学习率按batch size的倍数同比放大。比如单机batch size 16配学习率0.01,双机batch size 32就要把学习率调整到0.02左右。
另外,分布式训练时的BatchNorm统计量同步也很关键。默认情况下每张卡独立计算BN统计量,数据分布差异大时效果不稳定。从YOLOv8开始框架默认开启了跨卡BN同步,这个开关不要关,不然验证阶段和训练阶段的BN统计差异会导致精度下降。
6.4 边缘设备推理速度与精度如何取舍
边缘设备部署时的终极矛盾是算力有限。我的取舍原则是“精度优先、速度达标即可”——出苗率识别不是自动驾驶,不需要毫秒级响应,生产决策对几秒的延迟完全无感。所以优先保证AP不低于90%,推理速度只要低于单帧图像采集间隔(约200毫秒)就达标。
这个阈值思考下来非常合理:地面站显示页面刷新率不过每秒5帧,出苗率统计不需要实时更新到毫秒级。最终在Jetson Orin上的实测结果是CPU负载25%、GPU占用50%、内存占用8GB,整体余量充足,还能同时跑后端统计任务。
7. 实操心得与扩展建议
7.1 对数据工程比模型更重要这件事的体会
整个项目跑下来,我个人最大的感受是:农业视觉项目里最值得花时间的是数据工程,不是模型调参。你花费大量精力研究复杂的模型结构、调测试不同损失函数的排列组合,效果提升可能只有一两个点;而把标注规范定清晰、把数据分布摸透、把训练集划分做严谨,这里面的收益往往是二位数级别的提升。
这次项目里,数据清洗提高了5%的召回率,标注规范化提升了12%的AP,这两个数据远远超过任何模型结构优化带来的收益。以后做相关项目,我建议一上来就把数据工程的时间和预算打足,这是平台级的基础设施投入。
7.2 数据集的扩展思路与行业复用价值
这次构建的烟草出苗率识别数据集,如果做得好,可以成为一个行业性基准数据。原因是出苗率这个任务在农业智能化里有很强的通用性——不只烟草,水稻育秧、玉米出苗、蔬菜移栽,本质上都是“密集小目标计数”,模型结构完全通用,只需把数据换成对应作物。
进一步扩展的思路有两种:一种是做多作物数据集,在现有模型基础上加类别标注,训练出一个农业通用苗情识别模型;另一种是做时间序列数据集,对同一地块连续跟踪出苗过程,训练模型学习时序趋势预测,最终输出的是“出苗率趋势曲线”而不只是单帧数值。这后一种方向对农业决策的价值高得多,但数据成本也高,需要至少一个完整种植周期的数据积累。
7.3 最后分享两个小技巧
给想复现这个项目的朋友两个实在的小技巧。
第一个是关于标注工具的。Labelme虽然开源免费,但界面交互老旧,大图标注时缩放平移卡顿明显。X-AnyLabeling内置了Segment Anything模型做半自动标注,画出目标的大致轮廓就能自动生成精确掩膜,再转成矩形框,效率提升接近三倍。如果是单人做小规模验证标注,强烈推荐这个工具。
第二个是训练集划分上的一个细节。很多开源项目不重视“按地块隔离”原则,随机划分图像会让验证指标虚高。实际上验证集应该完全独立于训练集的地块形态,最好地块参数、采集时间也分开,这样测试结果才代表“模型遇到新地的真实表现”。做出来的模型要拿去农场用吗?那就必须按这个标准来评测。
这个项目后续还能怎么扩展呢?从工程角度看,模型的迭代机制和数据的自动采集闭环已经搭好,下一季种植时农田里继续飞、持续采集新样点,模型会越来越适应这个农场的具体环境。这就是农业AI一个不可忽视的核心价值——数据的累积复利效应。希望这份实战记录能帮到正在做同类项目的朋友,少踩几个坑,少走几段弯路。