Pure Rust inference for the nobg BiRefNet background remover. It loads the HuggingFace checkpoint directly and produces transparent RGBA cutouts. No Python, no PyTorch, no ONNX. Runs entirely on CPU.
Built on candle and the candle-birefnet reference port (Apache-2.0). See DESIGN.md for the architecture report.
The crate supports two BiRefNet checkpoints with the same feynobg architecture:
| Model | Backbone | Size | Quality | CPU speed (512) |
|---|---|---|---|---|
feyninc/FeyNobg |
Swin-L | ~1.1 GB | reference | ~7 s |
ZhengPeng7/BiRefNet_lite |
Swin-T | ~110 MB | IoU 0.982 versus golden | ~1.7 s |
ZhengPeng7/BiRefNet_lite is the DIS5K lite leader. The e2e test verifies its cutout parity against the nobg Python golden. The test runs at 1024 and requires IoU >= 0.95. Use the lite model for CPU inference. The example defaults to feyninc/FeyNobg. Pass --model ZhengPeng7/BiRefNet_lite to select the lite model.
cargo run --example remove_bg --release -- \
--model ZhengPeng7/BiRefNet_lite \
--image input.jpg \
--output out.png \
--size 512The first run downloads the checkpoint (about 110 MB for the lite) and caches it. Subsequent runs reuse the cache. --size 512 is the recommended resolution for CPU inference (about 1.7 s per image on an 8-physical-core AVX2 machine). Use --size 1024 when quality matters more than speed.
use feynobg::{BiRefNet, BiRefNetImageProcessor};
let device = candle_core::Device::Cpu;
let (model, _config) = BiRefNet::from_pretrained_lite("ZhengPeng7/BiRefNet_lite", &device)?;
let processor = BiRefNetImageProcessor::new(512);
let (tensor, original, orig_w, orig_h) = processor.preprocess("input.jpg", &device)?;
let outputs = model.forward(&tensor)?;
let alpha = processor.post_process_alpha_matting(&outputs[0], orig_h as usize, orig_w as usize)?;
let cutout = BiRefNetImageProcessor::cutout(&original, &alpha);
cutout.save("out.png")?;Use BiRefNet::from_pretrained("feyninc/FeyNobg", &device) for the full-size model.
birefnet- the BiRefNet model and forward pass (Swin backbone, ASPP, decoder, gradient attention, input patching).loader- the loader for both checkpoints, including the legacy state-dict remap for the lite.config- theBiRefNetConfigparser forconfig.json.processor- theBiRefNetImageProcessorwith preprocess, post_process_alpha_matting, and cutout.decoder,aspp- the decoder blocks and the ASPP deformable convolutions.fast_conv- custom NCHW im2col + gemm convolutions (k1, k3, k7) that replace the slow candle tiled path.deform_conv2d- the deformable convolution wrapper with tiled offset heads and tiled modulator heads.gemm_fast- direct gemm-crate matmuls that bypass the candle matmul wrapper.
The vendor/candle-swin and vendor/candle-dcnv2 crates provide the Swin transformer and the deformable convolution kernel with hand-optimized AVX2/FMA paths.
The checkpoint uses the nobg 0.2.0 key layout.
The feyninc/FeyNobg checkpoint uses strict loading. All 887 learnable tensors map to model parameters. The mapping has zero missing keys and zero unexpected keys. The 43 num_batches_tracked buffers are training-only. The inference path does not consume them.
The ZhengPeng7/BiRefNet_lite checkpoint uses the legacy state-dict layout. The loader remaps it at load time:
- Split the fused
qkvintoq_proj,k_proj, andv_proj. - Renumber the decoder block indices.
- Drop
relative_position_index. - Skip the optional stage LayerNorm when it is absent.
All 622 tensors map cleanly.
The measurements come from a machine with 8 physical x86_64 AVX2 cores. The machine has no GPU and no system BLAS.
- The lite model at 512 runs one inference in about 1.7 s.
- Set
RAYON_NUM_THREADS=8to use physical cores only. Hyper-threading hurts this gemm-bound workload on this machine. - The hot kernels are a direct gemm-crate F32 matmul path and an AVX2/FMA window attention with register blocking. The other hot paths are a tiled deformable convolution and a vectorized GELU.
cargo test --release # unit tests (no download)
cargo test --release -- --ignored # include the e2e and strict-loading tests
cargo test --release --test e2e_lite -- --ignored --nocapture # lite parity at 1024 (IoU >= 0.95)Inference only. Out of scope: training, fine-tuning, re-parameterization, push-to-hub, GPU or half-precision inference, and video batching.
Apache-2.0, same as the upstream candle-birefnet project.