ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

AI昆虫识别Pipeline实战:从数据采集到边缘部署的完整链路

AI昆虫识别Pipeline实战:从数据采集到边缘部署的完整链路

前阵子接了一个林业病虫害防治方向的AI项目,目标很直接:用计算机视觉自动识别诱虫灯拍到的昆虫照片,替代人工看图计数,给防治决策提供数据支撑。做之前我以为重点是“训练个模型”,真正上手才发现,在野外林场部署一套能稳定运行的AI昆虫识别Pipeline,工作量的大头全在数据和工程上。这篇文章就把整条链路展开聊聊,包括采集端怎么摆、数据标注怎么定规范、模型怎么选怎么调、边缘设备怎么落地,以及上线后那些文档里不会写的坑。

1. 为什么一条完整的AI昆虫识别Pipeline比“训练个模型”更值得打磨

1.1 传统监测模式的瓶颈在哪里

林业害虫监测以前主要靠两条腿。一条是林防人员定期巡林,沿着样线看树冠、看树干、看叶片背面有没有幼虫和危害状;另一条是在林间挂诱虫灯或诱虫板,人工定时收集并计数。问题在于林区面积太大,人员又有限,巡一趟下来少说半天,等发现某片林子尺蠖爆发,往往已经过了最佳防治窗口。

智能虫情测报灯的出现解决了“采集自动化”的问题,这种设备夜间用特定波长光源诱虫,昆虫撞到撞击屏后落入收集装置,内置相机定时拍照并上传。一台灯一个晚上能拍上千张照片,几十台灯覆盖一个试点林区,每天就是几万张图。照片有了,新的瓶颈又来了:靠人把几十万张图看完。一个熟练人员一小时最多过几百张,而且连续看久了注意力必然下降,漏判错判是常态。

我在项目里见过最典型的场景:某天早上,系统回传了四千多张夜间照片,值班员一张张翻,翻到后面基本只盯着明显的大虫体看,小个体害虫比如蚜虫、叶甲根本注意不到。这不是态度问题,是人眼在这种重复性劳动里的生理极限。AI昆虫识别要解决的,就是把“每张图都看”变成“机器先筛,人只看重点”。

1.2 项目Pipeline的整体组成与边界

我们最后跑通的Pipeline大致是:诱虫灯定时拍照 → 边缘设备本地预处理与检测 → 结果和图片上传到服务端 → 服务端做时序去重与虫情计数 → 生成当日监测报告 → 一线人员复核重点图片 → 标注结果回流到训练集。这条链路里,图像采集和模型推理只是两个节点,真正决定项目成败的是数据流转和反馈闭环。

这里有个很重要但容易被忽略的边界:AI识别做的是“发现疑似目标并计数”,不是“直接给出防治结论”。防治决策还要结合虫态、数量趋势、气候条件、历史基线。所以我们把系统输出定位成“数据”,而不是“指令”。这不仅是技术边界,也是和一线使用者建立信任的基础。如果模型输出了一个离谱的识别结果又被当成指令执行,整个系统的可信度就塌了。

后面所有章节讲的细节,都是围绕这条Pipeline展开的。我把整个项目的实践经历分成采集与标注、模型训练、边缘部署、上线迭代四个部分,每一块都踩过不少坑,下面挨个说。

2. 数据管线:野外虫情照片到干净训练集的三项硬功夫

2.1 采集端:虫情测报灯、诱虫板和无人机拍的是什么

数据采集不是简单把相机架起来就完事,不同设备拍出来的照片,特征差异非常大。虫情测报灯拍的是收集盘内的昆虫俯视图,背景往往是黑色或灰色托盘,目标密集但相对好分割;诱虫板拍的是粘板上的昆虫侧面或背面图,背景是黄色或蓝色板,昆虫形态更自然但容易和板面颜色糊在一起;无人机或巡护手机拍的是叶片、枝条上的幼虫和危害状,背景极度复杂,有树皮纹理、光影、叶片遮挡。

