Instructions to use wonfy/BiRefNet-ONNX-webgpu with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers.js
How to use wonfy/BiRefNet-ONNX-webgpu with Transformers.js:
// npm i @huggingface/transformers import { pipeline } from '@huggingface/transformers'; // Allocate pipeline const pipe = await pipeline('image-segmentation', 'wonfy/BiRefNet-ONNX-webgpu');
BiRefNet, ONNX for WebGPU
BiRefNet for background removal, rebuilt so it runs on WebGPU in the browser. This is the full model with the Swin-L backbone. For the smaller one see wonfy/BiRefNet_lite-ONNX-webgpu. The weights are unchanged. Only the graph was rewritten, starting from onnx-community/BiRefNet-ONNX.
The stock export doesn't run on WebGPU. Some of its shaders need more storage buffers than a GPU allows (WebGPU only promises 8 per shader), and its int64 index maths and Sum nodes have no WebGPU kernels, so they fall back to the CPU with very large tensors.
| File | Precision | Size |
|---|---|---|
onnx/model.onnx |
fp32 | 1038 MB |
onnx/model_fp16.onnx |
fp16 weights, float32 input and output | 520 MB |
Input input_image: float32 [1, 3, 1024, 1024], RGB resized to 1024 x 1024, scaled to 0..1, then ImageNet mean [0.485, 0.456, 0.406] and std [0.229, 0.224, 0.225].
Output output_image: float32 [1, 1, 1024, 1024] logits. Apply a sigmoid to get the alpha mask.
What was changed
- Constant folding with ONNX Runtime's basic optimizer, which only produces standard ONNX ops. It takes the graph from 21,968 to 5,271 nodes and removes every shape op,
ScatterND,WhereandConstantOfShape. - 4
Concatnodes with 16, 64, 256 and 1024 inputs became trees with at most 6 inputs each. - 59
Splitnodes with up to 32 outputs became trees with at most 6 outputs each. - 20
Sumnodes became chains ofAddin the same order, so the result stays bit-identical. - 80
GatherNDnodes (the sampling in the deformable convolutions) became a plainGatheron the data reshaped to[H*W, C]. Their index maths, which was int64, now runs in float (the values are whole numbers), theny * W + xis taken in int32. No int64 tensor is left in the graph. Doing the last step in int32 also keeps the index exact in the fp16 model. - fp16: converted with
onnxconverter-commonandkeep_io_types, so input and output stay float32.
Every node now uses at most 7 storage buffers, under the WebGPU minimum of 8.
Results
On the CPU (ONNX Runtime 1.31, three test images: hair, a car and two cats), compared with the original onnx-community fp32 model:
| File | Logits | Alpha mask |
|---|---|---|
model.onnx |
bit-identical, max difference 0.0 | identical |
model_fp16.onnx |
max difference 0.06 to 1.25 | mean difference under 1e-5, at most 0.02% of pixels move by more than 1/255 |
On WebGPU (Chrome 155, AMD Radeon RX 9070 XT, Transformers.js 4.3.1 with ONNX Runtime Web 1.31.0-dev.20260914), model_fp16.onnx on the same three inputs:
- About 800 ms per image once warm, about 4.3 s to load.
- 0.5% to 1.3% of pixels move by more than 1/255 from the fp32 CPU result, and 0.01% to 0.02% of pixels change between inside and outside, all of them on edges.
The fp32 file is about 1 GB. ONNX Runtime Web reads the whole model into WebAssembly memory before it moves it to the GPU, so the fp16 file is the safer choice in a browser.
Use it
With Transformers.js:
import { AutoModel, AutoProcessor, RawImage } from "@huggingface/transformers";
const model = await AutoModel.from_pretrained("wonfy/BiRefNet-ONNX-webgpu", {
device: "webgpu",
dtype: "fp32",
model_file_name: "model_fp16", // leave this out for the fp32 file
});
const processor = await AutoProcessor.from_pretrained("wonfy/BiRefNet-ONNX-webgpu");
const image = await RawImage.fromURL("photo.jpg");
const { pixel_values } = await processor(image);
const { output_image } = await model({ input_image: pixel_values });
// alpha = sigmoid(output_image.data[i]), at 1024 x 1024
dtype: "fp32" with model_file_name: "model_fp16" is the combination that was tested. It loads the fp16 file as it is.
With ONNX Runtime Web directly, create an InferenceSession from either file with executionProviders: ["webgpu"].
Rebuild it
The scripts are in scripts/. They were run with Python 3.13, onnx 1.23.2, onnxruntime 1.31.0, onnxconverter-common 1.16.0, numpy and Pillow.
python scripts/fold.py model.onnx folded.onnx
python scripts/patch.py folded.onnx onnx/model.onnx
python scripts/to_fp16.py onnx/model.onnx onnx/model_fp16.onnx
python scripts/verify.py samples/ results/ model.onnx onnx/model.onnx onnx/model_fp16.onnx
model.onnx in the first line is the fp32 file from onnx-community/BiRefNet-ONNX. patch.py prints an audit at the end: the most storage buffers any node uses, and any op still producing int64.
Licence
MIT, the same as BiRefNet. See LICENSE. BiRefNet is by Peng Zheng et al., paper and code.
BiRefNet's training data includes DIS5K, and DIS5K's own terms restrict commercial use of the dataset. The MIT licence covers the model and code, not the training data. Check what that means for your use.
- Downloads last month
- -
Model tree for wonfy/BiRefNet-ONNX-webgpu
Base model
ZhengPeng7/BiRefNet