Mask + Matting
The one-node production pipeline from segmentation to alpha to despill
- image
- pos_bbox
- neg_bbox
- normal_bbox
- external_mask
- external_trimap
- holdout_mask
- core_mask
- mask
- alpha
- preview
- trimap
- bbox
- bbox_json
- score
- info
- despilled
- lightwrap_rgba
- edge_mask
- inside_mask
- outside_mask
- luma_key_mask
- problem_regions
- severity
- suggested_method
This is the flagship. Mask Ops (MEC) is a full production matting pipeline in one node - segmenter, alpha matter, auto-quality pre-processing, despill, light wrap, video propagation, and diagnostics - with 17 outputs and enough knobs to scare anyone. The good news: the defaults are so aggressively automatic that you can ignore most of them and still get a better cutout than a hand-rolled chain.
The pipeline: a coarse mask from a segmenter, then an optional alpha matte, then polish. In this pack's terms it's MaskOpsMEC = the "Mask + Matting" node - the one-stop shop where the separate SAM/ViTMatte/RVM nodes get fused.
The parts that matter
segmenter(defaultauto_best) - the coarse-mask backend: SAM 2.1, SAM 3, SAM 3.1, BiRefNet, RMBG-2.0, InSPyReNet, DIS, GroundingDINO, and more. Entries tagged[missing-deps]need an optional pip install to activate.auto_bestpicks what's available and best - leave it unless you know why not.matter(defaultvitmatte) - refines the alpha:none(use the segmenter mask as-is),vitmatte,rvm,bgmattingv2,matanyone,birefnet. This is where hair and fur actually get good.model/matter_model- pick specific weight files, or(auto)and let each backend choose.auto_quality(default ON) - the killer feature. It detects motion blur, low light, low contrast, speckle noise, and similar fg/bg color, then applies just-enough preprocessing (CLAHE, unsharp, NL-means, chroma stretch) before segmentation and a light guided-filter polish after. No knobs. On hard images this is the difference between a decent mask and a good one.auto_disambiguate(default ON) - feedpositive_coords(e.g. on the face) andnegative_coords(e.g. on the neck) and it scores SAM's three candidates by pos-coverage minus neg-coverage, so you get the face, not the whole person.
Then the pro stuff: despill with preserve_skin (decontaminate green/blue/whatever backing), lightwrap_strength for blending over a new background, holdout_mask (force pixels to alpha 0 - boom mics, rigs), core_mask (force pixels to alpha 1), post_refine (guided or DenseCRF), tta_flip/multiscale for quality, and robust_propagation for video - a confidence-aware re-anchor loop that re-prompts SAM when a frame's mask drifts (flow warp / DINOv2 / blend strategies).
Outputs worth wiring
The full list is long; the ones you'll actually use: alpha (the production matte), mask (coarse), preview (premultiplied), bbox/bbox_json, score (0–1 quality), info (what actually ran), and the compositing aids - despilled, lightwrap_rgba, edge_mask, inside_mask/outside_mask. problem_regions/severity/suggested_method come from the built-in failure explainer.
Install and model files
Pack install, then models:
cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git
pip install opencv-python>=4.7.0 scipy>=1.10.0
SAM weights go in ComfyUI/models/sams/ (SAM 3) and ComfyUI/models/sam2/ (SAM 2.1); BiRefNet/RMBG/InSPyReNet weights are auto-listed from their standard folders. auto_download (default off) can lazy-fetch missing weights from HF/torch.hub. The [missing-deps] tags tell you exactly which pip packages unlock which backends - install transformers for ViTMatte, and the extras for the video matters.
Three gotchas: (1) RMBG-2.0 is non-commercial under BRIA's license - check before shipping a product. (2) SAM 3 is not Apache like SAM/SAM2, worth knowing for commercial use. (3) With 50+ inputs, keep auto_quality on and resist touching everything - the node's own docs describe it as "no knobs to tune," and it's right.
Inputs (68)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Source image or video frames (B,H,W,C). | |
| segmenter | COMBO | auto_best | Coarse-mask backend. Entries tagged [missing-deps] need an optional pip install to activate. |
| matter | COMBO | vitmatte | Optional alpha refinement. 'none' returns the segmenter mask as alpha. |
| model | COMBO | (auto) | Specific weight file to use. Tag prefix selects the backend folder; '(auto)' lets each backend pick. |
| matter_model | COMBO | (auto) | Weight file for the matter backend. |
| precision | COMBO | fp16 | 3 options: fp16, bf16, fp32 |
| attention | COMBO | auto | 6 options: auto, sdpa, flash, sage, xformers, eager |
| offload | COMBO | none | 3 options: none, cpu, sequential |
| subject_preset | COMBO | custom | Override trimap_dilate/erode/edge with subject-tuned values. |
| trimap_dilate | INT | 80–128 | — |
| trimap_erode | INT | 80–128 | — |
| edge_radius | INT | 40–64 | — |
| individual_objects | BOOLEAN | false | If supported by the backend, return one mask per detected object. |
| tracking_direction | COMBO | forward | 3 options: forward, backward, bidirectional |
| frame_annotation | INT | 00–100000 | Frame index (in clip) where prompts are anchored. |
| object_id | INT | 00–1024 | — |
| max_frames_to_track | INT | 00–100000 | 0 = no cap. |
| memory_size | INT | 81–256 | — |
| start_frame | INT | 00–100000 | — |
| end_frame | INT | -1-1–100000 | -1 = last frame. |
| auto_download | BOOLEAN | false | Allow lazy auto-download from HF/torch.hub when a weight is missing. |
| seed | INT | 00–18446744073709550000 | — |
| tta_flip | BOOLEAN | false | Test-time augmentation: run segmenter on the H-flipped image and average. Slower but cleaner. |
| multiscale | BOOLEAN | false | Run the segmenter at 0.75x / 1.0x / 1.25x and fuse. Helps small / thin subjects. |
| post_refine | COMBO | none | Final alpha refinement. 'guided' = guided filter (fast, torch-only). 'crf' = DenseCRF (requires pydensecrf, sharpest edges). |
| refine_radius | INT | 81–64 | Spatial radius for guided / CRF refinement. |
| refine_iterations | INT | 51–30 | CRF inference iterations. |
| despill | COMBO | off | Colour decontamination on the named backing. 'auto' estimates the colour from image corners. |
| despill_strength | FLOAT | 1.000–2 | How aggressively to subtract the spill (0 = off). |
| preserve_skin | BOOLEAN | true | Keep warm pixels (R>G>B) untouched during despill. |
| lightwrap_strength | FLOAT | 0.000–2 | Light-wrap intensity. 0 = off; ~0.3-0.6 = natural blend over the new BG. |
| lightwrap_radius | INT | 81–64 | Light-wrap halo radius in pixels. |
| edge_band_radius | INT | 41–64 | Width of the soft edge band when splitting edge/inside/outside masks. |
| premultiply | BOOLEAN | true | Premultiply preview by alpha. Disable for straight-alpha outputs. |
| enable_luma_key | BOOLEAN | false | Run a luminance keyer on the source image BEFORE segmentation and use it as a hint / external_mask. |
| luma_mode | COMBO | auto | 5 options: auto, highlights, midtones, shadows, custom |
| luma_low | FLOAT | 0.000–1 | — |
| luma_high | FLOAT | 1.000–1 | — |
| luma_gamma | FLOAT | 1.000.01–10 | — |
| luma_falloff | FLOAT | 1.00–10 | — |
| luma_invert | BOOLEAN | false | — |
| luma_mix | COMBO | hint_only | How to combine the luma-key mask with the segmenter result. 'hint_only' = use as external_mask hint; 'intersect/union/replace' = combine with the final alpha. |
| enable_advanced_trimap | BOOLEAN | false | Use the edge-aware trimap generator (asymmetric inner/outer scaling, image-edge snapping, smoothing) instead of the simple dilate/erode trimap. |
| trimap_inner_scale | FLOAT | 1.00.1–3 | — |
| trimap_outer_scale | FLOAT | 1.50.5–5 | — |
| trimap_smooth | FLOAT | 0.00–20 | — |
| trimap_threshold | FLOAT | 0.500–1 | — |
| auto_quality | BOOLEAN | true | AUTOMATIC robustness for hard images. Detects motion blur, low light, low contrast, speckle noise and low bg/fg colour separation, then applies just-enough pre-processing (CLAHE, unsharp, NL-means, chroma stretch) BEFORE the segmenter, and a light guided-filter+edge-snap polish on the alpha. No knobs. |
| auto_disambiguate | BOOLEAN | true | When BOTH positive and negative points are supplied, score SAM's 3 candidate masks by (pos-coverage − neg-coverage − size-penalty) instead of raw score. This is what makes `pos=face, neg=neck` return just the face, not the whole person. |
| quality_mode | COMBO | balanced | Strength of auto_quality pre/post processing. fast = mild, balanced = default, max_fidelity = NL-means denoise + larger guided filter. |
| enable_diagnose | BOOLEAN | true | Run automatic mask-failure diagnostics (severity score + suggested method). |
| diag_ring_width | INT | 51–50 | — |
| diag_blur_threshold | FLOAT | 500–1000 | — |
| diag_brightness_threshold | FLOAT | 0.150–1 | — |
| robust_propagation | BOOLEAN | false | Confidence-aware re-anchor loop for video. After SAM2 propagation, every frame's mask is scored vs the last good mask (IoU × size-ratio). When confidence drops below the threshold, the chosen re-anchor strategy fires (flow warp / DINOv2 region search / convex blend). Robust against motion blur + lighting drift. Single-image inputs skip this stage. |
| robust_confidence_threshold | FLOAT | 0.650–1 | Below this confidence the re-anchor fires. |
| robust_reanchor_method | COMBO | blend | flow=Farneback optical-flow warp of last good mask. dino=DINOv2 patch-feature region search + SAM2 re-prompt. blend=convex mix of current+warped. none=accept drifted output (debug). |
| robust_blend_alpha | FLOAT | 0.700–1 | Blend weight for current SAM2 mask when method=blend. |
| positive_coordsopt | STRING | JSON list of positive points [[x,y],...] from PointsBBoxMaskEditor (positive_coords output). | |
| negative_coordsopt | STRING | JSON list of negative points [[x,y],...] from PointsBBoxMaskEditor (negative_coords output). | |
| pos_bboxopt | BBOX | Single positive bbox [x0,y0,x1,y1]. | |
| neg_bboxopt | BBOX | Optional negative bbox (excluded region). | |
| normal_bboxopt | BBOX | Generic bbox if you don't care about polarity. | |
| text_promptopt | STRING | Open-vocabulary text prompt (SAM3 / GroundingDINO / VideoMaMa). Wire from any STRING source. | |
| external_maskopt | MASK | Optional mask used as a hint or overridden when input_mode='auto' falls through. | |
| external_trimapopt | MASK | Optional pre-computed trimap that bypasses internal trimap generation. | |
| holdout_maskopt | MASK | Garbage / holdout matte. Pixels where this is >0 are FORCED to alpha=0 (used to chop out boom mics, rigs, etc). | |
| core_maskopt | MASK | Core / inside matte. Pixels where this is >0 are FORCED to alpha=1 (used to lock down opaque interiors). |
Outputs (17)
| Name | Type | Description |
|---|---|---|
| mask | MASK | Coarse mask from the segmenter (B,H,W). |
| alpha | MASK | Refined alpha after matter + refinement (production output). |
| preview | IMAGE | image * alpha premultiplied preview. |
| trimap | MASK | Trimap (0/0.5/1) used by the matter. |
| bbox | BBOX | Tight bbox around the alpha as [x0,y0,x1,y1]. |
| bbox_json | STRING | Same bbox as JSON {'x','y','w','h'}. |
| score | FLOAT | Overall production-quality score in [0,1] (boundary + coherence + size + smoothness). |
| info | STRING | JSON: backends, modes, per-frame quality breakdown, refine stages run, settings used. |
| despilled | IMAGE | Image with backing-colour spill suppressed (when `despill_strength`>0). |
| lightwrap_rgba | IMAGE | RGBA light-wrap layer to ADD over the new background. |
| edge_mask | MASK | Soft edge band where matting actually matters. |
| inside_mask | MASK | Solid-fg interior mask (safe to colour-grade). |
| outside_mask | MASK | Solid-bg exterior mask (safe to defocus / replace). |
| luma_key_mask | MASK | Luminance keyer output (empty if `enable_luma_key` is off). |
| problem_regions | MASK | Diagnostic problem-region heatmap from the failure explainer. |
| severity | FLOAT | Severity score [0,1] from the failure explainer. |
| suggested_method | STRING | Suggested next masking method (string) from the failure explainer. |