FBRT-YOLO实战:从零部署到VisDrone数据集调优,5分钟搞定航拍小目标检测

如果你正在为无人机航拍图像里那些“若隐若现”的小目标头疼——比如几百米高空下,画面里小得像蚂蚁的车辆、行人,或者农田里零星分布的作物病害斑点——那么这篇文章就是为你准备的。传统的YOLO模型在这些场景下往往力不从心,要么漏检严重,要么推理速度跟不上实时需求。而今天我们要动手部署和测试的FBRT-YOLO,正是为了解决这个痛点而生。

FBRT-YOLO是北京理工大学团队在AAAI 2025上提出的一个专门针对实时航拍图像检测的轻量级模型。它不像某些论文那样只追求刷榜指标,而是实实在在地在精度和速度之间找到了一个绝佳的平衡点。最让我印象深刻的是,它在VisDrone数据集上,相比YOLOv8-S,参数量减少了74%,但平均精度(AP)反而提升了2.3%。这意味着你可以在算力有限的边缘设备(比如无人机机载计算机或Jetson系列开发板)上,跑出更准、更快的检测效果。

接下来的内容,我会带你从零开始,一步步完成FBRT-YOLO的环境搭建、模型下载、数据集准备、训练调优和性能测试。整个过程力求清晰直白,即便你之前没有太多深度学习部署经验,也能跟着走下来。我们不仅会跑通流程,更会深入几个关键调参技巧,帮你把模型性能“压榨”到极致。

1. 环境准备与模型获取

在开始任何实验之前,一个干净、兼容的环境是成功的基石。FBRT-YOLO基于PyTorch框架,对环境的版本有一定要求,盲目安装最新版可能会遇到兼容性问题。

1.1 创建并激活Conda虚拟环境

我强烈建议使用Conda来管理Python环境,它能有效避免不同项目间的包版本冲突。

# 创建一个名为fbrt-yolo的Python 3.9环境
conda create -n fbrt-yolo python=3.9 -y

# 激活环境
conda activate fbrt-yolo

选择Python 3.9是因为它在PyTorch生态中拥有最广泛的兼容性和最稳定的社区支持。环境激活后,你的命令行提示符前应该会出现(fbrt-yolo)的字样。

1.2 安装PyTorch与核心依赖

接下来安装PyTorch。请根据你的CUDA版本(如果有GPU)去PyTorch官网获取最匹配的安装命令。以下以CUDA 11.8为例:

# 安装PyTorch、TorchVision和TorchAudio
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

# 安装其他必要依赖
pip install opencv-python-headless matplotlib seaborn tqdm pandas pyyaml scipy ipython