我们项目里主要用的是虫情测报灯照片,这类照片的张数多、场景一致,适合做批量训练。但只靠灯下照片有个致命问题:灯诱到的是趋光性较强的成虫,对幼虫、地下害虫、蛀干害虫的覆盖不够。所以后来又补充了诱虫板和人工巡拍照片,把类别覆盖补上。采集时要刻意控制拍摄策略:相机固定高度、固定焦距、固定光照,最好让一只中等大小的昆虫在图像中占到至少40×40像素以上,太小的话后续检测会很难受,这个经验和很多做智慧农业图像项目的朋友是相似的。

这里建议从一开始就按“设备+点位+时间”的目录结构存储照片。我们早期没在意这个,结果后面做数据划分时发现同一场景的相似照片被同时分到训练集和验证集,指标虚高得一塌糊涂。规范命名的好处在数据清洗和模型评估阶段会成倍还回来。

2.2 清洗与去重:筛掉无效帧的三个规则

野外照片的无效帧比例远超想象。灯罩被露水糊住、夜间补光灯没开、虫子爬出画面只留半个残影、飞蛾扑棱导致运动模糊,这些都占有效拍摄量的不少比例。我们第一版训练集直接拿原始照片标注,模型在测试集上表现很惨,后来才发现是脏数据把模型带偏了。

清洗阶段我总结出三个最实用的筛除规则。第一个是清晰度检测,计算拉普拉斯算子方差,低于阈值的模糊帧直接丢弃;第二个是曝光检测,统计灰度直方图,过曝或纯黑画面剔除;第三个是相似帧去重,虫情灯每十分钟拍一张,很多连续帧里昆虫几乎没有位移,背景完全一样,用感知哈希去重后能把数据量压缩掉不少。三条规则跑完,大概筛掉了将近三成的照片。

有同事问过:为什么不像目标检测数据集那样直接全量标注,让模型自己适应模糊帧?我当时的回答是:模型确实有一定抗模糊能力,但训练数据的噪声比例一旦超过某个量,模型就会学会把“模糊”本身当成一种特征,尤其是夜间低光照情况下,虚影很容易被误识别成小个体害虫。与其让模型在脏数据里挣扎,不如把数据洗干净,标注人力也要花在刀刃上。

2.3 标注规范:矩形框、遮挡、相似物种的边界怎么定

数据清洗之后是标注,这个环节决定模型能力的上限。我们没有一开始就定死规范,结果第一批一万张图标出来,五个标注员对同一个“天牛到底是框身体还是框触角”的理解都不一样。后来专门开会把规范细化,才把质量拉回来。

我们最终确定了几条规则。第一,采用矩形框检测标注,不用分割标注,因为业务核心是计数和定位,分割成本高且对计数没有帮助。第二,目标至少达到一定像素尺寸才标,小于该尺寸的作为忽略区域处理,避免标注员在模糊小目标上浪费精力。第三,昆虫被遮挡超过一半时标成“遮挡”类别,不硬猜具体物种。第四,对相似物种做业务级合并,比如好几种外形接近的蛀干天牛,对防治来说危害类似,识别到“蛀干类天牛”这一层就够用,不需要人为制造难以区分的类间差异。

特别是第四条,很多做识别项目的人容易犯强迫症,想区分到“种”,结果类别间差异极小,标注员自己都拿不准,模型更学不会。工业项目要的是稳定可用,不是分类学专著。我们最初列了二十多个物种,最后合并成十二个业务类别,模型训练难度明显下降,用户反馈反而更好。

2.4 数据增强与类别平衡:不靠复制硬凑样本

十二个类别里,成虫数量严重不平衡。松毛虫成虫趋光性强,灯下一晚上能拍到上千只;某些小蛾类一整个采集周期可能只有几百只。直接用原始分布训练,模型会对头部类别过拟合,尾部类别基本学不会。

