大数跨境

14.7M参数,小目标AP达到13.9%!FSDETR用频空融合重新定义目标检测

14.7M参数,小目标AP达到13.9%!FSDETR用频空融合重新定义目标检测 机器学习AI算法工程
2026-04-29
18
导读:向AI转型的程序员都关注公众号 机器学习AI算法工程
图片

向AI转型的程序员都关注公众号 机器学习AI算法工程


无人机航拍影像中,那些只有十几个像素的小目标,传统检测器一不小心就漏掉了。

用更大的模型?参数太多,部署到边缘设备跑不动。

用更深的网络?梯度炸了,训练不稳定。

有没有一种方法,能用更少的参数,达到更好的效果

2026年4月,一篇叫FSDETR的论文给出了答案:

频域空域结合的方法,仅用14.7M参数,就在小目标数据集上跑出了13.9% APS的惊人成绩。

这是什么概念?相当于用一辆自行车的体积,干翻了一辆重卡。

01 先说说为什么小目标这么难

在说FSDETR之前,我们先聊聊小目标检测为什么这么痛苦。

你可能遇到过这种情况:

  • 一张航拍图里,车辆只有几十个像素
  • 一张大合影里,人脸小得看不清
  • 监控画面里,远处的行人模模糊糊

为什么会这样?问题出在特征提取特征融合上。

问题一:下采样丢失细节

CNN网络为了减少计算量,会不断下采样。16倍下采样后,一个32x32的小目标,就只剩下2x2像素了。

信息全丢了,怎么检测?

问题二:特征融合不对

很多方法把不同层级的特征强行融合,但高层特征语义虽然强,空间位置信息早就模糊了。

这就是"语义错位"——你知道这是个物体,但不知道它在哪儿。

问题三:背景干扰

小目标在整张图里占比极小,模型很容易被背景带跑。

想象一下在沙子里找金子——小目标就是那颗金子。


FSDETR 论文:

https://arxiv.org/pdf/2604.14884

代码开源地址:

https://github.com/YT3DVision/FSDETR



02 FSDETR 核心思想:频空融合



FSDETR的思路很巧妙:

与其在空间维度修修补补,不如换个维度思考——用频域来处理!

这就好像你听音乐,既要看五线谱(空域),也要听频率(频域),两个结合起来才能完整理解音乐。

FSDETR提出了三个核心模块,一个一个说:

2.1 SHAB:既看局部又看全局

Spatial Hierarchical Attention Block,分层空间注意力。

简单理解就是:

  • 细粒度分支
    :看小目标的边缘、纹理
  • 粗粒度分支
    :看小目标在整张图中的位置
  • 融合
    :把两种信息拼起来

就像你看一张航拍图,既要放大看细节(这里是车轮),也要缩小看全局(车在路的左边)。

2.2 DA-AIFI:动态采样,专挑重点

Deformable Attention based Intra-scale Feature Interaction,可变形注意力。

传统注意力是对所有像素都同等对待,DA-AIFI只关注重点区域

想象你看书的时候,不会每个字都看,而是扫一眼重点,然后仔细看关键段落。

这就是DA-AIFI做的事——自动找到小目标最可能出现的位置,然后重点关注。

2.3 FSFPN:频率+空间双剑合璧

Frequency-Spatial Feature Pyramid Network,频空特征金字塔。

这是FSDETR的核心创新:

  • 高频部分
    :提取边缘、纹理——小目标最缺的就是这些细节
  • 低频部分
    :提取轮廓、结构——告诉模型"这是个什么"

然后通过频空块(CFSB)把两者融合,既保留了细节,又有了语义信息。

⚡ 打个比方

就像我们看一张模糊的老照片:

  • 频域处理 = 看清轮廓和结构(低频)
  • 空域处理 = 看清纹理和边缘(高频)
  • 两者结合 = 既知道"这是个人",又看清了"他的衣服是什么颜色"

03 效果到底有多好?



直接上数据:

数据集
指标
FSDETR结果
对比SOTA
VisDrone 2019
APS(小目标)
13.9%
提升显著
TinyPerson
AP50
48.95%
SOTA
参数量
14.7M
极轻量

可能你对这些数字没概念,我换个说法:

  • 比它强的,参数比它多好几倍
  • 跟它参数差不多,效果没它好
  • 小目标检测AP提升了一大截

💡 简单理解:14.7M参数什么概念?一个普通的手机APP安装包大小。用这么小的模型,达到这种效果,相当于用自行车的油耗,跑出了跑车的速度

04 实战:用FSDETR训练自己的模型

下面进入硬核环节——手把手教你用FSDETR训练自己的检测模型。

4.1 环境准备

# 安装基础依赖
pip install torch torchvision

