kocabiyik's picture
Upload README.md with huggingface_hub
47a0c1d verified
|
Raw
History Blame Contribute Delete
8.09 kB
metadata
license: apache-2.0
library_name: onnxruntime
tags:
  - background-removal
  - image-segmentation
  - alpha-matting
  - onnx
  - computer-vision
  - remove-background
pipeline_tag: image-segmentation

withoutBG Open Weights (ONNX)

Open-source background removal and alpha matting from RGB images. This repository hosts the OSS variant exported as a self-contained ONNX graph for ONNX Runtime.

The graph includes DepthAnythingV2 and a ConvNeXt-fused matting head — no PyTorch checkpoints are needed at inference time.

See the results

Example 1 Example 2 Example 3

Open Weights results → · Cloud API results → · Compare →

Model details

Field Value
Variant oss
Version 10.0.0
Format ONNX (opset 18)
Precision fp32
Max resolution 448
ONNX input tensor 448 × 448 (fixed letterbox)
ONNX output tensor 448 × 448
Depth DepthAnythingV2 vits (dav2s)
Matting ConvNeXtFusedMattingUNet (DINOv3 ConvNeXt base)
Transformer opt disabled
ORT offline opt extended
Size ~455 MB
SHA256 29930e48e9d5ecc56d6486c53c35a4c1470566c2a3359fa180b08c8d3c34ef0f

Files

Always distribute the ONNX file and its sidecar JSON together:

  • withoutbg-open-weights.onnx — inference graph (depth → ConvNeXt matting)
  • withoutbg-open-weights.onnx.json — sidecar metadata (I/O names, shapes, SHA256, canvas size)

Read the sidecar first. It is the authoritative source for canvas_size (448), input/output names, precision, model version, depth_variant, convnext_size, and SHA256.

Architecture

v10 pipeline:

  • Depth: DepthAnythingV2 vits (dav2s)
  • Matting: ConvNeXtFusedMattingUNet — frozen DINOv3 ConvNeXt backbone fused into a U-Net on 4-channel RGB+depth at 448²

Consumers letterbox RGB to the fixed ONNX input tensor (canvas_size in the sidecar) and run a single inference session. Depth is computed inside the graph.

Input / output contract

Max resolution is 448px. Input letterboxing and output alpha both use canvas_size (448).

The graph expects a letterboxed RGB tensor sized to canvas_size from the sidecar:

Name Shape Dtype Range
Input rgb [1, 3, 448, 448] float32 [0, 1], NCHW
Output alpha [1, 1, 448, 448] float32 [0, 1]

Preprocessing (required):

  1. Convert image to RGB.
  2. Read canvas_size from the sidecar (448 for this export).
  3. Resize longest side to canvas_size, preserve aspect ratio.
  4. Paste at top-left on a black canvas_size × canvas_size canvas.
  5. Normalize to float32 [0, 1], transpose HWC → CHW, add batch dim.

Postprocessing (required):

  1. Crop alpha to the resized image region (top-left, before padding).
  2. Resize alpha back to the original image dimensions.
  3. Attach as PNG alpha channel for cutout output.

Download

from huggingface_hub import hf_hub_download

model_path = hf_hub_download(
    repo_id="withoutbg/withoutbg-openweights-onnx",
    filename="withoutbg-open-weights.onnx",
)
sidecar_path = hf_hub_download(
    repo_id="withoutbg/withoutbg-openweights-onnx",
    filename="withoutbg-open-weights.onnx.json",
)

Or with the CLI:

hf download withoutbg/withoutbg-openweights-onnx \
  withoutbg-open-weights.onnx \
  withoutbg-open-weights.onnx.json

Usage

from pathlib import Path
import json
import numpy as np
import onnxruntime as ort
from PIL import Image

model_path = Path("withoutbg-open-weights.onnx")
sidecar = json.loads(model_path.with_suffix(model_path.suffix + ".json").read_text())
canvas = sidecar.get("canvas_size", 448)
input_name = sidecar.get("input_name", "rgb")

session = ort.InferenceSession(str(model_path), providers=["CPUExecutionProvider"])

image = Image.open("input.jpg").convert("RGB")
orig_w, orig_h = image.size
scale = canvas / max(orig_w, orig_h)
new_w = max(1, round(orig_w * scale))
new_h = max(1, round(orig_h * scale))

resized = image.resize((new_w, new_h), Image.Resampling.BILINEAR)
padded = Image.new("RGB", (canvas, canvas), (0, 0, 0))
padded.paste(resized, (0, 0))

rgb = np.asarray(padded, dtype=np.float32) / 255.0
rgb = np.transpose(rgb, (2, 0, 1))[None, ...]

alpha_canvas = session.run(None, {input_name: rgb})[0][0, 0]
alpha_crop = alpha_canvas[:new_h, :new_w]
alpha_u8 = np.clip(alpha_crop * 255.0, 0, 255).astype(np.uint8)
alpha = Image.fromarray(alpha_u8, "L").resize((orig_w, orig_h), Image.Resampling.BILINEAR)

out = image.copy()
out.putalpha(alpha)
out.save("output.png")

Runtime dependencies

python >=3.11
numpy
pillow
onnxruntime

For Hugging Face downloads, also install huggingface_hub.

More than weights

This repo hosts the ONNX weights. Same open-weights technology powers ready-made surfaces:

Surface Choose when
Python package You want to embed withoutBG in scripts, notebooks, or backends
Docker / self-host You want an HTTP API or browser UI on your own server (CPU or NVIDIA GPU)
Mac app You want a native desktop cutout tool, with an optional Local API for plugins and scripts
GIMP plugin You edit in GIMP 3 and want a private, mask-first workflow via Mac Local API or Docker
Space You want to try a browser demo
Cloud API You need maximum quality without running inference yourself

License

Apache-2.0 — see withoutbg.com/open-model/license.

Built with DINOv3.

Third-party terms

This distribution includes upstream components under their respective licenses. See THIRD_PARTY_NOTICES.md.

DINOv3

License: DINOv3 License

Depth Anything V2

License: Apache-2.0 — Depth Anything V2

Links