Cutie 视频物体分割(VOS)模型的 C++ 推理库。参考 lite.ai.toolkit 的多后端架构,将 PyTorch 推理流程移植为纯 C++17 动态库,支持有状态多帧视频推理。
- 纯 C++17:零 Python 依赖,可直接嵌入生产系统
- 多推理后端:
- ONNX Runtime(默认):含 CUDA EP,兼容性好,使用 IO Binding 避免 CPU↔GPU 数据拷贝
- TensorRT(可选):高性能推理,支持 FP16/INT8 量化,智能引擎缓存(节省 10-60 秒启动时间)
- 全 GPU 数据流:输入图像 CPU→GPU 上传后,所有中间特征和内存数据保持在 GPU,仅最终结果按需下载
- GPU 加速预处理:BGR→RGB 转换、resize、ImageNet 归一化、pad 全部在 GPU 上完成
- 完整的有状态推理:工作记忆(FIFO KV 缓冲)+ 长期记忆(可选压缩原型)+ 感知记忆(per-object GRU 隐状态)
- 多对象跟踪:支持同时跟踪多个对象,支持中途删除对象
- RAII 风格 API:单头文件
#include "cutie/cutie.h"即可使用
Cutie 提供 base 和 small 两种变体,每种变体再按训练数据分为三个权重文件,共 6 个 .pth:
| 变体 | 骨干网络 | 特征维度 (f16/f8/f4) | 适用场景 |
|---|---|---|---|
| base | ResNet-50 | 1024 / 512 / 256 | 精度优先,GPU 推理 |
| small | ResNet-18 | 256 / 128 / 64 | 速度/显存受限场景 |
| 文件名 | 训练数据 | 说明 |
|---|---|---|
cutie-base-mega.pth |
MEGA 数据集(最大量) | base 变体最强精度,推荐首选 |
cutie-base-nomose.pth |
不含 MOSE 数据集 | 适用于 MOSE benchmark 评测对照 |
cutie-base-wmose.pth |
含 MOSE 数据集 | 遮挡场景更鲁棒 |
cutie-small-mega.pth |
MEGA 数据集 | small 变体最强精度 |
cutie-small-nomose.pth |
不含 MOSE | small 变体,MOSE 评测对照 |
cutie-small-wmose.pth |
含 MOSE | small 变体,遮挡更强 |
简单选择原则:不确定用哪个时,选
cutie-base-mega(精度最高)或cutie-small-mega(速度优先)。
Cutie 的推理被拆分为 6 个 ONNX 子模块,在每帧推理时按顺序调用:
image ──► pixel_encoder ──► f16, f8, f4, pix_feat
│
f16 ──► key_projection ──► key, shrinkage, selection
│
pix_feat + sensory + masks ──► mask_encoder ──► value, sensory, summaries
│
pix_feat + pixel + sensory + last_mask ──► pixel_fuser ──► fused_pixel
│
pixel_readout + obj_memory ──► object_transformer ──► updated_readout
│
f8 + f4 + readout + sensory ──► mask_decoder ──► new_sensory, logits → mask
| 子模块 | 输入 | 输出 | 作用 |
|---|---|---|---|
pixel_encoder |
image [1,3,H,W] |
f16/f8/f4/pix_feat | 多尺度图像特征提取(ResNet 骨干) |
key_projection |
f16 | key, shrinkage, selection | 生成记忆检索用的 key 向量 |
mask_encoder |
pix_feat + sensory + masks | value, sensory, summaries | 将 mask 编码进记忆 value |
pixel_fuser |
pix_feat + pixel + sensory + last_mask | fused_pixel | 融合像素特征与记忆读出 |
object_transformer |
pixel_readout + obj_memory | updated_readout | Transformer 跨对象注意力 |
mask_decoder |
f8 + f4 + readout + sensory | sensory, logits | 解码最终分割 logits |
| 记忆类型 | 说明 | 配置参数 |
|---|---|---|
| 工作记忆 | 最近 N 帧,时序 KV 缓冲,FIFO 淘汰 | mem_every, max_mem_frames |
| 长期记忆 | 可选,基于使用量压缩的原型记忆 | use_long_term, long_term.* |
| 感知记忆 | per-object GRU 隐状态,每帧更新 | sensory_dim(自动按变体设置) |
| 依赖 | 版本 | 必需 |
|---|---|---|
| CMake | ≥ 3.20 | ✅ |
| GCC/Clang | GCC ≥ 9 | ✅ |
| OpenCV | ≥ 4.0(含 CUDA 模块) | ✅ |
| CUDA Toolkit | ≥ 11.8 | ✅ |
| cuBLAS | (CUDA Toolkit 自带) | ✅ |
| ONNX Runtime | ≥ 1.16(含 CUDA EP) | ONNX 后端 |
| TensorRT | ≥ 10.0 | TRT 后端 |
| linden_logger | (子项目,自动加载) | ✅ |
注意:项目现在要求 CUDA ≥ 11.8,构建时必须确保 CUDA Toolkit 已正确安装并可被 CMake 检测到。
# 默认构建(ONNX Runtime 后端,Release 模式)
bash build.sh --vcpkg-root ./vcpkg/
# Debug 构建
bash build.sh --debug --vcpkg-root ./vcpkg/
# 清理重建
bash build.sh --clean
# 指定自定义依赖路径
bash build.sh --cuda-root /usr/local/cuda --onnxruntime-root /opt/onnxruntime
# 启用 TensorRT 后端
bash build.sh --enable-tensorrt --vcpkg-root ./vcpkg/
# 同时启用两个后端
bash build.sh --enable-onnxruntime --enable-tensorrt --vcpkg-root ./vcpkg/编译产物(默认输出到 build/ 目录):
build/libcutie.so— 动态库build/demo_basic— 示例程序
安装(可选):
bash install.sh
# 或
cmake --install build/从 .pth 权重文件导出 6 个 ONNX 子模块(需要 Python + PyTorch 环境):
cd share/scripts
# 导出 base-mega 权重
python export_onnx.py \
--variant base \
--weights ../model/cutie-base-mega.pth \
--output ../model/
# 导出 small-mega 权重
python export_onnx.py \
--variant small \
--weights ../model/cutie-small-mega.pth \
--output ../model/导出后在 share/model/ 目录下生成(以 cutie-base-mega 为例):
cutie-base-mega_pixel_encoder.onnx
cutie-base-mega_key_projection.onnx
cutie-base-mega_mask_encoder.onnx
cutie-base-mega_pixel_fuser.onnx
cutie-base-mega_object_transformer.onnx
cutie-base-mega_mask_decoder.onnx
ONNX 文件以权重文件名(去扩展名)为前缀,C++ 加载时通过
model_prefix字段定位。
注意:导出脚本对
downsample_groups进行了 monkey-patch,将不兼容 ONNX 导出的F.interpolate(mode='area')替换为等价的F.avg_pool2d。
#include "cutie/cutie.h"
using namespace cutie::cv::segmentation;
// 1. 创建配置(base 变体默认参数)
auto config = CutieConfig::base_default("/path/to/model/dir");
config.model_prefix = "cutie-base-mega"; // 对应 cutie-base-mega_*.onnx
config.use_long_term = true; // 启用长期记忆(可选)
// 2. 创建处理器(加载 ONNX,初始化推理 session)
CutieProcessor processor(config);
// 3. 首帧:提供图像 + 分割 mask + 对象 ID 列表
cv::Mat frame0 = cv::imread("frame_000.jpg");
cv::Mat mask0 = cv::imread("mask_000.png", cv::IMREAD_GRAYSCALE); // 像素值 = 对象 ID
auto result = processor.step(frame0, mask0, {1, 2, 3});
// 4. 后续帧:仅提供图像,自动传播分割
// (内部自动完成 GPU 预处理、特征提取、内存管理、分割解码)
for (auto& frame : remaining_frames) {
auto result = processor.step(frame);
// result.index_mask — H×W CV_32SC1,像素值为对象 ID(0 = 背景)
// result.object_ids — 当前活跃对象列表
}
// 5. 中途对象管理(可选)
processor.delete_objects({2}); // 删除对象 2
processor.clear_non_permanent_memory(); // 清除非永久记忆性能提示:内部已全 GPU 化,CPU
cv::Mat输入会自动上传到 GPU 并缓存,所有中间计算在 GPU 完成,最终结果下载到 CPU 返回。对于高吞吐场景,可考虑使用cv::cuda::GpuMat直接传入(需要相应 API 扩展)。
本库提供 Python 接口 cutie_cpp,用 numpy 数组完成推理,无需 PyTorch 依赖。
每帧只有一次 H2D 上传和一次 D2H 下载,性能与 C++ 直接调用相当。
# 方式一:安装为 wheel
pip install .
# 方式二:CMake 构建(扩展模块就地输出到 python/cutie_cpp/)
bash build.sh --enable-python --vcpkg-root ./vcpkg/
export PYTHONPATH=$PWD/pythonimport cutie_cpp
cutie_cpp.setup_logging()
config = cutie_cpp.CutieConfig.base_default("share/model")
with cutie_cpp.VideoSegmenter(config) as segmenter:
result = segmenter.step(first_frame, mask=first_mask) # 首帧给掩码
for frame in frames:
result = segmenter.step(frame) # 后续帧自动跟踪
result.index_mask # (H, W) int32,像素值 = 对象 ID详细的 API 说明、配置项与示例见 python/README.md, 可运行示例在 python/examples/。
项目目前唯一可运行的示例为:
# 基本用法
./build/demo_basic <video_path> <first_frame_mask.png>demo_basic 会自动扫描模型目录中 *_pixel_encoder.onnx 文件推断 model_prefix,无需手动指定。示例会逐帧处理视频,输出分割结果到控制台。
struct CutieConfig {
ModelVariant variant = ModelVariant::kBase;
std::string model_dir; // ONNX 文件所在目录
std::string model_prefix; // 必填:对应 .pth 文件名(不含扩展名)
Device device = Device::kCUDA; // kCPU 或 kCUDA
int device_id = 0;
// 推理参数
int max_internal_size = 480; // 长边 resize 目标(像素)
int mem_every = 5; // 每 N 帧写入工作记忆
int top_k = 30; // 记忆注意力 top-k
int chunk_size = -1; // 分块推理(-1 = 不分块)
int stagger_updates = 5; // 交错更新间隔
bool single_object = false; // 单对象模式(跳过多对象融合)
// 工作记忆
int max_mem_frames = 5;
// 长期记忆(use_long_term = true 时生效)
bool use_long_term = false;
struct LongTermConfig {
bool count_usage = true;
int max_mem_frames = 10;
int min_mem_frames = 5;
int num_prototypes = 128;
int max_num_tokens = 10000;
int buffer_tokens = 2000;
} long_term;
};cutie-cpp/
├── include/cutie/ # 公共头文件
│ ├── cutie.h # 统一入口头文件
│ ├── types.h # CutieMask, ObjectId, 枚举
│ ├── models.h # 命名空间别名
│ └── core/
│ └── processor.h # CutieConfig, CutieProcessor 声明
├── src/ # 实现源码
│ ├── common/ # GPU 公共代码(ORT 和 TRT 后端共享)
│ │ ├── cuda_kernels.cu # CUDA kernel 实现
│ │ ├── gpu_memory.cpp # GPU 内存分配器
│ │ ├── gpu_tensor_ops.cpp # GPU 张量操作原语
│ │ ├── gpu_image_preprocess.cu # GPU 图像预处理
│ │ ├── gpu_mask_preprocess.cu # GPU 掩码预处理
│ │ └── gpu_postprocess.cu # GPU 后处理
│ ├── core/ # 与平台无关的推理逻辑
│ │ ├── inference_core.cpp # 主推理循环
│ │ ├── memory_manager.cpp # 三层内存系统
│ │ ├── kv_memory_store.cpp # KV 内存存储
│ │ ├── object_manager.cpp # 对象管理
│ │ └── processor.cpp # 公共 API 实现
│ ├── ort/ # ONNX Runtime 后端
│ │ ├── ort_handler.cpp # 会话管理
│ │ └── ort_cutie.cpp # 6 个子模块封装
│ └── trt/ # TensorRT 后端
│ ├── trt_engine_builder.cpp # 引擎构建
│ ├── trt_handler.cpp # 引擎管理
│ └── trt_cutie.cpp # 6 个子模块封装
├── examples/
│ └── demo_basic.cpp # 基础使用示例
├── share/
│ ├── docs/ # API 参考文档、需求文档
│ ├── model/ # .pth 权重文件 & 导出的 ONNX 文件
│ └── scripts/
│ └── export_onnx.py # PyTorch → ONNX 导出脚本
├── .ref_project/ # 参考项目(不提交到 Git)
│ ├── Cutie/ # 原始 PyTorch 实现
│ └── linden_logger/ # 专有日志库
├── cmake/ # CMake 查找模块
├── build.sh # 一键编译脚本
└── install.sh # 安装脚本
见 LICENSE。
原始 Cutie 模型版权归 Ho Kei Cheng 所有,请遵守其许可证。