类别平衡的常规操作是过采样和变换增强。头尾比例超过几十倍的类别,光靠旋转、翻转、调色不够,我们用了两类思路。一是“场景粘贴”,把尾部类别的昆虫实例裁剪出来,随机粘贴到空白的虫情板背景上,模拟不同位置和密度,这种方式比单纯copy-paste更贴近真实采集场景;二是“实例混合”,把两个样本叠加再训练,增加模型对遮挡和重叠的鲁棒性。

有人说这类增强是“伪造数据”,我理解这个顾虑,但我的经验是:只要粘贴样本在物理上合理,比如光照方向、阴影、透视关系一致,并且验证集只保留真实采集图片,模型学到的就不是噪声,而是“尾巴类别在这个拍摄条件下长什么样”的分布。生成式合成样本在冷启动阶段也可以用来做小类目的预训练,但正式交付前必须以真实样本验证为准。

3. 模型训练:小目标、相似物种、样本不均是害虫识别的真正难题

3.1 模型选型:为什么在边缘约束下选择轻量级检测器

项目初期我们做过一次技术选型对比,把大型视觉模型和轻量级目标检测模型都纳入了候选。大型模型的定位能力强,在公开数据集上有漂亮的表现,但实际推到林间设备上就露馅了:几十瓦以上的功耗、数百毫秒以上的单帧时延、对显存的要求,放在太阳能供电和低功耗工控板上完全不可接受。轻量级检测器虽然在通用大模型评测上未必占优,但针对特定业务场景微调后,完全够用。

我当时选模型的判断依据有三个:端侧算力能不能跑实时或准实时、模型体积能不能塞进板卡内存、小目标召回能不能通过架构和训练调整提升。围绕这三个约束,我们在这类轻量级检测器上做了大量实验。它属于典型的anchor-free检测框架,对小目标的特征融合比旧一代结构更友好,同时也有足够成熟的部署生态。

方案算力依赖单帧时延(边缘端)小目标表现部署复杂度适用场景
大型视觉模型高,需GPU服务器数百毫秒级依赖大图输入高,设备难承载服务器端离线分析
轻量级检测器低,可用NPU板卡几十毫秒级需针对性调优低,成熟工具链林间边缘设备实时识别

结论很明确:我们这类几十台设备、每台每天上千张图、还要在弱网环境本地推理的项目,只能选后者。技术选型不是越强越好,是在资源约束下做出取舍。

3.2 小目标检测:提高输入分辨率治标不治本

虫情灯照片里的昆虫个体通常很小。一张分辨率接近千万像素的照片里,很多害虫可能只占几十个像素,直接下采样到标准输入尺寸后目标信息损失严重。最直觉的解决办法是提高输入分辨率,但分辨率翻倍,计算量呈指数上升,边缘设备根本跑不动。

我们的解法是“两段式检测”,思路和切片辅助推理类似。第一步,先跑一个轻量的区域检测模型,找到托盘或诱虫板的主体区域;第二步,只对板面区域做切片推理,把每个切片送到识别模型里检测昆虫。这样既保留了原始图像的细节,又避免了整张图超高分辨率推理的计算压力。实际推理时,B/S两段协同,单台设备处理一整日采集图片的时间压缩到了可接受范围。

另一个有效手段是给检测器增加浅层特征输出,也就是通常说的P2层。浅层特征图分辨率更高,对小目标的位置信息保留更好。代价是计算量和内存占用小幅上升,但换来的是小目标召回率的明显提升。我们上线版本里用“主干+浅层输出”的组合,配合多尺度训练,松毛虫成虫这类的召回率比基础配置提升了可观的幅度。

3.3 损失函数与训练细节:召回优先的业务怎么调

病虫害监测业务里“漏检”和“误检”的代价是不对称的。漏掉一只已经发生的害虫,可能导致防治窗口错失;多报一次误警,顶多让巡护人员多跑一趟。所以我们把训练目标定为“在不至于淹没人工复核的前提下,尽可能提高召回”。

