必须显式传 -DCMAKE_CUDA_ARCHITECTURES,否则环境里的旧值会覆盖导致 CUDA 预处理 kernel 未针对你的 GPU 优化;运行前需先用 Python 一次性导出 ONNX 并用 rfdetr_build 构建 engine,C++ 运行时本身不需要 Python;FP16 引擎可能因注意力数值超出 FP16 范围产生 NaN 而检测为空,需用 test_img 验证,异常时回退 FP32。
rf-detr-cpp
infracvApache-2.0活跃维护基于 C++ 和 TensorRT 的 RF-DETR 推理引擎,支持目标检测与实例分割,可在 NVIDIA GPU 和 Jetson 上以 FP32/FP16/INT8 量化部署。
Production-ready C++/TensorRT inference engine for RF-DETR. Object detection and instance segmentation with FP32/FP16/INT8 support. Optimized for NVIDIA GPUs, Jetson (Orin, AGX Thor).
git clone https://github.com/infracv/rf-detr-cpp.git
cd rf-detr-cpp
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_CUDA_ARCHITECTURES=120
cmake --build build -j$(nproc)需 NVIDIA GPU,计算能力 ≥ 8.0(RTX 30xx/40xx/50xx),并支持 Jetson Orin 与 Thor/GH200;README 未给出最低显存要求,benchmark 中 nano 模型占用约 836–892 MB。
RF-DETR 的 C++/TensorRT 推理引擎,运行时零 Python 依赖,面向生产部署
基于 C++ 和 TensorRT 的 RF-DETR 推理引擎,支持目标检测与实例分割,可在 NVIDIA GPU 和 Jetson 上以 FP32/FP16/INT8 量化部署。
核心能力
- 用纯 C++ 实现 DETR 式推理管线,无需 NMS、anchor 与 letterbox
- 预处理走 GPU CUDA kernel,主机到设备异步传输用 pinned memory
- 支持 FP32/FP16/INT8 三种精度,INT8 走校准缓存或 QDQ ONNX
- 用 CUDA Graph 重放派发推理,降低每帧调度开销
- 提供检测与实例分割 API,并支持动态 batch 与 C ABI 供 FFI 调用
容易踩的坑
- v0.0.1v0.0.1 - initial release最新正式版2026-06-27 · 2026-06-27 17:01 UTC
We are excited to announce the initial public release of RF-DETR C++, a production-grade TensorRT inference library for RF-DETR, Roboflow's transformer-based real-time object detection model built on a DINOv2 backbone.
RF-DETR C++ brings zero-Python, GPU-accelerated inference to C++ applications. The entire pipeline — preprocessing, inference, and postprocessing — runs in C++ with CUDA, delivering sub-3ms latency on modern NVIDIA GPUs.
Features
Object Detection
RFDetrDetectorwithdetect()anddetect_batch()APIs- Fused resize and normalize CUDA preprocessing kernel with async H2D transfers via pinned memory
- CUDA Graph capture for minimal dispatch overhead on repeated inference calls
- Supports all RF-DETR variants:
nano,small,medium,base,large
Instance Segmentation
RFDetrSegmenterwithsegment()andsegment_batch()APIs- GPU mask decode kernel — bilinear upsample and threshold parallelized across all detections simultaneously
- Per-detection
CV_8UC1masks at original image resolution - Supports segmentation variants:
seg-nano,seg-small,seg-medium,seg-large,seg-xlarge,seg-2xlarge
Precision Support
- FP32 — full precision, default
- FP16 — ~25% faster than FP32, pre-converted ONNX weights for TRT 11
- INT8 — lowest memory footprint, QDQ ONNX path for TRT 11+, calibration cache for TRT < 11
Memory and Resource Management
- RAII CUDA wrappers replacing raw pointer management throughout the library
- All CUDA handles owned and destroyed automatically
C ABI
- Full C API (
librfdetr_c.so) for FFI bindings from Python, Rust, Go, or any language with a C FFI
CLI Tools
rfdetr_build— convert ONNX to TensorRT engine (FP32, FP16, INT8, dynamic batch)rfdetr_detect— run detection on a single imagerfdetr_seg— run instance segmentation on a single imagerfdetr_video— run detection on a video file or live camera streamrfdetr_batch— run detection on multiple images in a single engine callrfdetr_bench— full latency and throughput benchmark with JSON outputrfdetr_inspect— print engine I/O bindings, shapes, and sidecar metadatarfdetr_smoke— load an engine, run a zero-input forward pass, verify outputs
Benchmark
NVIDIA RTX 5070 Ti, Batch 1, 500 iterations.
Task Variant Precision FPS Avg Latency GPU Memory Detection nanoFP16 500 2.001 ms 768 MB Detection nanoINT8 482 2.073 ms 684 MB Segmentation seg-nanoFP16 166 6.014 ms 735 MB Segmentation seg-nanoINT8 126 7.895 ms 687 MB
Requirements
Dependency Version NVIDIA GPU CC >= 8.0 CUDA Toolkit >= 12.0 TensorRT >= 10.0 OpenCV >= 4.5 CMake >= 3.20 C++ compiler C++17
Getting Started
git clone https://github.com/infracv/rf-detr-cpp.git cd rf-detr-cpp cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_CUDA_ARCHITECTURES=120 cmake --build build -j$(nproc)See the README for the full setup guide including ONNX export and engine conversion.
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
Overview
RF-DETR C++ is a production-grade TensorRT inference engine for RF-DETR, Roboflow's transformer-based real-time object detection model built on a DINOv2 backbone.
#include "rfdetr/tasks/detector.hpp"
rfdetr::RFDetrDetector detector("rf-detr-nano-fp32.engine");
rfdetr::Detections dets = detector.detect(cv::imread("image.jpg"), 0.5f);
Unlike YOLO models, RF-DETR uses a DETR-style architecture with no NMS, no anchor grids, no letterboxing. This requires a different inference pipeline, which this library implements entirely in C++ with zero Python at runtime.
Most RF-DETR deployments run Python at inference time. This library eliminates that dependency:
| RF-DETR C++ | Python (PyTorch) | |
|---|---|---|
| Runtime dependency | C++ only | Python + PyTorch + CUDA |
| Preprocessing | GPU CUDA kernel | CPU / torchvision |
| Host-to-device transfer | Async (pinned memory) | Synchronous |
| Precision | FP32 / FP16 / INT8 | FP32 / FP16 |
| Inference dispatch | CUDA Graph replay | Per-frame forward pass |
| Latency (RTX 5070 Ti) | 2.0 ms (FP16) | ~15–30 ms |
Quick Start
# 1. Clone & build
git clone https://github.com/infracv/rf-detr-cpp.git
cd rf-detr-cpp
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_CUDA_ARCHITECTURES=120
cmake --build build -j$(nproc)
# Replace 120 with your GPU arch: RTX 30xx=86, RTX 40xx=89, RTX 50xx=120
# Tarball TensorRT: add -DTENSORRT_DIR=/path/to/TensorRT
# 2. Export ONNX and build TRT engine (one-time, Python)
pip install -r requirements.txt
python trt-files/scripts/export_onnx.py --variant nano --out-dir trt-files/onnx
# FP32 engine
./build/rfdetr_build --onnx trt-files/onnx/rf-detr-nano.onnx --precision fp32
# FP16 engine
./build/rfdetr_build --onnx trt-files/onnx/rf-detr-nano.onnx --precision fp16
# 3. Run inference
./build/rfdetr_detect \
--engine trt-files/onnx/rf-detr-nano-fp16.engine \
--image asset/test_img.jpg --out out/result.jpg
Supported Models & Tasks
| Task | Variants |
|---|---|
| Object Detection | nano, small, medium, base, large |
| Instance Segmentation | seg-nano, seg-small, seg-medium, seg-large, seg-xlarge, seg-2xlarge |
Precision support
| Precision | TRT < 11 | TRT 11+ | Notes |
|---|---|---|---|
| FP32 | ✅ | ✅ | Default |
| FP16 | ✅ (kFP16 flag) | ✅ (convert_fp16.py → pre-converted ONNX) | ~25% faster than FP32 |
| INT8 | ✅ (calibration cache) | ✅ (QDQ ONNX via convert_int8.py) | Lowest memory |
FP16 NaN sanity check. RF-DETR's transformer attention can produce values that exceed the FP16 range (±65,504), causing NaNs to propagate through the network and yield zero detections. After building an FP16 engine, run a single detection on
asset/test_img.jpg. If you get zero detections on an image where FP32 finds objects, your FP16 engine is hitting overflow. Fall back to FP32 (rfdetr_build --precision fp32) or rebuild with mixed-precision settings.
Installation
Prerequisites
| Dependency | Version | Notes |
|---|---|---|
| NVIDIA GPU | CC ≥ 8.0 | RTX 30xx / 40xx / 50xx |
| CUDA Toolkit | ≥ 12.0 | |
| TensorRT | ≥ 10.0 | TRT 11 supported (strongly-typed networks) |
| OpenCV | ≥ 4.5 | core, imgproc, imgcodecs, videoio, highgui |
| CMake | ≥ 3.20 | |
| C++ compiler | C++17 | GCC 9+, Clang 10+ |
Build from Source
git clone https://github.com/infracv/rf-detr-cpp.git
cd rf-detr-cpp
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_CUDA_ARCHITECTURES=120
cmake --build build -j$(nproc)
# Tarball TensorRT: add -DTENSORRT_DIR=/path/to/TensorRT
Replace 120 with your GPU's compute capability:
| GPU family | CMAKE_CUDA_ARCHITECTURES |
|---|---|
| RTX 30xx (Ampere) | 86 |
| RTX 40xx (Ada Lovelace) | 89 |
| RTX 50xx (Blackwell) | 120 |
| Jetson Orin | 87 |
| Thor / GH200 | 101 |
The default build (no -DCMAKE_CUDA_ARCHITECTURES) compiles for all five (86 87 89 101 120). Pass a single value to keep build times short.
Note: Always pass
-DCMAKE_CUDA_ARCHITECTURESexplicitly. If your environment has a stale value set (e.g. from a conda env), CMake will use that instead and the CUDA preprocessing kernel won't be optimized for your GPU.
Model Conversion
Python is only needed for this one-time conversion step. The C++ runtime requires no Python.
# Python deps (uv recommended)
uv venv --python 3.12 .venv && source .venv/bin/activate
uv pip install -r requirements.txt
# Export RF-DETR PyTorch → ONNX
python trt-files/scripts/export_onnx.py --variant nano --out-dir trt-files/onnx
# FP32 engine
./build/rfdetr_build --onnx trt-files/onnx/rf-detr-nano.onnx --precision fp32
# FP16 engine
./build/rfdetr_build --onnx trt-files/onnx/rf-detr-nano.onnx --precision fp16
For INT8 see trt-files/INT8_QUANTIZATION.md.
API Reference
Object Detection
#include "rfdetr/tasks/detector.hpp"
rfdetr::RFDetrDetector detector("rf-detr-nano-fp32.engine");
cv::Mat image = cv::imread("image.jpg");
rfdetr::Detections dets = detector.detect(image, /*threshold=*/0.5f);
for (const auto& d : dets)
std::printf("class=%d score=%.2f box=[%.1f %.1f %.1f %.1f]\n",
d.class_id, d.score, d.box.x1, d.box.y1, d.box.x2, d.box.y2);
rfdetr::draw_detections(image, dets);
cv::imwrite("out.jpg", image);
// Check whether CUDA Graph was captured at construction:
if (detector.cuda_graph_active())
std::puts("CUDA Graph active: lowest dispatch latency");
Instance Segmentation
#include "rfdetr/tasks/segmenter.hpp"
rfdetr::RFDetrSegmenter segmenter("rf-detr-seg-nano-fp16.engine");
cv::Mat image = cv::imread("image.jpg");
rfdetr::Detections dets = segmenter.segment(image, /*threshold=*/0.5f);
for (const auto& d : dets)
std::printf("class=%d score=%.2f mask=%dx%d (CV_8UC1)\n",
d.class_id, d.score, d.mask.cols, d.mask.rows);
rfdetr::draw_segmentations(image, dets);
rfdetr::draw_detections(image, dets);
cv::imwrite("out.jpg", image);
Each Detection.mask is a CV_8UC1 cv::Mat of the original image size, with values 0 or 255.
Batch Inference
Batching requires a dynamic-batch engine. Export the ONNX with
--dynamic-batch, then build with a profile:
python trt-files/scripts/export_onnx.py --variant nano --dynamic-batch \
--out-dir trt-files/onnx --name rf-detr-nano-dyn
./build/rfdetr_build --onnx trt-files/onnx/rf-detr-nano-dyn.onnx --precision fp16 \
--min-batch 1 --opt-batch 4 --max-batch 4
std::vector<cv::Mat> frames = { img0, img1, img2, img3 };
rfdetr::RFDetrDetector detector("rf-detr-nano-dyn-fp16.engine");
auto batch = detector.detect_batch(frames, 0.5f);
for (std::size_t i = 0; i < batch.size(); ++i)
std::printf("frame %zu: %zu detections\n", i, batch[i].size());
RFDetrSegmenter::segment_batch() works the same way. Note that batching speeds
up inference only — segmentation postprocessing scales with output resolution and
runs per image, so at high resolutions the end-to-end gain is small.
Batching raises throughput at the cost of per-image latency: nothing completes until the whole batch does. Prefer single-image inference for live feeds.
C ABI (Python / Rust / Go FFI)
Build with -DRFDETR_BUILD_C_API=ON to produce librfdetr_c.so:
#include "rfdetr/c_api.h"
rfdetr_detector_t* det = rfdetr_detector_create("model.engine", NULL);
rfdetr_detections_t* res = rfdetr_detector_detect(det, bgr_data, w, h, w*3, 0.5f);
for (int i = 0; i < res->count; ++i)
printf("cls=%d score=%.2f\n", res->detections[i].class_id, res->detections[i].score);
rfdetr_detections_free(res);
rfdetr_detector_destroy(det);
# Python via ctypes
import ctypes
lib = ctypes.CDLL("librfdetr_c.so")
# See include/rfdetr/c_api.h for the full binding
Benchmarks
NVIDIA RTX 5070 Ti, 500 iters, 50-iter warm-up, Batch 1.
| Task | Precision | FPS | Avg Latency | P50 | P99 | GPU Memory |
|---|---|---|---|---|---|---|
Detection (nano) | FP32 | 406 | 2.462 ms | 2.444 ms | 2.778 ms | 859 MB |
Detection (nano) | FP16 | 514 | 1.944 ms | 1.911 ms | 2.508 ms | 836 MB |
Segmentation (seg-nano) | FP32 | 112 | 8.906 ms | 8.817 ms | 10.243 ms | 892 MB |
Segmentation (seg-nano) | FP16 | 157 | 6.364 ms | 6.314 ms | 7.211 ms | 886 MB |
Numbers include the full pipeline: preprocessing, inference, and postprocessing. Segmentation mask decoding runs entirely on the GPU via a dedicated CUDA kernel.
500 iters, 50-iter warm-up, Batch 1.
| Task | Precision | FPS | Avg Latency | P50 | P99 |
|---|---|---|---|---|---|
Detection (nano) | FP16 | 120 | 8.302 ms | 7.766 ms | 12.829 ms |
Detection (nano) | FP32 | 50 | 19.984 ms | 18.858 ms | 33.003 ms |
Segmentation (seg-nano) | FP16 | 55 | 18.093 ms | 17.008 ms | 23.871 ms |
Segmentation (seg-nano) | FP32 | 24 | 42.292 ms | 42.047 ms | 45.436 ms |
GPU Memory column is omitted — Jetson uses unified CPU/GPU memory, so
cudaMemGetInforeports system memory rather than dedicated VRAM and the delta reads as zero. See the Benchmarking Guide for details.
See benchmarks/BENCHMARKING.md to reproduce these numbers or run your own benchmarks on any GPU.
License
Apache-2.0. See LICENSE.
Acknowledgments
- Roboflow RF-DETR for the model architecture and pretrained weights
- NVIDIA TensorRT for optimised GPU inference
- OpenCV for image I/O and visualisation
Contributing
We welcome and appreciate all contributions. If you notice any issues or bugs, have questions, or would like to suggest new features, please open an issue or pull request. By sharing your ideas and improvements, you help make RF-DETR C++ better for everyone.
See CONTRIBUTING.md for guidelines on setting up the dev environment, coding standards, and the PR process.