注意:如果你没有NVIDIA GPU或CUDA环境,请使用CPU版本的PyTorch (--index-url https://download.pytorch.org/whl/cpu)。不过,训练和推理速度会慢很多。

1.3 克隆官方代码仓库与模型下载

FBRT-YOLO的官方代码通常会在论文发表后开源在GitHub上。我们可以直接克隆仓库并进入项目目录。

# 克隆代码仓库 (请以论文作者最终公布的仓库地址为准,此处为示例)
git clone https://github.com/galaxy-oss/FBRT-YOLO.git
cd FBRT-YOLO

# 安装项目特定的依赖包 (通常包含在requirements.txt中)
pip install -r requirements.txt

进入项目目录后,你通常会看到类似如下的结构:

FBRT-YOLO/
├── models/          # 模型定义文件 (FBRT-YOLO的FCM、MKP模块定义就在这里)
├── data/            # 数据配置脚本
├── utils/           # 工具函数 (数据加载、指标计算等)
├── weights/         # 预训练模型权重存放处 (初始为空)
├── train.py         # 训练脚本
├── detect.py        # 推理/检测脚本
└── README.md        # 项目说明

接下来下载预训练模型。论文作者一般会提供在大型数据集(如COCO)上预训练的权重,这能极大加速我们在特定数据集(如VisDrone)上的收敛。权重文件通常以.pt后缀保存。将其放入weights/文件夹。

# 示例:下载FBRT-YOLO-S模型的预训练权重
wget -P weights/ https://github.com/galaxy-oss/FBRT-YOLO/releases/download/v1.0/fbrt_yolo_s.pt

如果wget不可用,你也可以手动从发布页面下载并放置到对应目录。至此,基础环境就绪。

2. VisDrone数据集处理与配置

模型准备好了,接下来需要“喂”给它的数据。VisDrone是无人机目标检测领域最权威的公开数据集之一,包含大量城市、乡村、交通枢纽等场景的航拍图像,目标小而密集,非常适合用来验证FBRT-YOLO。

2.1 数据集下载与解压

首先,访问VisDrone数据集官网进行注册并下载。我们需要的是“VisDrone2019-DET”部分,它包含训练集、验证集和测试集。

# 假设你将下载的压缩包放在了当前项目目录下
# 解压数据集
unzip VisDrone2019-DET.zip -d data/

解压后的目录结构应如下所示:

data/VisDrone2019-DET/
├── annotations/          # 标注文件 (XML或TXT格式,VisDrone通常为TXT)
├── images/              # 图像文件夹
│   ├── train/
│   ├── val/
│   └── test/
└── splits/              # 可能包含划分好的文件列表

VisDrone的标注格式是每张图片对应一个.txt文件,每行表示一个目标,格式为:<class_id> <x_center> <y_center> <width> <height>,坐标和尺寸都是归一化到[0,1]的值。

2.2 转换为YOLO格式

虽然VisDrone提供了标注,但它的类别ID和文件组织方式可能需要调整以适配FBRT-YOLO的训练流程。通常,我们需要编写一个简单的转换脚本。

创建一个名为convert_visdrone_to_yolo.py的脚本:

import os
from pathlib import Path

def convert_visdrone_annotation(txt_path, output_dir, img_width=1920, img_height=1080):
    """将VisDrone的TXT标注转换为YOLO格式的TXT文件。"""
    with open(txt_path, 'r') as f:
        lines = f.readlines()

    yolo_lines = []
    for line in lines:
        # VisDrone格式: <bbox_left,bbox_top,bbox_width,bbox_height,score,class,truncation,occlusion>
        parts = line.strip().split(',')
        if len(parts) < 8:
            continue
        # 只取前5个和类别,忽略score, truncation, occlusion
        x_min, y_min, w, h, _, class_id = map(int, parts[:6])

        # 过滤掉无效目标 (VisDrone中class_id为0表示忽略)
        if class_id == 0:
            continue

        # 将类别ID映射到从0开始的连续ID (VisDrone有10类: pedestrian, people, bicycle...)
        # 这里需要根据你的任务定义映射关系,假设我们只关心前10类,且忽略‘ignored regions’
        # 一个简单的映射:原class_id 1->0, 2->1, ... 10->9
        yolo_class_id = class_id - 1  # 确保在0-9范围内
        if not (0 <= yolo_class_id <= 9):
            continue  # 跳过其他类别

        # 计算中心点和归一化宽高
        x_center = (x_min + w / 2) / img_width
        y_center = (y_min + h / 2) / img_height
        nw = w / img_width
        nh = h / img_height

        yolo_lines.append(f"{yolo_class_id} {x_center:.6f} {y_center:.6f} {nw:.6f} {nh:.6f}")

    # 写入YOLO格式文件
    if yolo_lines:
        output_path = output_dir / (txt_path.stem + '.txt')
        with open(output_path, 'w') as f:
            f.write('\n'.join(yolo_lines))

# 主转换流程
data_root = Path('data/VisDrone2019-DET')
annotations_dir = data_root / 'annotations'
images_dir = data_root / 'images'

for split in ['train', 'val']:
    img_folder = images_dir / split
    ann_folder = annotations_dir / split
    output_ann_folder = data_root / 'labels' / split  # YOLO格式的标签存放处

    output_ann_folder.mkdir(parents=True, exist_ok=True)

    # 遍历所有TXT标注文件
    for ann_file in ann_folder.glob('*.txt'):
        convert_visdrone_annotation(ann_file, output_ann_folder)

print("转换完成!")

运行此脚本后,你会在data/VisDrone2019-DET/labels/下得到trainval文件夹,里面是YOLO格式的标签文件。

2.3 创建数据集配置文件

YOLO系列模型通常需要一个.yaml文件来指明数据集路径和类别信息。在data/目录下创建visdrone.yaml

# VisDrone数据集配置文件
path: ../data/VisDrone2019-DET  # 数据集根目录
train: images/train  # 训练集图像路径 (相对于path)
val: images/val      # 验证集图像路径

# 类别数
nc: 10

# 类别名称列表 (根据VisDrone官方顺序)
names: [
  'pedestrian', 'people', 'bicycle', 'car', 'van', 'truck', 'tricycle', 'awning-tricycle', 'bus', 'motor'
]

# 可选:下载地址/自动下载脚本 (用于复现)
# download: https://github.com/...

这个配置文件将告诉训练脚本去哪里找图片和标签,以及有多少个类别需要检测。

3. 模型训练与关键调参技巧

有了数据和模型,训练是下一个核心环节。直接使用默认参数可能也能跑出结果,但要想获得论文中报告的最佳性能,以下几个调参点至关重要。

3.1 启动基础训练

首先,我们使用最基本的命令启动训练,观察模型能否正常跑起来。这里以FBRT-YOLO-S(小模型)为例。

python train.py \
  --weights weights/fbrt_yolo_s.pt \  # 预训练权重
  --data data/visdrone.yaml \         # 数据集配置
  --epochs 100 \                      # 训练轮数
  --imgsz 640 \                       # 输入图像尺寸
  --batch-size 16 \                   # 批次大小,根据GPU内存调整
  --device 0 \                        # 使用第0号GPU,如果是CPU则用 --device cpu
  --workers 4 \                       # 数据加载线程数
  --project runs/train \              # 输出目录
  --name fbrt_yolo_s_baseline         # 本次实验名称

训练开始后,你会看到终端输出每个epoch的损失值、精度指标(mAP@0.5, mAP@0.5:0.95)等。TensorBoard或类似的日志工具(如果项目支持)会记录更详细的曲线,方便你监控训练过程。

3.2 针对小目标的核心调优策略

默认训练可能无法充分发挥FBRT-YOLO在小目标检测上的潜力。下面几个策略是我在多次实验中总结出来的,能有效提升在VisDrone这类数据集上的表现。

策略一:调整输入图像分辨率 航拍图像原始分辨率很高(如1920x1080),直接下采样到640x640会丢失大量小目标细节。尝试增大--imgsz

# 尝试更大的输入尺寸,但注意这会增加显存消耗和计算量
python train.py ... --imgsz 896

如果GPU内存不足,可以相应减小--batch-size。一个经验法则是,在VisDrone上,将分辨率从640提升到896,mAP@0.5通常能有1-3个百分点的提升,尤其是对小目标。

策略二:启用马赛克增强与混合增强 YOLO系列常用的马赛克(Mosaic)和混合(MixUp)数据增强能极大地提升模型鲁棒性,特别是对于小目标和密集场景。确保它们在配置文件中是开启的(通常默认开启)。你可以在data/hyps/hyp.scratch.yaml(或类似文件)中调整增强强度。

# 示例超参数文件片段
mosaic: 1.0  # 马赛克增强概率,1.0表示100%启用
mixup: 0.15  # MixUp增强概率
copy_paste: 0.0  # 复制粘贴增强,对小目标密集场景可能有奇效,但需谨慎调整

策略三:优化损失函数权重 FBRT-YOLO的损失函数通常包含分类损失(cls)、定位损失(box)和对象度损失(obj)。在VisDrone上,由于小目标多且密集,可以适当提高定位损失的权重,让模型更关注边界框的精确回归。

# 通过命令行覆盖默认超参数
python train.py ... --box 0.06 --cls 0.35 --obj 0.7

这里的数值需要根据你的验证集表现进行微调。一个常见的做法是,在训练中期观察验证集损失曲线,如果定位损失下降缓慢,可以尝试增大--box的权重。

策略四:使用更密集的锚框(Anchor) YOLO模型会针对数据集聚类生成一组先验锚框尺寸。VisDrone的目标普遍偏小,默认的COCO预训练锚框可能不匹配。你可以使用项目自带的utils/autoanchor.py脚本为VisDrone重新聚类锚框。

python utils/autoanchor.py --data data/visdrone.yaml --model weights/fbrt_yolo_s.pt

脚本会输出一组新的锚框尺寸。将这组尺寸更新到模型配置文件(models/fbrt_yolo_s.yaml)的anchors部分,然后重新训练。

3.3 训练过程监控与早停

训练时不要设完命令就放任不管。密切监控验证集指标mAP@0.5:0.95(即mAP)。当这个指标在连续多个epoch(如10-20个)不再提升时,就可以考虑提前终止训练,避免过拟合。

# 许多训练脚本支持早停参数
python train.py ... --patience 30  # 如果mAP在30个epoch内未提升,则停止训练

训练完成后,最佳模型权重通常会保存在runs/train/fbrt_yolo_s_baseline/weights/best.pt。这个文件就是我们后续用于测试和部署的模型。

4. 模型评估与性能对比分析

训练完成,我们需要客观地评估模型性能,并与基线模型(如YOLOv8)进行对比,看看FBRT-YOLO的提升究竟在哪里。

4.1 在验证集上评估模型

使用验证集评估模型,会输出一系列关键指标。

python val.py \
  --weights runs/train/fbrt_yolo_s_baseline/weights/best.pt \
  --data data/visdrone.yaml \
  --batch-size 32 \
  --imgsz 640 \
  --task val \
  --device 0 \
  --verbose  # 输出每个类别的详细AP

运行后,你会看到类似下面的输出摘要:

Class     Images  Instances      P      R      mAP50  mAP50-95
all        548        ...      0.xxx  0.xxx   0.xxx    0.xxx
pedestrian 548        ...      0.xxx  0.xxx   0.xxx    0.xxx
car        548        ...      0.xxx  0.xxx   0.xxx    0.xxx
...

重点关注mAP50mAP50-95(即mAP@0.5和mAP@0.5:0.95)。前者衡量在IoU阈值为0.5时的检测精度,后者是更严格的综合指标。同时,观察每个类别的AP,可以知道模型在哪些具体类别上表现好或差。

4.2 可视化检测结果

数字指标是冰冷的,可视化能给你更直观的感受。使用检测脚本在几张验证集图片上运行模型。

python detect.py \
  --weights runs/train/fbrt_yolo_s_baseline/weights/best.pt \
  --source data/VisDrone2019-DET/images/val/0000001_00001_d_0000006.jpg \  # 单张图片
  --conf 0.25 \     # 置信度阈值
  --iou 0.45 \      # NMS的IoU阈值
  --device 0 \
  --save-txt        # 同时保存标签文件
  --save-conf       # 在标签中保存置信度

打开生成的runs/detect/exp/文件夹,查看标注后的图片。你可以特别关注那些包含密集小目标的场景,看看FBRT-YOLO是否比基线模型(比如用同样的流程训练一个YOLOv8-S)检测出更多、更准的小目标。

4.3 性能对比:FBRT-YOLO vs. YOLOv8

为了进行公平对比,你需要用完全相同的训练设置(数据、增强、超参数、epoch数)再训练一个YOLOv8-S模型。然后对比两者的关键指标:

模型参数量 (M)GFLOPsmAP@0.5 (Val)mAP@0.5:0.95 (Val)FPS (RTX 3080)
YOLOv8-S11.228.638.7%22.1%156
FBRT-YOLO-S2.921.441.0%23.8%183

表:在VisDrone验证集上的性能对比示例(数值为模拟,实际以你的实验结果为准)

从这张表可以清晰看出FBRT-YOLO-S的优势:参数量大幅减少(约74%),计算量(GFLOPs)降低,但精度(mAP)反而更高,推理速度(FPS)也更快。这正是其核心价值所在——通过特征互补映射模块(FCM)多核感知单元(MKP) 的精巧设计,在减少冗余计算的同时,更有效地保留了小目标的空间信息和多尺度特征。

4.4 速度测试与边缘部署考量

对于无人机等边缘设备,推理速度(FPS)和模型大小至关重要。我们可以用detect.py脚本并指定--half(半精度推理)来测试速度。

python detect.py \
  --weights runs/train/fbrt_yolo_s_baseline/weights/best.pt \
  --source data/VisDrone2019-DET/images/val \  # 对整个验证集测速
  --imgsz 640 \
  --device 0 \
  --half \      # 使用FP16半精度,可显著提升速度
  --save-txt \
  --save-conf

在输出日志的末尾,你会看到平均推理时间(如Speed: 2.4ms pre-process, 5.6ms inference, 1.2ms NMS per image at shape (1, 3, 640, 640))。据此可以估算FPS(1000 / (5.6+1.2) ≈ 147 FPS)。结合半精度和TensorRT等推理引擎进一步优化,完全有可能在Jetson Orin等设备上实现实时检测。

5. 高级技巧:模型集成与推理优化

当你满足于单个模型的性能后,还可以通过一些高级技巧进一步“压榨”潜力,或者为生产环境部署做准备。

5.1 测试时增强(TTA)

测试时增强是一种在推理阶段通过应用多种图像变换(翻转、缩放等)并集成结果来提升精度的方法,但会牺牲速度。

python val.py \
  --weights runs/train/fbrt_yolo_s_baseline/weights/best.pt \
  --data data/visdrone.yaml \
  --imgsz 640 \
  --task val \
  --device 0 \
  --augment  # 启用测试时增强

启用TTA后,mAP通常会提升1-2个百分点,但推理时间会增加数倍。这适合对精度要求极高、对实时性要求不苛刻的离线分析场景。

5.2 模型集成

如果你训练了多个不同初始化或不同数据增强版本的FBRT-YOLO模型,可以尝试将它们的结果集成起来。

# 一个简单的集成推理示例 (伪代码)
import torch
from ensemble_boxes import weighted_boxes_fusion  # 需要安装 ensemble-boxes 库

model1 = load_model('weights/model1.pt')
model2 = load_model('weights/model2.pt')
# ... 更多模型

all_detections = []
for model in [model1, model2]:
    dets = model(image)  # 获取检测结果
    all_detections.append(dets)

# 使用加权框融合(WBF)等方法融合多个模型的预测结果
fused_boxes, fused_scores, fused_labels = weighted_boxes_fusion(
    all_boxes_list, all_scores_list, all_labels_list,
    weights=[1.0, 1.0], iou_thr=0.5, skip_box_thr=0.0001
)

集成往往能稳定提升精度,但同样会增加计算开销和复杂度。

5.3 模型导出与优化

为了在C++环境、移动端或边缘设备部署,你需要将PyTorch模型导出为ONNX或TensorRT等格式。

# 导出为ONNX格式
python export.py \
  --weights runs/train/fbrt_yolo_s_baseline/weights/best.pt \
  --imgsz 640 640 \
  --include onnx \
  --opset 12  # ONNX算子集版本

导出ONNX后,你可以使用ONNX Runtime进行推理,或者进一步使用TensorRT的trtexec工具转换为TensorRT引擎,获得极致的推理速度。

# 使用TensorRT转换ONNX模型 (示例)
trtexec --onnx=fbrt_yolo_s.onnx \
        --saveEngine=fbrt_yolo_s.engine \
        --fp16 \          # 使用FP16精度
        --workspace=2048  # 指定显存工作空间

经过TensorRT优化后,在相同的GPU上,FPS通常能有30%-100%甚至更高的提升,这对于无人机实时视频流分析至关重要。

整个流程走下来,你应该已经成功部署并优化了FBRT-YOLO模型,并在VisDrone数据集上验证了其在小目标检测上的优势。记住,没有一劳永逸的“最佳参数”,最好的模型永远是那个最适应你具体场景和数据特性的模型。多实验、多分析验证集上的失败案例,不断调整数据增强、超参数甚至模型结构,才能真正发挥出FBRT-YOLO的潜力。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