小麦入口的东西,品质把关从来都是大事。我在某农机装备相关的模拟项目中做过一版小麦杂质检测方案,从传统图像处理做到深度学习,最后落到YOLOv11+BiFPN这套组合上。这个项目解决的核心问题很具体:如何在输送带高速运动、小麦颗粒密集堆叠的场景下,实时把霉变粒、虫蚀粒、破损粒和混入的沙子、石子、秸秆碎片、草籽这些杂质从正常小麦中准确分离出来。农业质检场景里,精度和速度都得看,而且模型要能跑在普通工控机上,不能指望机房里的高端显卡。这篇文章就把整套方案的思路、改网络、调参数和踩坑过程完整记录下来。
我先说结论:把YOLOv11默认的Neck换成BiFPN之后,在自建的小麦杂质数据集上,mAP@0.5从0.891提升到了0.934,最难检的霉变粒这一类涨了大概7个百分点,而且推理速度基本没损失。下面拆开讲。
1. 项目背景与整体思路
1.1 小麦杂质检测为什么难做
小麦杂质检测不是新题目。传统的粮食质检实验室里,人工用扦样器取样,然后铺在白纸上用小镊子挑杂质,一个人一天最多处理几十份样品,效率完全跟不上收购季节的节奏。后来出现了振动筛、风选机和比重分选机,这些设备能去掉大颗粒异物,但对霉变粒、虫蚀粒这类"看起来还像麦粒"的杂质基本无能为力。色选机靠颜色分离能解决一部分问题,可在光线变化大、麦粒表面有灰尘的情况下,误杀率很高。
这个场景对算法真正的挑战在于三点。第一,目标密集,一张640x640的图里正常麦粒可能有几百上千颗,杂质往往只有几颗到几十颗,正负样本极度不平衡。第二,目标尺度小,霉变粒和正常麦粒大小几乎一致,可能只有十几个像素到几十个像素,属于典型的小目标检测。第三,外观相似度高,早期霉变的小麦粒在RGB图像上和正常麦粒的颜色差异非常微弱,有时候连人都需要凑近仔细看才能分辨。
用传统图像处理的方案,比如阈值分割加形态学,只能处理"严重霉变发黑"这类极端情况,一旦遇到颜色过渡阶段的轻微霉变粒,特征就彻底失效。所以整个项目很快就转向了深度学习目标检测路线,确切地说,落到了YOLO系列上。
1.2 为什么选择YOLOv11+BiFPN的组合
选YOLOv11而不是其他检测框架,原因其实很实际。这个系列到了v11版本,项目生态已经非常完整,训练、导出、量化、部署的链路都是通的,对工程落地友好。更重要的是,v11的backbone在v8的基础上做了进一步优化,用C3k2模块替代部分C2f,还引入了C2PSA模块,在保持轻量化的同时增强了特征提取能力。对杂质检测这种需要兼顾速度和精度的场景,YOLOv11的默认结构已经是个不错的起点。
但默认结构有一个明显的短板:Neck部分用的还是PANet(路径聚合网络)的思路,特征是自顶向下和自底向上的双向传递,但每一层的融合权重是固定的,简单说就是"平等地融合所有尺度的特征"。在小麦杂质检测里,不同杂质的语义层级差异很大——霉变粒靠的是细微的颜色纹理,属于底层细节;石块砂砾靠的是形状,属于中层语义;而草籽秸秆这类异物,部分特征要到高层特征图才明显。固定权重的特征融合方式,很难在这么多差异化的特征之间找到一个最优平衡。
BiFPN(双向特征金字塔网络,Bidirectional Feature Pyramid Network)恰好解决这个问题。它做了三件事:把只有单个输入边的节点删除,减少计算量;增加了同一层级的横向跳跃连接,让高层语义和低层细节有更多交互;最关键的是,每一条融合路径都带一个可学习的权重系数,网络在训练过程中自己学会该重点依赖哪些层级的特征。把这些机制移植到YOLOv11的Neck里,相当于让"特征融合"这件事有了自适应能力。
这里要补充说明一下,项目里不是把整个EfficientDet的BiFPN照搬过来,那样反而会破坏YOLO原本的训练稳定性。实际操作是保留YOLOv11的backbone和检测头,只把Neck层的特征拼接逻辑改成带权重系数的双向融合形式,属于一种"取中间精髓"的嫁接方案。
2. 数据集构建与预处理
2.1 图像采集与样本标注
数据是这类项目的命门。我最初拿到的一批数据是某实验室提供的静态拍摄图片,把小麦摊在黑色绒布上,用工业相机俯拍。这批数据质量很好,但数量只有两千多张,而且都是单一背景、单一光照条件。模型在上面训练出来,一到现场的输送带环境就明显掉点。
所以后来我自己搭了一套采集装置:用工业面阵相机固定在输送带正上方,加了一组白色LED光源,用接近45度的角度打光,尽量避免麦粒表面的镜面反射。同时做了两个关键设计:一是让输送带以固定速度运行,相机采用连续拍摄模式,模拟实时检测的帧率;二是在采集样本时人为投入不同比例和不同尺寸的杂质颗粒,覆盖从单粒杂质到混杂一堆杂质的各种情况。
标注类别上,我把杂质分成四大类:霉变粒、虫蚀粒、破损粒、异物。前两类是"内部杂物",和麦粒尺寸相近,是最难检测的;第三类破损粒包括半粒麦和被压碎的麦粒;异物类包含沙粒、小石子、秸秆碎片、草籽和个别塑料片。每张图片平均标注目标在30到80个之间,最终自建数据集总计5800多张图,标注框数量接近26万个。
2.2 标注规范与质量把控
标注质量直接决定模型上限,这一点再怎么强调都不过分。在标注环节,我定了三条硬性规则。
第一,遮挡目标只要可见面积超过1/3就必须标。麦粒堆叠严重,如果一个目标完全被其他麦粒盖住,那本来人眼也看不见,把它标出来反而会给模型传递错误信号。但在边缘露出半个的,就一定标,因为这正好是模型学习"从密集堆叠中找出小目标"的关键样本。
第二,霉变粒的判断标准要统一。霉变是一个连续变化过程,我要求标注员只标"肉眼一眼能看出异常"的麦粒,处于模糊边界的宁可不标。原因很简单,模糊边界样本会让模型的置信度输出变得混乱,后面改阈值的时候很麻烦。这条规则虽然损失了一部分模糊样本,但换来的是模型输出的稳定性。
第三,叶片碎片和草籽这种容易混淆的异物,在标签上允许"近似归类"。这个判断基于现场实践的考量:收购站关心的是"有几个异物",并不会细分到草籽还是秸秆。如果强行细分,反而会因为两种目标外观重叠严重导致标签噪声。
标注工作完成后,我又做了两轮交叉复查,重点检查小目标有没有漏标,以及异性目标有没有标串类。实际跑下来,这样一轮人工复盘大概优化了3%到5%的标注置信度,回报相当值得。
2.3 数据增强策略
数据集规模摆在那里,数据增强是必须用足的环节。我这边采用的增强组合是Mosaic、MixUp和Copy-Paste配合使用。
Mosaic增强在YOLO训练里是标配,把四张图拼接成一张,让模型学会在更复杂背景中找到目标。但Mosaic有个副作用,它会显著改变小目标的分布,因为拼接时目标被缩小了。所以我在训练时把Mosaic概率设置为0.8,并且在最后20个epoch把这个概率逐步降到0。这个"退火"操作在YOLO社区里已经是公开经验,我也实测了确实能稳定提升mAP。
Copy-Paste增强是我这次特别加上去的,做法是从其他图片中切出真实的杂质目标,随机粘贴到当前图片的小麦区域中。这种增强对杂质检测格外有效,因为它直接增加了每一类杂质的目标数量,尤其是把霉变粒这种标注数量相对少的类别的目标数放大,缓解类别不均衡问题。
另外还在HSV颜色空间做了轻度扰动,H偏移0.015、S偏移0.5、V偏移0.4,主要是模拟现场灯光变化。亮度扰动不敢调太大,因为霉变粒检测恰恰依赖颜色信息,颜色失真太严重就等于把区分特征抹掉了。
3. YOLOv11核心机制与BiFPN融合原理
3.1 看懂YOLOv11的特征提取骨架
在改网络之前,得先明白YOLOv11默认是怎么工作的。YOLOv11把整张图送进backbone,经过一系列卷积和C3k2模块逐层提取特征,然后在不同的层级输出三种不同分辨率的特征图,分别对应小型目标、中型目标和大型目标的检测。
v11和v8相比,在backbone里有一个重要变化:用C3k2替换了C2f。C2f原本是v8引入的结构,它把特征分成多个分支并行处理再融合,参数效率很高。v11的C3k2相当于在C2f里引入了更灵活的内核尺寸选择,部分阶段还可以配合注意力机制。另一个值得注意的点是C2PSA模块,它把位置注意力机制直接嵌入到了特征提取通道中,让网络在下采样过程中就能保留位置敏感性。
这些改进对杂质检测的影响很实际。小麦颗粒排列紧密,目标之间存在大量重叠和遮挡,位置敏感性是定位精度的关键。霉变粒和正常麦粒的纹理差异可能只有几个像素,C2PSA的注意力机制放大了这种微小差异在高层特征中的表达。从我自己跑实验的情况看,把同样的数据分别用v8和v11训练,v11在霉变粒这一类上的Recall有大约3%的提升,这也侧面说明backbone确实强了。
3.2 BiFPN的特征融合思想
YOLO的Neck部分(v8/v11默认是PANet结构)承担着把backbone输出的多层特征进行融合的任务。默认的PANet是两条路径:自顶向下路径把高层的语义信息传到低层,帮助低层特征"知道自己在找什么类型的物体";自底向上路径把底层的细节信息传到高层,帮助高层特征"看得清物体边缘纹理"。两条路径在一个通道汇合后,就得到了同时具备语义和细节的融合特征。
问题在于,YOLO的这个融合过程对每一条输入边、每一个特征层级用的都是预设权重,不会根据数据分布自动调整。比如,草籽这类小目标可能更需要低层高分辨率特征,但在这个固定权重体系下,高层特征也在强行参与融合,反而引入了噪声。
BiFPN的做法简单说就是给特征融合加杠杆。来自不同层级的特征,在相加之前先乘以一个可学习的权重,权重的初始值可以在某个范围内设置,训练过程中网络会自己调整每个权重的数值。这样一来,如果模型发现霉变粒的检测主要依赖低层纹理特征,那它自然会把低层特征的融合权重调高,把其他层的权重压低。
另外BiFPN额外加了一条路径:在自顶向下和自底向上两条干路之外,增加了从原输入层到融合输出层的横向跳跃连接。这等于让浅层特征保留了一条"原始通道",避免信息经过多层传递后衰减太多。对小麦这种细粒度差异目标,这种信息保真机制是有价值的。
用一句话总结,BiFPN的特征融合发生在网络内部,但每次融合都带着"当前特征对最终检测重要度"的可学习权重,这就是它优于PANet的本质原因。
3.3 在YOLOv11里嫁接BiFPN的实操方案
接下来是最关键的嫁接环节。YOLOv11的模型定义在官方仓库里是以yaml配置文件加Python模块的形式组织的。backbone输出三个特征图,分别是P3、P4、P5,分辨率依次为原图的1/8、1/16、1/32,后续Neck操作就是围绕这三个尺度展开。
我的改造思路是:backbone结构不动,检测头不动,只重写Neck部分的特征融合逻辑。具体来说,默认Neck依次是上采样P5并与P4拼接、再上采样P4并与P3拼接,得到两组融合特征;然后从P3层开始依次下采样,重新与之前融合的特征拼接。我在每一处add或concat操作之前,插入一组可学习的通道权重,整个融合过程变成加权融合。
用公式描述BiFPN的一个核心计算节点:新的融合特征等于w1乘上一层输出,加上w2乘当前层级输入,加上w3乘跳跃连接输入,三个权重都经过归一化处理。归一化用的是最简单可靠的方案,每个权重除以所有权重之和,避免权重数值训练过程中出现爆炸。实操里我用了三个一维可学习参数,初始化时先保证所有路径的初始权重相等,这样在训练刚开始时相当于一个均衡的PANet,网络不会因为权重突变而震荡。
我把这个模块定义为BiFPN_Add,然后把它插入到Neck的对应位置。这里要特别提醒一点:主干网络输出的stride和通道数必须严格匹配,YOLOv11的backbone在P4、P5层输出的通道数默认都是256和512,如果改了backbone的宽度系数,那BiFPN的通道也要同步调整,否则会直接报通道不匹配的错。
另外还有一个容易被忽视的细节:BiFPN的横向跳跃连接在特征图分辨率不同的情况下需要先对齐。我在实际实现里通过1x1卷积加双线性上采样来对齐分辨率,没有引入转置卷积,因为转置卷积在小目标任务上容易出现棋盘伪影。
4. 环境搭建与训练实操
4.1 软硬件环境与初始配置
这套方案对硬件的要求并不夸张。训练阶段我用了一张单卡GPU,显存24G,batch size设到16,输入分辨率640x640,训练大约200个epoch,耗时约十个小时。如果显存只有12G,batch size减半到8也能跑,但BN层的统计会稍微不稳定,建议同步把学习率也降一半。
软件环境方面,Python版本要求3.10以上,PyTorch版本不低于2.0。这里有一个容易踩的坑:官方仓库在编译部分自定义算子时需要匹配特定的CUDA版本,如果CUDA版本不对,直接运行会报找不到so文件的错误。我这边最终的组合是CUDA 12.1加PyTorch 2.1,编译无障碍,供参考。装依赖不要漏了yaml、opencv-python、tensorboard、onnxruntime这几个常用的库,export模型时也用得上。
4.2 修改配置文件与网络结构
先说一个实用技巧:在动手改代码之前,先用官方默认的yolov11模型跑通一遍全流程,确认环境没问题,然后再改Neck结构。这样后面如果出现奇怪的问题,至少能确定不是环境造成的。
改网络结构的文件一般有两个。第一个是模型配置yaml文件,需要把Neck部分对应引用改为BiFPN模块。第二个是Python模型定义文件,要增加BiFPN_Add模块和对应的forward逻辑。我建议把BiFPN相关代码单独放在一个文件中,然后在模型文件里import进来,这样改动最小,后面回滚也方便。
关键代码片段大致是这样一个流程:先对backbone输出的P3、P4、P5做1x1卷积统一通道,然后按照BiFPN路径逐层做加权融合,融合结果再输入给下一层。要注意的是,YOLOv11的检测头期望接收的输入通道数要和Neck输出通道数一致,默认检测头的输入分别为128、256、512(对应三个scale),如果改了通道,检测头也要同步。为了改动最小化,我保留了默认通道数,只改融合逻辑。
训练数据的配置在另一个yaml文件里维护,格式照搬官方coco数据集的写法,写上train、val路径和类别名字列表。我这里四个类别的顺序是:霉变粒、虫蚀粒、破损粒、异物。这个顺序会在输出结果里固定下来,后面写推理代码读类别名的时候要和这里保持一致,否则类别名会错位,这是一个非常低级的坑,我在项目初期就踩过一次。
4.3 训练参数推导与细节调优
参数设计上,我遵循了几个在目标检测圈里比较成熟的默认值,再结合自己的数据集做了调整。
初始学习率设置为0.01,优化器用SGD,momentum为0.937,weight decay为0.0005。为什么不用AdamW?这类农业检测数据规模不算特别大,SGD配合warmup在YOLO系列上已经验证了稳定性和泛化性。AdamW跑得快,但后期容易过拟合,对小目标recall提升有限。如果确实想用AdamW,可以把学习率降到0.001,其他参数不变,也能收敛,但mAP通常会低1到2个点。
学习率调度用的是cosine退火,配合前3个epoch的warmup。warmup的用处是让模型在训练初期不用面对过大的梯度更新,尤其是BN层的统计量需要一个稳定的启动过程。我试过不设warmup直接开跑,前十几个epoch的loss曲线波动明显更剧烈,最终mAP反而低了两个点左右。
epoch数我取120作为基准,但因为数据增强导致的训练时间变长,实际设了200。判断收敛的标准不是固定的epoch数,而是看验证集mAP是否在连续20个epoch内不再上升。如果上升,就继续;如果开始震荡了,说明该停止了。用这个标准,我的实验基本在第160到180个epoch之间达到最优。
输入分辨率选择640。也试过1280,确实让mAP涨了约1.5个点,但推理速度慢了将近三倍。考虑到现场需要实时检测,速度收益远大于精度收益,最终选择了640。
4.4 训练过程中的关键观测
训练中途我会同时盯两个东西,一个是loss曲线,另一个是每一类别的PR曲线。前者看整体是否收敛,后者看具体类别的困境。
最值得关注的现象是:如果霉变粒这一类别的precision和recall始终低于其他类别,大概率是这类目标的数量不够多,或者标注目标过小导致正样本不足。我当时的处理办法是加大Copy-Paste增强的概率,并手动挑选500张霉变粒相对集中的图像做了过采样,让每个epoch里霉变粒样本的占比从原来的12%提高到20%。这个操作让霉变粒的Recall提高了大约5个百分点,效果非常直接。
还有一个训练阶段必须提到的细节:Mosaic增强会让部分目标在拼接接缝处被截断,导致框的位置不准确。YOLO官方实现里处理这种情况的办法是忽略被截断超过一定比例的目标,通常这个阈值设为0.1。但我在杂质检测场景里把它调到了0.2,因为麦粒本身很小,被截断的框即使比例大一些,也仍然包含了足够多可用于学习的视觉信息。实测在NMS后能略微提升小目标的召回,且没发现引入明显误检。
5. 实验结果分析与性能对比
5.1 评价指标与验证方法
目标检测任务的性能评估主要看mAP,具体分成mAP@0.5和mAP@0.5:0.95两档。前者是IoU阈值为0.5时的平均精度,数值通常较高,更贴近"检测出目标"这种粗粒度判断;后者是从0.5到0.95每隔0.05取一个阈值,再取平均值,更严格,也更考验定位精度。在小麦杂质检测里,我用的是mAP@0.5:0.95作为主指标,因为这个项目里很多目标只有十几个像素,定位框稍微偏移就有可能错过真正的杂质区域,对定位精度的要求确实高。
验证方式上,我把自建数据集按9:1划分训练集和验证集,确保两种数据集都覆盖四类杂质,并且验证集里包含一段连续拍摄的输送带图像序列。用连续序列做验证有一个额外的好处:可以观察同一个麦粒在帧间检测结果的稳定性,减少"单帧能检,多帧抖动"的问题。
5.2 对比实验数据
我在相同数据集、相同训练参数和相同epoch数下跑了一组对比实验,目的是验证BiFPN带来的增益是否来自结构改进,而不是其他随机因素。
| 模型配置 | Params | GFLOPs | mAP@0.5 | mAP@0.5:0.95 | 帧率(FPS) |
|---|---|---|---|---|---|
| YOLOv11s | 9.4M | 21.5 | 0.891 | 0.732 | 63 |
| YOLOv11s+BiFPN | 10.1M | 22.8 | 0.934 | 0.771 | 58 |
| YOLOv11m | 20.1M | 67.6 | 0.915 | 0.758 | 41 |
| YOLOv11m+BiFPN | 21.6M | 70.1 | 0.947 | 0.789 | 37 |
数据说明三个问题。第一,加了BiFPN之后,mAP@0.5:0.95有明显提升,说明自适应权重融合确实增强了模型在复杂场景下的定位能力。第二,参数量和计算量增加很少,s版本只增加了约0.7M参数,这在工程上几乎可以忽略。第三,推理速度损失不大,s版本从63帧降到58帧,对于实际场景里30帧的要求完全够用。
分类别看,提升最大的单项出现在霉变粒上,mAP@0.5从0.82提升到了0.89,原因也很直观:霉变粒的颜色纹理是典型的细节特征,BiFPN的加权融合让低层细节特征获得了更大的融合权重,模型对这类细节特征的敏感度自然就提上去了。异物的提升则相对小,因为异物特征在多个层级都有明显表达,固定权重本来就够用。
5.3 典型检测案例分析
我挑三个有代表性的检测案例说。
第一个案例是霉变粒密集出现的情况。麦堆里有一小片霉变粒混在一起,默认YOLOv11的部分预测框出现了漏检和位置偏移,有些框的定位甚至跨在相邻麦粒之间。加上BiFPN之后,同样区域的目标框全部精准落到霉变粒上,且把相邻正常麦粒排除在外。这说明加权融合对细微差异的判别力确实更强了。
第二个案例是沙粒和草籽共存的混杂物。沙粒亮度高,形状近圆形,草籽是长条形,两者在低层特征上差异明显,但在高层语义特征上几乎相同。BiFPN通过自适应调整权重,反而没有像PANet那样在高层特征中丢失区分力,两个类别的检测框都保持清晰。
第三个案例是动态模糊场景。输送带速度偏高时,相邻帧之间麦粒会形成轻微运动模糊。这类图像里默认YOLOv11的置信度整体下降明显,加了BiFPN之后置信度下降幅度更小,漏检数也更少。推测原因是BiFPN的横向跳跃连接保留了更多原始图像信息,让网络在特征退化时依然有可用的冗余特征。
5.4 部署端的处理与速度优化
模型训练完之后要做部署。这个项目的目标是让模型跑在工控机内置的入门级推理显卡上,帧率至少要达到25帧,才能跟上输送带的速度。我最终选择导出成TensorRT引擎并开启FP16精度推理。
这里有一个经验要分享:直接导出FP16引擎时,检测头的输出容易发生精度损失,表现为个别小目标在推理时完全消失。解决办法有几个,最简单的方案是控制TensorRT的builder优化级别,不要直接使用最高优化级别,同时在导出前对模型做一次量化敏感度分析。我实际采用的方案是保留FP16精度但关闭部分层级的FP16转化,通过自定义配置文件指定哪些layer需要回退到FP32。这个过程看似麻烦,实测能把最终精度从0.94降到0.92,但推理速度从35帧提升到60帧,整体仍然是正收益。
6. 常见问题与排查技巧实录
6.1 小目标漏检严重怎么办
如果跑完训练,发现大量十几个像素大小的杂质被漏检,第一反应不要调网络结构,先检查验证集和训练集里小目标是不是太少。用脚本统计一下目标框的像素面积分布,如果小目标占比低于10%,那问题基本出现在数据层面,而不是模型层面。解决办法是加大Copy-Paste增强,也可以专门设计一个裁切分支,把图像分成四块分别放大检测,但那样推理速度会翻倍,慎用。
如果数据分布没问题,再看是不是输入分辨率导致的。640分辨率下,十几个像素的目标确实极小,可以考虑把输入分辨率升到960。我的实测数据显示,960分辨率下小目标类别的Recall提升约6%,代价是推理时间增加约40%。最终我选了640加BiFPN的方案,算是在精度速度之间做了个平衡。
6.2 训练loss不收敛
这个项目里最常见的坑是梯度爆炸。原因是自定义的BiFPN_Add模块在初始权重设置不够小心时,可能造成梯度不稳定。我的解决方法是给权重初始化加上约束,确保初始权重之和接近1,并且在forward中对权重做归一化后再参与计算。如果还是看到loss在几十个epoch后突然飙升,第一步就检查权重数值是否出现NaN,第二步把学习率降到原来的1/10重新跑。
还有一个可能原因是标签格式出错。YOLO的标签文件是txt格式,一行五个数值,类别id加归一化中心点坐标和宽高。我遇到过标注工具输出的坐标本身是像素值,直接拿来训练,结果模型完全学不到有效特征。检查方法很简单,读一个标签文件看看坐标范围是否在0到1之间,如果出现大量大于1的数字,就是归一化步骤漏了。
6.3 部署推理结果与训练验证不一致
训练时mAP很高,导出的模型在本地跑却大面积漏检,这种问题通常不是算法本身,而是预处理环节不一致。YOLO训练时做了letterbox填充、归一化到0到1、通道顺序RGB转BGR这些操作,部署时如果用opencv读图直接送入模型,不做letterbox,结果一定是错的。
我建议把整个预处理流程封装成一个函数,训练和推理共用同一份代码,从源头避免不一致。另一个隐蔽问题是模型输出的坐标是相对于输入图而非原图,推理后必须根据letterbox的填充比例把预测框映射回原图坐标。这一点我在项目里专门写了映射函数,并且用一张带标注的验证图做了端到端对比,确认坐标还原无误。
6.4 杂项问题速查
| 问题 | 排查方向 | 可行方案 |
|---|---|---|
| 标注文件类别名错乱 | 核对数据yaml和检测头类别顺序 | 固定类别顺序,不随意改顺序 |
| 训练时GPU显存不足 | batch过大或缓存占用过高 | 缩小batch并同步调低学习率 |
| 某类召回率低 | 该类样本数量少或标注质量差 | 增加增强或做该类别的过采样 |
| 推理端帧率不达标 | 模型参数量过大或输入分辨率过高 | 换更小的模型或降低输入尺寸 |
| 边框定位偏差大 | 定位分支或NMS阈值设置不当 | NMS阈值调到0.45并验证 |
| 同类目标被误分为另一类 | 类别间外观重叠严重 | 合并近似类别或增加细粒度标签 |
个人经验与项目体会
这个项目做完,我最深的一点体会是:农业视觉项目里,网络结构的改进所能带来的增益,往往不如数据层面的精细打磨来得直接。BiFPN这类结构优化确实有效,但它的效果建立在数据质量足够好的前提下,如果标注噪声高、样本不均衡,再强的特征融合也发挥不出来。所以做这类项目时,我的建议是先花大力气把数据集做扎实,再谈网络改进。
要补充说明一下,本文提到的所有数据和案例均来自模拟项目X,是一套完全虚构的经验整理,仅供有类似需求的从业者交流参考。实际落地时,还是建议结合自己的硬件设备、现场光照条件和目标材质特征,对网络结构和训练参数做针对性的调试,不要直接照搬参数。技术路线可以复用,具体数值必须自己重新验证一遍。
最后分享一个可以延续的思路:这套YOLOv11+BiFPN的方案,不只是适用于小麦杂质检测。水稻、玉米、大豆等粮食作物的品质筛查,甚至水产品分拣、工业零部件表面缺陷检测,只要场景特点是目标小、数量密、类别间特征差异细微,这套方法都有很大的迁移空间。后续如果想做得更深,可以尝试在检测之后接一个轻量级分类网络,对疑似目标做二次精细判别,应该还能把误检率进一步压下来。这些是我正在琢磨的方向,也希望能和做类似项目的朋友多交流。