Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

feynobg

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.

Models

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.

Quick Start

cargo run --example remove_bg --release -- \
  --model ZhengPeng7/BiRefNet_lite \
  --image input.jpg \
  --output out.png \
  --size 512

The 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.

Library API

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.

Modules

  • 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 - the BiRefNetConfig parser for config.json.
  • processor - the BiRefNetImageProcessor with 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.

Checkpoint loading

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 qkv into q_proj, k_proj, and v_proj.
  • Renumber the decoder block indices.
  • Drop relative_position_index.
  • Skip the optional stage LayerNorm when it is absent.

All 622 tensors map cleanly.

CPU performance notes

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=8 to 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.

Tests

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)

Status

Inference only. Out of scope: training, fine-tuning, re-parameterization, push-to-hub, GPU or half-precision inference, and video batching.

License

Apache-2.0, same as the upstream candle-birefnet project.

About

Rust FeyNoBg implementation

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages