RF-DETR 是 Roboflow 开发的实时目标检测和实例分割 Transformer 架构模型。该模型基于 DINOv2 视觉 Transformer 骨干网络构建,在 Microsoft COCO 和 RF100-VL 数据集上实现了业界领先的精度与延迟平衡。RF-DETR 提供 Nano、Small、Medium、Large、XLarge、2XLarge 等多种尺寸变体,满足不同算力场景需求。本项目使用 RFDETRNano 模型进行 NPU 迁移,该模型参数量 30.5M,输入分辨率 384x384,在 COCO 数据集上达到 AP50=67.6、AP50:95=48.4 的检测精度。
RF-DETR 适用于实时目标检测和实例分割场景,包括:
| 项目 | 版本 / 规格 |
|---|---|
| 操作系统 / 架构 | openEuler 24.03 (LTS) / aarch64 |
| 驱动 / 固件 | 25.2.0 |
| CANN | 8.2.RC1 |
| Python | 3.10.14 |
| torch / torch_npu | 2.4.0 / 2.4.0 |
| 包名 | 版本 | 说明 |
|---|---|---|
| torch | 2.4.0 | PyTorch 核心 |
| torch_npu | 2.4.0 | NPU 适配库 |
| torchvision | 0.19.0 | 视觉处理库 |
| transformers | 4.40.0 | Transformer 模型库 |
| numpy | 1.26.4 | 数值计算(必须 1.x 版本) |
| Pillow | 11.2.1 | 图像处理 |
| albumentations | 1.4.24 | 图像增强 |
| supervision | 0.27.0.post2 | 目标检测可视化 |
| pycocotools | 2.0.11 | COCO 数据集评估 |
| peft | 0.11.0 | 参数高效微调 |
| pydantic | 2.9.2 | 数据验证 |
| scipy | 1.14.1 | 科学计算 |
| tqdm | 4.67.3 | 进度条 |
| opencv-python | 4.12.0.88 | 图像处理 |
| onnx | 1.17.0 | ONNX 格式支持 |
| onnxruntime | 1.15.1 | ONNX 推理 |
| accelerate | 0.34.2 | 分布式训练加速 |
| huggingface_hub | 1.11.0 | 模型下载 |
| safetensors | 0.7.0 | 安全序列化 |
https://github.com/roboflow/rf-detr(预训练权重自动下载)
https://cocodataset.org/#home(COCO 2017 数据集)
https://github.com/roboflow/rf-detr
TODO(补充容器镜像链接)
torch_npu、atc、ais_bench、npu-smi
克隆代码仓并准备环境:
cd /opt
git clone https://github.com/roboflow/rf-detr.git创建虚拟环境:
python3.10 -m venv /opt/rfdetr_venv设置环境变量:
export LD_LIBRARY_PATH=/usr/local/python3.10/lib:$LD_LIBRARY_PATH
export PYTHONPATH=/opt/rfdetr_venv/lib/python3.10/site-packages:/rf-detr/src:$PYTHONPATH
export PYTHONNOUSERSITE=1
export TASK_QUEUE_ENABLE=0
export ACL_OP_INIT_MODE=1
export TBE_PARALLEL_COMPILER=0
source /usr/local/Ascend/ascend-toolkit/8.2.RC1/aarch64-linux/script/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh安装核心依赖:
pip install torch==2.4.0
pip install torch_npu==2.4.0
pip install transformers peft pydantic supervision tqdm requests
pip install pycocotools scipy albumentations修复 CANN TBE 环境缺失的 attr 模块:
pip install attrs decorator
cp /opt/rfdetr_venv/lib/python3.10/site-packages/attrs /usr/local/Ascend/ascend-toolkit/8.2.RC1/python/site-packages/ -r
cp /opt/rfdetr_venv/lib/python3.10/site-packages/decorator.py /usr/local/Ascend/ascend-toolkit/8.2.RC1/python/site-packages/将 COCO 数据集转换为标准格式存放于 /data/coco_formatted 目录,目录结构如下:
/data/coco_formatted/
├── annotations/
│ ├── instances_train2017.json
│ └── instances_val2017.json
├── train2017/
│ └── *.jpg
└── val2017/
└── *.jpg关键适配修改点:
cuda 改为 npu。nccl 改为 hccl。torch.compile() 函数(NPU backend 不支持)。torch.npu.set_compile_mode(jit_compile=False) 可选设置,经测试不关闭 JIT 也能正常训练。find_unused_parameters=True。TASK_QUEUE_ENABLE=0 和 ACL_OP_INIT_MODE=1 绕过 TBE 算子编译问题。单卡训练脚本:[train_npu_native.py]
启动单卡训练:
export ASCEND_RT_VISIBLE_DEVICES=4
python train_npu_native.py --epochs 10 --batch-size 8 --output-dir output/rfdetr_npu_single多卡 DDP 训练脚本:train_npu_ddp.py
DDP 启动脚本:run_ddp.sh
启动 4 卡 DDP 训练:
./run_ddp.sh或手动启动:
export ASCEND_RT_VISIBLE_DEVICES=4,5,6,7
/usr/local/python3.10/bin/python3.10 -m torch.distributed.launch \
--nproc_per_node=4 \
--master_addr=127.0.0.1 \
--master_port=29500 \
--use_env \
train_npu_ddp.py \
--epochs 50 \
--batch-size 8 \
--output-dir output/rfdetr_npu_4card训练完成 50 epochs 后,loss 从初始值 11.1578 下降至 6.2836,训练过程稳定。
训练日志关键数据:
Epoch 1 completed, loss: 11.1578
Epoch 10 completed, loss: 8.2097
Epoch 20 completed, loss: 7.7716
Epoch 30 completed, loss: 7.5393
Epoch 40 completed, loss: 7.3361
Epoch 50 completed, loss: 6.2836
Training completed! Best loss: 6.2836继续训练至 250 epochs 后,loss 最终下降至 4.12,总体降幅约 63%。
完整训练曲线:
| 阶段 | Epoch范围 | Loss变化 | 降幅 |
|---|---|---|---|
| 第1阶段 | 1→50 | 11.16 → 6.28 | -44% |
| 第2阶段 | 51→100 | 6.28 → 6.28 | 持平 |
| 第3阶段 | 101→150 | 6.27 → 5.40 | -14% |
| 第4阶段 | 151→200 | 5.38 → 4.66 | -13% |
| 第5阶段 | 201→250 | 4.67 → 4.12 | -12% |
训练Loss曲线:

训练速度:单卡约 1.0 it/s,4 卡 DDP 约 1.8 it/s,每 epoch 约 1.5 分钟。
输出模型文件:
output/rfdetr_npu_4card/best_model.pth:最佳模型权重(Epoch 248,loss=4.12)output/rfdetr_npu_4card/model_epoch_*.pth:各 epoch checkpointmodel.export() 函数预热模型,准备导出。安装 onnx 包:
pip install onnxONNX 导出脚本:
导出脚本内容:
import os
import sys
os.environ['TASK_QUEUE_ENABLE'] = '0'
os.environ['ACL_OP_INIT_MODE'] = '1'
os.environ['TBE_PARALLEL_COMPILER'] = '0'
venv_site_packages = "/opt/rfdetr_venv/lib/python3.10/site-packages"
sys.path.insert(0, venv_site_packages)
sys.path = [p for p in sys.path if 'python3.11' not in p]
import torch
from rfdetr.config import RFDETRNanoConfig, TrainConfig
from rfdetr._namespace import build_namespace
from rfdetr.models.lwdetr import build_model
model_config = RFDETRNanoConfig(num_classes=80)
train_config = TrainConfig(dataset_dir="/data/coco_formatted")
ns = build_namespace(model_config, train_config)
model = build_model(args=ns)
checkpoint = torch.load('best_model.pth', map_location='cpu')
model.load_state_dict(checkpoint['model_state_dict'])
model = model.float()
model.eval()
print("Calling model.export() to prepare for ONNX export...")
model.export()
resolution = 384
dummy_input = torch.randn(1, 3, resolution, resolution).float()
print(f"Exporting ONNX with resolution {resolution}x{resolution}...")
torch.onnx.export(
model,
dummy_input,
'best_model.onnx',
export_params=True,
opset_version=17,
do_constant_folding=True,
input_names=['images'],
output_names=['output'],
dynamic_axes=None,
dynamo=False
)
print("转换完成!输出文件: best_model.onnx")执行 ONNX 导出:
export LD_LIBRARY_PATH=/usr/local/python3.10/lib:$LD_LIBRARY_PATH
export PYTHONPATH=/opt/rfdetr_venv/lib/python3.10/site-packages:/rf-detr/src:$PYTHONPATH
/opt/rfdetr_venv/bin/python3.10 export_onnx.py校验 ONNX 模型:
python -c "import onnx; model = onnx.load('best_model.onnx'); onnx.checker.check_model(model); print('ONNX模型验证通过!')"使用 ATC 工具将 ONNX 模型转换为 OM 格式。
关键配置:
CPLUS_INCLUDE_PATH 环境变量,解决 GridSample 算子编译失败问题。TBE_PARALLEL_COMPILER=0 关闭并行编译。OM 转换脚本:
转换脚本内容:
#!/bin/bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
export TBE_PARALLEL_COMPILER=0
export ASCEND_SLOG_PRINT_TO_STDOUT=0
export ASCEND_GLOBAL_LOG_LEVEL=3
export CPLUS_INCLUDE_PATH=/usr/include/c++/12:/usr/include/c++/12/aarch64-openEuler-linux:$CPLUS_INCLUDE_PATH
export C_INCLUDE_PATH=/usr/include:$C_INCLUDE_PATH
ONNX_MODEL="best_model.onnx"
OM_MODEL="best_model"
CHIP_TYPE="Ascend910B3"
INPUT_SHAPE="images:1,3,384,384"
PRECISION="allow_mix_precision"
echo "开始转换ONNX模型到OM格式..."
atc --model=$ONNX_MODEL \
--framework=5 \
--output=$OM_MODEL \
--input_format=NCHW \
--input_shape=$INPUT_SHAPE \
--precision_mode=$PRECISION \
--soc_version=$CHIP_TYPE
if [ $? -eq 0 ]; then
echo "模型转换成功!OM文件已保存为: $OM_MODEL.om"
else
echo "模型转换失败,请检查错误信息。"
exit 1
fi执行 OM 转换:
chmod +x convert_onnx_to_om.sh
./convert_onnx_to_om.sh输出文件:best_model.om(约57MB)
使用 ais_bench 进行 OM 模型推理。
安装 ais_bench:
pip install ais_bench图片预处理脚本:
预处理脚本内容:
import cv2
import numpy as np
import glob
import os
import random
os.makedirs("bin", exist_ok=True)
MEAN = np.array([0.485, 0.456, 0.406])
STD = np.array([0.229, 0.224, 0.225])
val_images = glob.glob("/data/coco_formatted/val/*.jpg")
selected_images = random.sample(val_images, min(10, len(val_images)))
for f in selected_images:
img = cv2.imread(f)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (384, 384))
img = img.astype(np.float32) / 255.0
img = (img - MEAN) / STD
img = img.transpose(2, 0, 1)[None, ...].astype(np.float32)
bin_name = f"bin/" + os.path.basename(f)[:-4] + ".bin"
img.tofile(bin_name)
print(f"Converted: {f} -> {bin_name}")
print(f"\nTotal converted: {len(selected_images)} images")执行图片预处理:
python3 jpg_bin.pyOM 推理脚本:
推理脚本内容:
import os
import sys
import glob
import numpy as np
sys.path.insert(0, '/usr/local/lib/python3.11/site-packages')
sys.path.insert(0, '/usr/local/lib64/python3.11/site-packages')
from ais_bench.infer.interface import InferSession
os.makedirs("results", exist_ok=True)
session = InferSession(device_id=0, model_path="best_model.om")
bin_files = glob.glob("bin/*.bin")
print(f"Found {len(bin_files)} bin files")
for bin_file in bin_files:
input_data = np.fromfile(bin_file, dtype=np.float32).reshape(1, 3, 384, 384)
outputs = session.infer([input_data])
result_name = f"results/" + os.path.basename(bin_file)[:-4] + "_output.bin"
if isinstance(outputs, list):
for i, output in enumerate(outputs):
output_name = f"results/" + os.path.basename(bin_file)[:-4] + f"_output_{i}.bin"
if isinstance(output, np.ndarray):
output.tofile(output_name)
print(f"Saved: {output_name}, shape: {output.shape}")
else:
if isinstance(outputs, np.ndarray):
outputs.tofile(result_name)
print(f"Saved: {result_name}, shape: {outputs.shape}")
print(f"Processed: {bin_file}")
print(f"\nTotal processed: {len(bin_files)} images")执行 OM 推理:
export ASCEND_RT_VISIBLE_DEVICES=0
python3 om_inference.py推荐使用 inference_om.py 脚本进行图片直接推理,无需手动转换为 bin 文件。
推理脚本:inference_om.py
执行推理:
source /usr/local/Ascend/ascend-toolkit/8.2.RC1/aarch64-linux/script/set_env.sh
python3.11 inference_om.py \
-m best_model_epoch248.om \
-i /data/coco_formatted/val/000000200839.jpg \
--threshold 0.5 \
--output result.jpg参数说明:
| 参数 | 说明 | 默认值 |
|---|---|---|
-m | OM模型路径 | 必需 |
-i | 输入图片/目录 | 必需 |
--threshold | 置信度阈值 | 0.3 |
--output | 输出图片路径 | output_om.jpg |
--device | NPU设备ID | 0 |
测试图片检测结果:
Detected 6 objects (threshold=0.5)
[1] airplane: score=0.9427, box=[92.2, 170.1, 477.2, 316.0]
[2] refrigerator: score=0.7923, box=[142.9, 240.4, 179.3, 271.9]
[3] refrigerator: score=0.7400, box=[199.4, 237.6, 230.6, 275.2]
[4] refrigerator: score=0.7370, box=[234.5, 201.8, 265.8, 244.2]
[5] refrigerator: score=0.6601, box=[360.1, 193.9, 408.7, 260.4]
[6] refrigerator: score=0.5389, box=[305.8, 192.2, 341.7, 243.2]| 指标 | 值 |
|---|---|
| 最高置信度 | 0.77(airplane检测) |
| 平均置信度 | 0.103 |
| threshold≥0.3 | 68个有效检测 |
| threshold≥0.5 | 18个高置信检测 |
| threshold≥0.7 | 4个非常确定检测 |
置信度分布:
推理结果可视化示例:

模型输出两个 tensor:
后处理步骤:
sigmoid(logits[:, 1:]) 获取类别概率(跳过背景类 index 0)score = max(probs)argmax(probs) + 1xyxy = [cx - w/2, cy - h/2, cx + w/2, cy + h/2]检测结果保存于 vis_results/ 目录,包含标注框的可视化图片。