Background removal
MODNet (portraits)
Separates a person from the background with a soft alpha matte, hair and edges included. Apache-2.0.
About this model
MODNet removes the background behind people. For every pixel it gives how much of it belongs to the person, from 0 (background) to 1 (person), so hair and soft edges blend cleanly into a new background instead of being cut along a hard line.
This is the photographic portrait model from the authors (6.5 million parameters, MobileNetV2 backbone). It needs no trimap or second photo of the empty background.
What you can build
- Background replacement and blur for video calls
- Product-style cutouts of people for photo apps
- Stickers and portraits on a transparent background
- Privacy: hide what is behind the person
Man with beard portrait
f16ThuyHaBich, CC0, https://commons.wikimedia.org/wiki/File:Bearded_man_smoking_pipe-3013924.jpg
Matte on the Metal (FP16 pack); 43% of the photo is person (alpha above one half). Shown over a checkerboard.
People at market
f16Wilfredor, CC0, https://commons.wikimedia.org/wiki/File:Fishmonger_smiling,_Maracaibo_street_market,_Venezuela.jpg
Matte on the Metal (FP16 pack); 42% of the photo is person (alpha above one half). Shown over a checkerboard.
Basketball players
f16LTx Domas, CC0, https://commons.wikimedia.org/wiki/File:Basketball_player_13.jpg
Matte on the Metal (FP16 pack); 56% of the photo is person (alpha above one half). Shown over a checkerboard.
Variants & downloads
Choose the build for your appModel files are hosted on Google Drive. Large files may open a confirmation page before downloading.
Standard
SlabWeights stored in FP16: half the size of FP32, the same results (see Accuracy).
Platforms: macos · android
modnet-f16.slab
15.1 MB · Hosted download
SHA-256 checksum
fd2be360a831843106d4cc73d311899009b8c94a7032c2ee4745a3332e06f4d9LICENSE-MODNet.txt
11 KB
SHA-256 checksum
c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4Conversion details
- command
- git clone https://github.com/ZHKKKe/MODNet && git -C MODNet checkout 28165a451e4610c9d77cfdf925a94610bb2810fb # run the export next to MODNet/, not inside it: its onnx/ folder hides the onnx package gdown --folder https://drive.google.com/drive/folders/1umYmlCulvIFNaqPjwod1SayFmSRHziyR -O MODNet/pretrained # the README's Google Drive folder (pip install gdown) python -c "import sys, torch, importlib.util as u; sys.path.append('MODNet'); s = u.spec_from_file_location('m', 'MODNet/onnx/modnet_onnx.py'); m = u.module_from_spec(s); s.loader.exec_module(m); net = m.MODNet(backbone_pretrained=False); sd = torch.load('MODNet/pretrained/modnet_photographic_portrait_matting.ckpt', map_location='cpu', weights_only=True); net.load_state_dict({k[7:]: v for k, v in sd.items()}); torch.onnx.export(net.eval(), torch.randn(1, 3, 512, 512), 'model.onnx', input_names=['input'], output_names=['output'], opset_version=17, dynamo=False)" slab-load convert model.onnx model.slab --input input=1x3x512x512 --meta task=segment --meta resize=stretch --meta antialias:bool=true --meta normalize=neg_one_to_one --meta color=rgb slab-load quantize model.slab modnet-f16.slab --f16 slab-load meta set modnet-f16.slab default_backend.macos=gpu
Integration examples
Python
python
import slab
cfg = slab.Config(cache_dir="/tmp/slab_cache", license=open("license.slablic.txt").read())
session = slab.Session(cfg, "modnet-f16.slab", warmup=True)
photo = slab.Frame.open("photo.jpg")
out = session.run(slab.Input(frame=photo))
alpha = out.matte() # Gray8 Frame, the photo's size
cutout = photo.with_alpha(alpha) # RGBA8 Frame, background transparent
print(cutout.width, cutout.height)
Device & backend compatibility
Pack default: macos / GPU. The fastest backend on the Mac (about 10 ms per frame); the Neural Engine takes 14 ms.
| Platform | Engine | Status | Precision |
|---|---|---|---|
| apple | CPU CPU | Supported Measured on macOS. | f32 |
| apple | Metal GPU | Supported Measured on macOS. The default. | f32 |
| apple | Apple Neural Engine NPU | Supported Measured on macOS. The Neural Engine computes in FP16. | f16 |
| android | CPU CPU | Supported Measured on a Samsung Galaxy S23 Ultra (Snapdragon 8 Gen 2, Adreno 740), Android 17. | f32 |
| android | Vulkan GPU | Supported Measured on a Samsung Galaxy S23 Ultra (Snapdragon 8 Gen 2, Adreno 740), Android 17. | f32 |
| android | Qualcomm Hexagon NPU (QNN) NPU | Not supported Tried on a Samsung Galaxy S23 Ultra (Hexagon v73): Slab's QNN backend has no translation for Expand yet. | — |
Performance
Results depend on the device, runtime, and test conditions. Each measurement keeps its own context.
Mac with Apple M1 Max
Slab · CPU
macOS 26.6.2
141.0 ms
Measured time · scope below
Median of 100 warm runs of the model (Slab's run time). From a 1920 x 1080 photo, resizing included: 140.43 ms median. matte() at 1920 x 1080 adds about 3 ms.
Mac with Apple M1 Max
Slab · GPU
macOS 26.6.2
10.4 ms
Measured time · scope below
Median of 100 warm runs of the model (Slab's run time). From a 1920 x 1080 photo, resizing included: 12.32 ms median. matte() at 1920 x 1080 adds about 3 ms.
Mac with Apple M1 Max
Slab · NPU
macOS 26.6.2
13.8 ms
Measured time · scope below
Median of 100 warm runs of the model (Slab's run time). From a 1920 x 1080 photo, resizing included: 15.67 ms median. matte() at 1920 x 1080 adds about 3 ms.
Samsung Galaxy S23 Ultra (Snapdragon 8 Gen 2)
Slab · CPU
Android 17
631.0 ms
Measured time · scope below
Median of 19 warm runs of the model (Slab's run time). From a 1920 x 1080 photo, resizing included: 614 ms median. open_ms: opening the session. Peak memory (resident) after the runs: 393 MB.
Samsung Galaxy S23 Ultra (Snapdragon 8 Gen 2)
Slab · GPU
Android 17
143.0 ms
Measured time · scope below
Median of 68 warm runs of the model (Slab's run time). From a 1920 x 1080 photo, resizing included: 146 ms median. open_ms: opening the session with the GPU programs already in the cache folder (the first open on a device compiles them, about 0.3 s more). Peak memory (resident) after the runs: 102 MB.
Accuracy checks
macos · CPU · f16
The upstream PyTorch model, 41 public-domain and CC0 photos of people (Wikimedia Commons). Same size: PyTorch on the same 512 x 512 stretch, its matte resized back bilinearly. Upstream script: MODNet's own inference (aspect kept, about 512 on the short side). Differences are mean |alpha| on a 0..1 scale
With Slab preprocessing and matte(): 0.19% mean difference to the same-size PyTorch matte (1.10% on the worst photo). On identical input tensors: 0.062%. Against MODNet's own script, which keeps the aspect ratio: 6.5% (25.5% on the worst photo).
macos · GPU · f16
The upstream PyTorch model, 41 public-domain and CC0 photos of people (Wikimedia Commons). Same size: PyTorch on the same 512 x 512 stretch, its matte resized back bilinearly. Upstream script: MODNet's own inference (aspect kept, about 512 on the short side). Differences are mean |alpha| on a 0..1 scale
With Slab preprocessing and matte(): 0.19% mean difference to the same-size PyTorch matte (1.10% on the worst photo). On identical input tensors: 0.062%. Against MODNet's own script, which keeps the aspect ratio: 6.5% (25.5% on the worst photo).
macos · NPU · f16
The upstream PyTorch model, 41 public-domain and CC0 photos of people (Wikimedia Commons). Same size: PyTorch on the same 512 x 512 stretch, its matte resized back bilinearly. Upstream script: MODNet's own inference (aspect kept, about 512 on the short side). Differences are mean |alpha| on a 0..1 scale
With Slab preprocessing and matte(): 0.20% mean difference to the same-size PyTorch matte (1.09% on the worst photo). On identical input tensors: 0.094%. Against MODNet's own script, which keeps the aspect ratio: 6.5% (25.5% on the worst photo).
Before you choose this model
- Made for photos of people; other subjects are not reliably separated.
- The pack runs at a fixed 512 x 512 and stretches the photo to it. MODNet's own script keeps the aspect ratio, and its mattes differ from the pack's by 6.5% on average across our photos (up to 26% on one). Converting at your camera's aspect ratio removes most of that: at 512 x 672 for 4:3 landscape photos, the difference dropped to 0.45%.
- Crowds and people far from the camera are separated less cleanly.