AI segmentation (SegmentationBiRefNet)¶
End-user guide for the AI-powered foreground/background segmentation
node shipped with this port. The architecture deep-dive is at
dev/segmentation-pipeline.md; this
page covers what an operator needs to run the node.
What is segmentation?¶
In photogrammetry, segmentation produces a per-view binary mask that
labels each pixel as foreground (the object you want to reconstruct)
or background (everything else — sky, walls, turntable, capture rig).
Downstream nodes (DepthMap, Meshing, Texturing) consume those masks
to restrict reconstruction to the foreground region, which improves
geometric accuracy on the subject and avoids wasting compute on the
background.
Typical uses on this Mac port:
- Object scans — turntable captures of a single subject; mask out the table, backdrop, and floor.
- Outdoor objects — statue, vehicle, building façade; mask out sky, people, vegetation that moves between frames.
- Background-only reconstruction — invert the masks to reconstruct only the static environment.
SegmentationBiRefNet uses BiRefNet
loaded as a pre-converted CoreML .mlpackage and dispatched on the
Apple Silicon GPU via MLComputeUnits.cpuAndGPU.
The Apple Neural Engine is intentionally NOT used
BiRefNet's ASPPDeformable decoder requires deformable convolution
v2, which CoreML lowers via grid_sample. The ANE compiler cannot
plan grid_sample — passing .all or .cpuAndNeuralEngine hangs
the load call in com.apple.anef.p3 forever. The CPU + Metal GPU
path is fast enough (~350 ms / 1024² frame for lite) that this
isn't a battery/thermal limit for photogrammetry workloads. Full
diagnosis: models/production_note.md.
What happened to the rembg/ONNX backend?
Earlier versions of this node ran inference through rembg +
ONNX Runtime's CoreML Execution Provider. That path was removed
2026-05-23: on Apple Silicon it ran 6–10 s per frame on CPU and
~233 s per frame via the CoreML EP CPUAndGPU mode (Metal
command-buffer thrashing in ORT for swin-v1 graphs). The
.mlpackage path is 10–35× faster and uses 5× less memory.
Quick start¶
# 1. The CoreML mlpackage models are pre-shipped at ai-models/.
# Confirm they're present:
ls ai-models/BiRefNet_lite.mlpackage ai-models/BiRefNet.mlpackage
# 2. In Meshroom, add the SegmentationBiRefNet node to your graph.
# The descriptor lives at:
# plugins/ai-segmentation/nodes/aliceVision/SegmentationBiRefNet.py
# (auto-discovered via MESHROOM_NODES_PATH from scripts/run_meshroom.sh)
# 3. Wire CameraInit.output → SegmentationBiRefNet.input
# (same input contract as ImageMasking).
After the run, masks land in {outputDir}/ next to the per-view
intermediates, one file per input view.
If the .mlpackage files are missing, follow
ai-models/README.md
to re-convert them from the BiRefNet HuggingFace checkpoints (one
command per variant, ~70–125 s on M4).
Model variants¶
Exposed as the node's modelVariant ChoiceParam. Both variants are
MIT-licensed (commercial use allowed) and produced from the
ZhengPeng7/BiRefNet* HuggingFace checkpoints.
| Variant | Backbone | .mlpackage size |
Steady-state latency (M-series GPU) | When to pick it |
|---|---|---|---|---|
birefnet-lite (default) |
swin_v1_t | 90 MB | ~350 ms / frame | Default. Fits 8 GB UMA comfortably. Fast enough for everyday photogrammetry. |
birefnet-general |
swin_v1_l | 447 MB | ~980 ms / frame | Higher accuracy on hair, fine foliage, transparent edges. Use when you need the very best mask quality. |
Latencies from models/production_note.md
(3-iter mean after 2 warm-ups, single-threaded, no other GPU load,
fixed 1024² FP16 mlprogram).
How to switch models¶
The modelVariant parameter takes either birefnet-lite or
birefnet-general.
Python Meshroom (PySide6 UI):
- Select the
SegmentationBiRefNetnode in the graph editor. - In the Attribute Editor on the right, find Model Variant under the node's inputs.
- Pick from the dropdown. The choice is part of the node UID, so swapping invalidates the cache — masks are regenerated on the next compute.
Headless (meshroom_compute / direct CLI):
source meshroom-venv/bin/activate
python -m meshroom.bin.node_run \
--nodeType SegmentationBiRefNet \
--input /path/to/sfmData.sfm \
--output /tmp/masks/ \
--modelVariant birefnet-lite \
--maskFormat png \
--keepFilename true
The in-process session cache keeps each loaded .mlpackage in RAM for
the lifetime of the worker, so re-running with the same modelVariant
across chunks pays the ~3–5 s model-load cost only once. Switching
variants mid-process loads the second model without unloading the
first — so a two-variant comparison in one process needs
90 + 447 = ~540 MB resident in addition to the activation buffers.
Workflow integration¶
SegmentationBiRefNet slots in between CameraInit and any downstream
node that consumes per-view masks. Two canonical pipelines:
Object-only photogrammetry (turntable / isolated subject)¶
CameraInit → SegmentationBiRefNet → FeatureExtraction → FeatureMatching
↘ ↘
DepthMap Meshing → Texturing
Wire the output (masks folder) of SegmentationBiRefNet into:
FeatureExtraction.masksFolderDepthMap.masksFolder(if available — masks suppress background depth)Meshing.masksFolder(if your scene has consistent foreground across views)
FeatureExtraction.maskExtension defaults to png and matches our
default maskFormat. Switch both to exr together if you need float
masks.
Hybrid (foreground hint, background still reconstructed)¶
Connect masks only to FeatureExtraction and leave DepthMap unmasked.
This biases feature detection toward the subject without throwing away
background context — useful for free-roam outdoor captures where the
boundary is fuzzy.
Apple Silicon optimization¶
This node is designed for the M-series UMA architecture. Key knobs and
constraints (see dev/apple-silicon-optimization.md
for the deep dive):
- Compute target is
MLComputeUnits.cpuAndGPU, always. Hard-coded in the session loader. There is no setting to change this, and there should not be — see the ANE warning above. - First prediction is slower. CoreML JIT-compiles the Metal pipelines
on first run; warm subsequent runs are what the latency table reports.
The session loader runs one warm-up
predict()on a zero tensor immediately afterMLModel.__init__, so by the time you see[SegmentationBiRefNet] Session readyin the log, the pipelines are compiled. - Memory budget by variant (peak RSS during prediction, from
models/production_note.md): birefnet-lite: ~1 GB → comfortable on 8 GB UMA.birefnet-general: ~3 GB → comfortable on 16 GB+.- Unified memory (UMA). CPU and GPU share one physical buffer — no host↔device copy. Model weights load once and CPU + Metal GPU see them.
- Fixed 1024² input. Both
.mlpackagefiles are shape-locked to 1024×1024. The node resizes source images to 1024² (bilinear) before predict and resizes the output mask back to source dimensions (bilinear). To support a different resolution, re-convert withpython models/convert/convert_to_coreml.py <variant> --resolution N.
Backend confirmation in the log¶
The node always emits, once per chunk:
[SegmentationBiRefNet] Host chip: Apple M…
[SegmentationBiRefNet] Compute target: CoreML (CPU + GPU dispatch, coremltools <version>)
[SegmentationBiRefNet] Loading BiRefNet_lite.mlpackage (cpuAndGPU)
[SegmentationBiRefNet] Session ready for variant=birefnet-lite
If the Compute target line says UNAVAILABLE, install
coremltools into the meshroom-venv (pip install "coremltools>=8.0").
Output format¶
Per-view masks are written to the node's output folder
({outputDir}/ — {nodeCacheFolder} in Meshroom's cache layout).
Naming follows the AliceVision convention used by ImageMasking:
maskFormat |
Filename | Notes |
|---|---|---|
png (default) |
{imageStem}_mask.png |
8-bit single channel, matches AliceVision _mask.png convention |
exr |
{imageStem}.exr |
float32 in [0, 1], useful when downstream nodes prefer EXR |
The mask is the sigmoid output of BiRefNet bilinearly resized back to the source image dimensions.
Troubleshooting¶
BiRefNet CoreML package missing at …¶
The .mlpackage files aren't staged. Run the conversion from
ai-models/README.md
(one command per variant). The packages must live at:
You can also point the node at an alternative directory with
export AV_AI_MODELS_DIR=/path/to/my/models before launching Meshroom.
Compute target reports UNAVAILABLE¶
coremltools is not importable inside meshroom-venv. Reinstall:
source meshroom-venv/bin/activate
pip install "coremltools>=8.0"
python -c "import coremltools as ct; print(ct.__version__)"
Load call hangs forever¶
You are passing MLComputeUnits.all or .cpuAndNeuralEngine somewhere
in your stack — the BiRefNet model cannot be lowered to the ANE. The
node itself always uses .cpuAndGPU. If you've patched session.py,
revert the compute_units argument.
Mask is all-black¶
The input image is single-channel grayscale. Convert it upstream (open in Preview, re-export as RGB).