针对这个目标,我们做了几件事。第一,损失函数调整为Focal Loss,参数按经验设置,缓解正负样本极度不平衡的问题;第二,给分类分支加标签平滑,避免模型对相似物种的预测过于自信,影响阈值调节;第三,训练阶段采用多尺度输入,让模型适应不同相机距离带来的尺度变化;第四,数据划分按“设备”而不是“随机”,保证同一台灯的照片不会同时出现在训练和验证集里,这个细节很多人会忽略,但对指标真实性影响巨大。

训练过程中我们还记录了一个有趣的现象:提升召回最有效的操作不是改损失函数,而是把输入分辨率适当增加并且加入浅层输出。这两个改动对mAP@0.5的提升比换任何Backbone都明显。这也印证了在特定域的图像任务里,架构和输入分辨率往往比玄学调参更有价值。

3.4 评估指标:mAP之外还要看业务指标

模型在验证集上mAP到了预期值,不代表系统能上线。mAP是算法层面的指标,业务层面还要跟踪另外几个数字:每台设备每天的有效检测次数、人工复核列表里的错检率、与历史基线相比的异常波动。

举个例子,mAP@0.5很高,可能只是因为其中两个头部类别贡献了大量真阳性,而尾部小蛾类完全不识别。只看均值评估会掩盖这个问题。所以我们在评估阶段分两个维度:一是各个类别的AP单独看,二是给业务人员看“上报总数准确率”而不是“识别框打得好不好”。后者直接决定他们愿不愿意用这个系统。

实际操作上,我们给每个类别设定独立置信度阈值。松毛虫这类头部类别阈值可以高一些,减少复核负担;小类目阈值放低,宁可多推几张让复核员判断。这种“按类别调阈值”的方式比全局统一阈值好用得多,也是我强烈建议做检测项目的人都试一试的工程手段。

4. 部署落地:把识别能力塞进太阳能供电的林间设备的工程细节

4.1 轻量化压缩:量化、剪枝与蒸馏的取舍

算法模型训练完成只是第一步,能不能在野外设备的板卡上跑起来是另一回事。我们目标设备是带NPU的低功耗边缘板卡,整机功耗受太阳能供电约束,内存也不大。模型文件直接塞进去能跑,但很勉强,推理时延会拖累整晚图片的处理节奏。

轻量化我们按顺序做了三轮。第一轮是结构化剪枝,把冗余通道裁掉,模型体积缩小明显;第二轮是蒸馏,用未剪枝的大模型当老师,把小模型的输出往老师那边拉,把剪枝掉的效果补回来一点;第三轮是INT8量化,用几百张代表性图片做校准,替换原有的FP32权重。三轮做完,模型体积相比原始版本压缩了大半,推理速度提升明显,精度只掉了一个多点。

量化是这里面最值得讲的。它不太敏感数据分布,但校准集一定要覆盖夜间开灯、夜间补光、白天自然光等典型场景。我们第一版量化就是只用白天照片做校准,导致夜间推理结果很差,后来把校准集按场景分层采样才算稳定。另外,不是所有板卡的NPU都支持任意算子量化,遇到不支持的算子要提前在模型里替换或规避,这个要在选型阶段就调研清楚。

4.2 边缘端预处理与后处理:阈值不是一拍脑袋定的

部署时最容易翻车的其实不是模型本身,而是预处理和后处理。虫情灯照片里有大量环境干扰,白天强光直射托盘、夜间补光灯带来的偏色、红外成像和可见光成像切换造成的色调差异,这些都会让推理输入分布和训练时不一致。

我们的预处理环节加了白平衡校正和亮度归一化,在设备端完成,服务端只接收处理后的结果和原图。后处理环节有两个经验值得说。第一是置信度阈值要分场景调整,夜间照片的成像质量和白天不同,我们分别调了一套参数,而不是全系统一个阈值。第二是加类别互斥逻辑,比如同一检测框不可能同时是两种成虫,利用先验知识把互相矛盾的预测压掉,能减少不少低置信度误报。