# 安装FSDETR
git clone https://github.com/YT3DVision/FSDETR.git
cd FSDETR
pip install -r requirements.txt

4.2 数据准备

FSDETR支持COCO格式,这里我们用YOLO格式举例(更通用):

my_dataset/
├── data.yaml          # 配置文件
├── train/
│   ├── images/      # 训练图片
│   └── labels/      # 训练标签
└── valid/
    ├── images/      # 验证图片
    └── labels/      # 验证标签

data.yaml 配置:

path: ./my_dataset
train: train/images
val: valid/images

nc: 3  # 你的类别数
names: ['car', 'person', 'dog']  # 类别名称

标签格式(YOLO格式):

# 每行一个目标:类别ID x_center y_center width height
# 所有值都是归一化的(0-1之间)
0 0.716 0.427 0.108 0.284
1 0.342 0.536 0.075 0.156

4.3 训练代码

import torch
from fsdetr import FSDETR

# 创建模型(小体积,适合边缘部署)
model = FSDETR(
    num_classes=3,          # 你的类别数
    backbone='resnet50',    # 骨干网络
    d_model=256,           # Transformer维度
    nhead=8,                # 注意力头数
    num_encoder_layers=6,  # Encoder层数
    num_decoder_layers=6,  # Decoder层数
    dim_feedforward=2048,   # FFN维度
    dropout=0.1,
    pre_norm=True,
)

# 使用RT-DETR作为基础(已经集成好了)
# 官方提供了更简单的接口:
from fsdetr import build_model

# 方法1:使用预训练模型微调
model = build_model('fsdetr_r50')
model.load_state_dict(torch.load('pretrained.pth'))

# 训练配置
trainer = torch.optim.AdamW(model.parameters(), lr=1e-4)

# 训练循环
for epoch in range(100):
    for batch in dataloader:
        images, targets = batch

        # 前向传播
        outputs = model(images)

        # 计算损失(分类+框回归)
        loss = compute_loss(outputs, targets)

        # 反向传播
        loss.backward()
        trainer.step()
        trainer.zero_grad()

        if epoch % 10 == 0:
            print(f"Epoch {epoch}, Loss: {loss.item():.4f}")

4.4 推理代码

import torch
from fsdetr import FSDETR
from PIL import Image
import numpy as np

# 加载训练好的模型
model = FSDETR(num_classes=3)
model.load_state_dict(torch.load('best_model.pth'))
model.eval()

# 读取图片
image = Image.open('test.jpg').convert('RGB')
image_tensor = torch.from_numpy(np.array(image)).permute(2, 0, 1).float() / 255.0

# 推理
with torch.no_grad():
    outputs = model([image_tensor])

# 解析结果
boxes = outputs['boxes']      # 边界框
scores = outputs['scores']    # 置信度
labels = outputs['labels']    # 类别

# 打印结果
for box, score, label in zip(boxes, scores, labels):
    if score > 0.5:  # 置信度阈值
        print(f"检测到: {label}, 置信度: {score:.2f}, 位置: {box}")

4.5 导出ONNX部署

# 导出为ONNX(跨平台部署)
model.eval()
dummy_input = torch.randn(1, 3, 640, 640)

torch.onnx.export(
    model,
    dummy_input,
    'fsdetr.onnx',
    input_names=['input'],
    output_names=['boxes', 'scores', 'labels'],
    dynamic_axes={
        'input': {0: 'batch'},
        'boxes': {0: 'batch'},
        'scores': {0: 'batch'},
        'labels': {0: 'batch'}
    }
)
print("ONNX导出成功!")

📌 完整训练脚本

# train.py - 完整训练脚本
import torch
import torch.optim as optim
from torch.utils.data import DataLoader
from fsdetr import build_model, CocoDetection
import transforms as T

# 数据增强
def get_transform():
    return T.Compose([
        T.RandomResize([640], max_size=1333),
        T.RandomHorizontalFlip(),
        T.ToTensor(),
        T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])

# 创建数据集
train_dataset = CocoDetection('train2017', get_transform())
val_dataset = CocoDetection('val2017', get_transform())

train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=2)

# 创建模型
model = build_model('fsdetr_r50')

# 优化器
optimizer = optim.AdamW(model.parameters(), lr=1e-4, weight_decay=1e-4)

# 学习率调度
lr_scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)

# 训练循环
num_epochs = 50
for epoch in range(num_epochs):
    model.train()
    total_loss = 0

    for images, targets in train_loader:
        outputs = model(images, targets)
        losses = sum(loss for loss in outputs.values())

        optimizer.zero_grad()
        losses.backward()
        optimizer.step()

        total_loss += losses.item()

    avg_loss = total_loss / len(train_loader)
    print(f"Epoch {epoch+1}/{num_epochs}, Loss: {avg_loss:.4f}")

    lr_scheduler.step()

    # 保存检查点
    if (epoch + 1) % 10 == 0:
        torch.save(model.state_dict(), f'checkpoint_{epoch+1}.pth')

