034、特定场景优化(一):小目标检测的改进策略合集


一、从产线瑕疵检测说起

上周在客户现场调试,产线摄像头拍到的PCB板图像里,那些微小的焊点缺陷和刻痕,YOLOv11一个都没抓出来。不是模型精度不够,而是这些目标在640×640的输入尺度下,往往只有4×4甚至更小的像素区域------在经历了多次下采样之后,特征图上可能就剩个寂寞了。

小目标检测一直是工业落地中的硬骨头。今天我们就拆解几套实战中验证过的改进策略,不搞理论堆砌,直接上能写进代码的干货。


二、数据层面:别急着改模型

遇到小目标漏检,第一反应不应该是改网络结构。先看看数据怎么喂的。

保持原始分辨率

YOLO默认的640输入,对于小目标就是灾难。我一般先尝试跳到1024甚至1280:

python 复制代码
# 训练时直接改输入尺寸
model.train(data='pcb.yaml', imgsz=1280, batch=8)  # batch得调小,显存警告!

# 推理时也要保持一致
results = model('defect.jpg', imgsz=1280)  # 这里踩过坑:训练推理尺寸不一致,效果直接崩

但注意,大尺寸训练会显著拖慢速度,且容易过拟合小目标------其他目标可能反而变差。

切图大法好

更稳的一招是大图切块训练+滑动窗口推理。把高分辨率原图切成重叠的小块,每块里的小目标就变成了"中目标":

python 复制代码
# 简易切图示例
def slide_crop(img, crop_size=640, overlap=0.2):
    stride = int(crop_size * (1 - overlap))
    patches = []
    # 别这样写死循环,大图会炸,建议用yield省内存
    for y in range(0, img.shape[0], stride):
        for x in range(0, img.shape[1], stride):
            patch = img[y:y+crop_size, x:x+crop_size]
            if patch.shape[0] == crop_size and patch.shape[1] == crop_size:
                patches.append(patch)
    return patches

训练时对每个切块单独标注,推理时切块检测再拼回去。代价是计算量翻倍,但召回率提升明显。

人工放大标注区域

对于特别关键的小缺陷,可以在标注时稍微把框画大一圈,给模型一点学习余地。这招有点"作弊",但产线急上线时很管用。


三、网络结构:三个必改点

1. 减少下采样次数

YOLO默认下采样32倍,小目标到最后一层特征图早就没了。把最后一个stride=2的卷积或池化去掉,改成16倍下采样:

yaml 复制代码
# 修改model.yaml的backbone部分
# 把某个P5层的stride从2改成1,记得调整后续通道数匹配
# 这块改完一定要算清楚特征图尺寸,不然head会报shape不对

2. 增加高分辨率检测头

YOLOv11默认三个检测头(P3/P4/P5)。对于小目标,我在P2(更大特征图)上加了一个检测头:

python 复制代码
# 在head部分新增一个P2输出
- from: ['backbone.某个浅层输出']
  number: 1
  args: [[128, 256, 'NeckBlock', ...]]  # 这里参数根据实际通道数调整
  # 注意这个头只检测小目标,anchor要重新聚类

然后针对P2头,只用小尺寸的anchor(比如8×8、16×16),避免大anchor干扰。

3. 注意力机制不是银弹

很多人喜欢加SE、CBAM等注意力模块。对于小目标,空间注意力比通道注意力更重要。我习惯在浅层特征后加一个简单的空间注意力:

python 复制代码
class SimpleSpatialAttention(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv = nn.Conv2d(2, 1, kernel_size=7, padding=3, bias=False)
        self.sigmoid = nn.Sigmoid()
    
    def forward(self, x):
        # 沿着通道维度做均值池化和最大池化
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        concat = torch.cat([avg_out, max_out], dim=1)
        attention = self.sigmoid(self.conv(concat))
        return x * attention  # 增强重要区域

但注意,注意力模块会拖慢推理速度,部署前要评估性价比。


四、损失函数:让模型更"关注"小目标

1. 修改anchor匹配策略

YOLO默认用IoU匹配anchor,小目标因为位置敏感,可以改用NWD(Normalized Wasserstein Distance) 作为匹配度量。NWD对微小框的位置偏差更敏感:

python 复制代码
# NWD计算函数
def wasserstein_loss(pred, target):
    # 把框转为高斯分布,算Wasserstein距离
    # 具体实现略,篇幅有限,可搜NWD for YOLO
    return distance

2. 损失权重动态调整

在loss计算时,给小目标更高的权重:

python 复制代码
# 在compute_loss函数里
for i, pi in enumerate(pred):
    # pi是第i个检测头的输出
    # 根据target的尺寸动态赋权
    box_loss_scale = 2.0 - target[:, 3] * target[:, 4]  # 框越小,权重越高
    # 乘到bbox_loss上

3. 分类损失用QFL

Quality Focal Loss不仅解决正负样本不平衡,还对难例小目标有更好的梯度响应。把普通的Focal Loss换成QFL,小目标召回能提2-3个点。


五、后处理与部署陷阱

1. NMS的改进

小目标经常密集出现,传统NMS容易误杀。试试Soft-NMSDIoU-NMS

python 复制代码
# 直接用torchvision里的soft_nms
from torchvision.ops import nms, soft_nms
# soft_nms返回的是新分数,需要阈值过滤

更简单的办法是调高NMS的iou_thres,比如从0.45调到0.6,让重叠的小目标更容易保留。

2. 部署时的分辨率对齐

训练时用了大尺寸或切图,部署时也要保持一致。嵌入式端显存不够怎么办?动态分辨率 或者ROI区域检测

cpp 复制代码
// 嵌入式C++伪代码
// 第一遍用低分辨率检测大目标
// 裁出疑似区域,第二遍高分辨率细查
// 这样整体耗时可控

3. 量化带来的精度损失

小目标对量化更敏感,8bit量化后可能消失。建议:

  • 对小目标检测头单独用更高精度(如16bit)
  • 用感知量化训练(QAT)而不是后训练量化(PTQ)
  • 量化前先做通道蒸馏,让网络对小目标更鲁棒

六、个人经验包

  1. 小目标检测没有通用解法,先分析你的目标到底多小、多密、多模糊。拿张典型图,用画图工具数像素,再定策略。

  2. 数据永远比模型重要。花两天时间精细化标注,比调一个月模型提升更大。特别是边界模糊的小目标,标注一致性是关键。

  3. 不要盲目堆模块。先试输入分辨率→再试数据增强(如mosaic+小目标复制)→最后改网络。我见过有人先改了一堆结构,最后发现是训练时忘了开mosaic。

  4. 部署时留余量。训练时小目标召回95%,部署后可能只剩80%。预留一些阈值调整空间,比如检测分数阈值做成可配置参数。

  5. 终极方案:上高像素相机。算法工程师的尊严是能用算法解决,但实际项目里,换个好相机可能立竿见影------硬件升级有时候是最经济的方案。

相关推荐
何玺1 小时前
从HappyHorse到Seedance:AI视频的“四强争霸”终局推演
人工智能·音视频
菜鸟学习成功之路-李飞1 小时前
OpenClaw 常用命令详解
人工智能·ai
碎碎思1 小时前
FPGA图像处理平台搭建:MIPI + VDMA + Ethernet全流程
图像处理·人工智能·fpga开发
我的世界洛天依1 小时前
胡桃讲编程:混音教学第三步|AI 翻唱实操:软件 + 模型 + 索引全安装(全链接无遗漏・老本专属)
人工智能
猫小呆1 小时前
Openclaw启动后Error: EACCES: permission denied, mkdir权限问题解决(windows)
人工智能
techdashen2 小时前
Rust 在安全关键软件:机遇、挑战与未来之路
人工智能·安全·rust
java1234_小锋2 小时前
LangChain4j快速入门
人工智能·python·spring
江瀚视野2 小时前
美团“小团健康管家”发布,美团也入局AI健康了?
人工智能
HIT_Weston2 小时前
47、【Agent】【OpenCode】本地代理增强版分析(JSON解析)
人工智能·json·agent·opencode