还有一个很关键的后处理是时序重复抑制。虫情灯每隔十分钟拍一张,同一只虫子只要没爬走,会被拍进连续好几张照片,如果每张都计数,虫情数据会指数级膨胀。我们给每台设备维护了一个短时间窗口的目标跟踪缓冲,通过IoU匹配判断检测框是不是之前出现过的目标,匹配上了就不重复计数,只在当前帧重新确认状态。这个机制上线后,上报数量直接从夸大走向合理,和人工抽查结果接近了。

4.3 断网弱网场景:本地推理与任务队列

林区网络条件比城市差很多,4G信号时断时续,偶尔直接离线几天。如果系统设计成“拍完照必须传云端分析”,那断网时段就是监控盲区,这是不可接受的。我们最后确定的原则是:推理必须在设备端完成,云端只做汇总和分析。

具体做法是设备端按固定节奏抓拍并本地推理,推理结果连同原图先写入本地任务队列,再按网络状态批量上传。网络断开时队列持续堆积,网络恢复后按顺序补传。队列要支持断点续传,防止设备重启丢数据。我们用的是本地数据库存任务状态,简单可靠,不用引额外的队列中间件。

这里还有个容易被忽略的点:设备白天要做识别,晚上也要工作,太阳能板供电能力有限,夜间补光灯和板卡全速跑是耗电大户。所以我们给推理流程做了任务优先级,拍摄高峰期优先处理,低峰期把队列里的历史任务慢慢清掉,总之不能让设备因电量耗尽在关键时段停机。实际运行下来,这个设计比一味提高模型算力更管用。

4.4 硬件环境与数据漂移:设备老化、温湿度变化怎么应对

部署上线后,模型面对的已经不是测试集里的“干净照片”了。太阳能供电电压波动会让相机曝光参数悄悄变化,镜头结露会让图片发雾,补光LED老化会让整个画面偏黄。这些都属于数据漂移,不处理的话,再好的模型也会慢慢变钝。

我们当时做了两件防护。第一,设备端每天回传图片的亮度直方图、模糊度得分等统计信息,服务端监控这些指标,一旦发现系统性偏移就触发运维告警,让维护人员去现场清洁镜头、检查补光灯。第二,模型端每周从新回传照片中抽样评测,和上版指标对比,如果某个类别的AP掉得太多,就把新场景数据加入训练集重新微调。这套机制让模型在运行几个月后依然保持稳定识别能力。

顺带说一句,模型更新本身也要谨慎。我们规定新版本必须先在模拟环境中跑完回归测试,再推送到试点设备。之前有过一次新版本在验证集上表现更好,但推上去后夜间误报暴增的例子,原因就是新增的训练样本大部分是白天照片,把夜间分布带偏了。这类问题不靠流程卡住,靠人盯是盯不住的。

5. 上线后的问题:误报治理、人工复核闭环与一线信任

5.1 误报的真实来源:不止是模型的问题

系统刚上线那阵子,一线反馈最集中的就是“怎么净瞎报警”。打开误报图片细看,真凶大多跟模型能力没关系。蜘蛛网在夜间补光下会形成一圈圈高光结构,被模型当成虫体;粘板上残留的胶迹、枯枝碎屑、灯罩上的水滴折射,都会生成一小片类似昆虫的纹理。

我们把各种误报截出来做了个归类,大概分成设备类、环境类和语义类。设备类是镜头脏、过曝、失焦;环境类是水滴、蛛网、植物碎屑;语义类才是模型真正把不该识别的东西识别成了昆虫。每一类处理的思路都不一样,不能都靠“调高置信度阈值”解决。