# 保存最终模型
torch.save(model.state_dict(), 'fsdetr_best.pth')
print("训练完成!")

05 效果对比:传统方法 vs FSDETR

为了让你更直观地感受FSDETR的威力,我们做个对比:

方面
传统YOLO系列
FSDETR
小目标检测
容易漏检
13.9% APS
参数体积
50M+
14.7M
边缘部署
困难
轻松
特征融合
简单拼接
频空融合
计算量

🎯 适合场景

  • ✅ 无人机航拍目标检测
  • ✅ 自动驾驶小目标识别
  • ✅ 工业质检微小缺陷
  • ✅ 边缘设备部署
  • ✅ 资源受限的移动端


FSDETR的核心贡献,是证明了频域和空域结合这条路走得通。

以前我们总在空间维度上纠结——怎么融合特征、怎么增强感受野。

FSDETR告诉我们:换个维度思考,可能就是破局的关键。




阅读过本文的人还看了以下文章:


最顶尖的OCR算法有哪些?

最强一键抠图19Kstar 的 Rembg 开源神器


实时语义分割ENet算法,提取书本/票据边缘


整理开源的中文大语言模型,以规模较小、可私有化部署、训练成本较低的模型为主


《大语言模型》PDF下载


动手学深度学习-(李沐)PyTorch版本


YOLOv9电动车头盔佩戴检测,详细讲解模型训练


TensorFlow 2.0深度学习案例实战


基于40万表格数据集TableBank,用MaskRCNN做表格检测


《基于深度学习的自然语言处理》中/英PDF


Deep Learning 中文版初版-周志华团队


【全套视频课】最全的目标检测算法系列讲解,通俗易懂!


《美团机器学习实践》_美团算法团队.pdf


《深度学习入门:基于Python的理论与实现》高清中文PDF+源码


《深度学习:基于Keras的Python实践》PDF和代码


特征提取与图像处理(第二版).pdf


python就业班学习视频,从入门到实战项目


2019最新《PyTorch自然语言处理》英、中文版PDF+源码


《21个项目玩转深度学习:基于TensorFlow的实践详解》完整版PDF+附书代码


《深度学习之pytorch》pdf+附书源码


PyTorch深度学习快速实战入门《pytorch-handbook》


【下载】豆瓣评分8.1,《机器学习实战:基于Scikit-Learn和TensorFlow》


《Python数据分析与挖掘实战》PDF+完整源码


汽车行业完整知识图谱项目实战视频(全23课)


李沐大神开源《动手学深度学习》,加州伯克利深度学习(2019春)教材


笔记、代码清晰易懂!李航《统计学习方法》最新资源全套!


《神经网络与深度学习》最新2018版中英PDF+源码


将机器学习模型部署为REST API


FashionAI服装属性标签图像识别Top1-5方案分享


重要开源!CNN-RNN-CTC 实现手写汉字识别


yolo3 检测出图像中的不规则汉字


同样是机器学习算法工程师,你的面试为什么过不了?


前海征信大数据算法:风险概率预测


【Keras】完整实现‘交通标志’分类、‘票据’分类两个项目,让你掌握深度学习图像分类


VGG16迁移学习,实现医学图像识别分类工程项目


特征工程(一)


特征工程(二) :文本数据的展开、过滤和分块


特征工程(三):特征缩放,从词袋到 TF-IDF


特征工程(四): 类别特征


特征工程(五): PCA 降维


特征工程(六): 非线性特征提取和模型堆叠


特征工程(七):图像特征提取和深度学习


如何利用全新的决策树集成级联结构gcForest做特征工程并打分?


Machine Learning Yearning 中文翻译稿



不断更新资源

深度学习、机器学习、数据分析、python

 搜索公众号添加: datayx  

图片



【声明】内容源于网络
0
0
机器学习AI算法工程
计算机视觉、自然语言处理、推荐系统、人工智能、大模型、深度学习、机器学习、大数据技术社区,分享各类算法原理与源码、数据处理、可视化、爬虫、竞赛开源代码等资源。
内容 1548
粉丝 1
机器学习AI算法工程 计算机视觉、自然语言处理、推荐系统、人工智能、大模型、深度学习、机器学习、大数据技术社区,分享各类算法原理与源码、数据处理、可视化、爬虫、竞赛开源代码等资源。
总阅读12.9k
粉丝1
内容1.5k