像蛛网和碎屑这类,后来我们用了一个很土但有效的办法:叠加背景差分。因为虫情灯拍摄位置固定,背景托盘相对静态,如果检测框区域在连续多帧里没有变化,很可能是背景纹理而不是活虫。这个简单逻辑把夜间误报率压下去一大截,比调模型参数还见效。遇到问题先分析数据,再决定是改代码还是改模型,是我在这个项目里最大的体会之一。

5.2 人工复核回流:模型迭代的日常机制

模型上线后的迭代,光靠算法团队自己闭门造车是不行的。我们把一线人员的日常工作设计成“复核回路”:每天早晨,系统推送当天的高价值图片列表,复核员只需在界面上点“确认”或“误报”,一分钟能过几十张;这些确认结果自动回流到待标注池,定期清洗后进入训练集。

这套回流机制跑起来后,模型每个月都在变好。第一个月系统误报还比较多,复核员要花不少时间;两三个月后,高频误报在难例挖掘里被反复清洗和重训,复核负担明显降低。让我意外的是,复核员最终会把系统当成“第一道筛子”,而不是“只会报错的机器”。这个信任转变,是整个项目能持续运转的关键。

这里有一个值得说的细节:回流样本要有明确的优先级标签,比如“高置信误报”“低置信漏检”“跨类别混淆”。如果只是把一堆标注数据丢进训练集,不区分样本价值,模型提升效率会很低。难例挖掘的优先顺序决定了每次微调的边际收益。

5.3 让一线人员信任输出:给建议而不是给概率

技术团队习惯把模型输出描述成“某某类别置信度95%”,但一线林防人员要的不是这个。他们关心的是“今天要不要去XX号灯看看”“比往年同期是不是多了很多”“松毛虫是不是在爆发的临界点”。置信度是对算法本身的描述,不是对业务的回答。

所以我们把展示层彻底改掉了。每天早上的报告不再显示一堆识别框和置信度数字,而是输出三句话:今日监测到的各类虫量是多少、与最近七日基线相比是否有明显上升、建议优先关注的灯号和现场照片。这些内容由服务端根据检测结果和历史统计数据自动生成。置信度只在后台保留,作为人工复核的辅助信息。

说起来简单,这个改动却花了不少时间去推敲措辞。比如“疑似爆发”这种词就不能乱用,你得给一个基于历史数据基线的客观描述。系统输出的是一张“体检单”,医生还是植保专家。界限划清楚了,一线人员才不会把系统的判断当成唯一依据,也不会因为一次误报就把整台设备弃用。

5.4 定期回归测试:防止修了一个类别坏了一片效果

模型迭代版本多了以后,最怕的是“修好了一个类别,带崩了另一个类别”。我见过太多项目死于这类回归事故。为了防这个问题,我们维护了两套评测集:一套是包含所有类别的代表性样本全集,固定不变,每次迭代都跑;另一套是每个月新增的最近一个月真实采集样本,专门用来验证模型能不能跟上新数据分布。

每次发版前,新模型先和旧模型在固定回归集上对比。任何类别的AP掉了一个点以上,就阻断发布,先查清原因再说。月度新增样本集如果出现整体性能下降,说明采集环境发生了变化,模型训练数据也需要跟着调整。这两套评测集就是模型的“红绿灯”,把发版这件事从“感觉没问题”变成“有依据的确认”。

回归测试的自动化程度越高,模型迭代频率才能越快。我们后来把评测脚本接进了发版流程,新版本训练完自动出报告,冲突点一眼能看出来,发布时间从两三天压缩到几小时。这个投入非常值。

最后说点个人感受。这个项目让我对“AI落地”的理解变了:模型训练只是Pipeline上的一环,数据怎么来、怎么清洗、怎么标注、怎么部署、怎么让人愿意用,这些环节里的坑比模型本身多得多。你在实验环境里刷到好看的指标,往往不是终点;把模型塞进偏远的林间设备,让它稳定跑上百天,才是真正的项目管理功底。如果这篇分享对正在做类似智慧农业、林业监测项目的朋友有一点帮助,我就很满足了。

RELATED READING

延伸阅读

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