TS Matting (ViTMatte)
From a sloppy SAM mask to real hair-level transparency
- image
- mask
- background_color
- IMAGE
- MASK
- MASK_IMAGE
The name is a lie and that's a good thing - this node doesn't take a clean, hand-painted mask. You hand it a coarse one, the kind SAM3 Detect or SAM3 Video Track hands you (a hard binary blob, edges included), and it returns an actual photo-quality alpha matte with flyaway hair, fur, and semi-transparency preserved. That's the whole trick, and it's the difference between a cutout that looks fine in a preview and one that holds up over a coloured background.
Why matting instead of segmentation
A segmentation model labels each pixel foreground or background - structurally wrong for a veil, a wine glass, or a single hair. Matting predicts fractional alpha for every pixel. This node is built around Hugging Face's ViTMatte, which does exactly that job, and the brief is clear about where it fits: it's a drop-in upgrade for TS Remove Background when you already have a SAM3 mask and edges, hair or transparency actually matter.
The mechanism is easy to follow. ViTMatte wants a trimap - an image where you've marked "definitely foreground," "definitely background," and "unknown, please decide." This node builds that for you from your coarse mask: trimap_erode_px shrinks the mask to a confident foreground core, trimap_dilate_px expands an "unknown" band around it where the model does the real work. If your source mask is tight around hair or fur, bump trimap_dilate_px to 32+ so ViTMatte gets room to look. The model then predicts fractional alpha inside that band.
The inputs that actually matter
For a beginner, three things:
mask- your coarse mask. From SAM3 Detect, BiRefNet, a Mask Editor, anything. A single-frame mask is broadcast across the batch.model-vitmatte-base-composition-1kis the default (~370 MB, best edge quality);smallis ~96 MB and faster but lower detail.trimap_dilate_px- the unknown band. Higher = more context for hair and fur.
The VRAM controls are worth knowing because ViTMatte uses global self-attention: on a 4K input that single attention matrix wants ~25 GB. max_resolution (default 2048) caps the long edge and upscales the alpha back afterwards; auto_crop_by_mask crops to the mask's bounding box first, which saves enormous amounts of VRAM and time when your subject is small in the frame. Leave both defaults on and you'll rarely think about them.
The output contract is the same as TS Remove Background: IMAGE (RGBA cutout, or composited on your chosen background colour), MASK (the refined alpha), and MASK_IMAGE (a grayscale preview). For video, temporal_smooth (median3 by default) kills the "boiling" edge flicker across frames.
Install
There's no special dependency - it's part of comfyui-timesaver, so ComfyUI Manager → search "Timesaver" → install, then restart. The ViTMatte weights auto-download into models/vitmatte/ on first use.
cd ComfyUI/custom_nodes
git clone https://github.com/AlexYez/comfyui-timesaver
cd comfyui-timesaver
python -m pip install -r requirements.txt
Where people get burned
- "My cutout has hard edges again." You fed it a segmentation mask but expected matting output. If the model is
small, trybase- the edge quality is the advertised difference. - OOM on a big photo. That's
max_resolutionandauto_crop_by_maskdoing the wrong job for you - set a lower cap or turn the crop on. - Boiling edges in video. That's what
temporal_smoothexists for; ifmedian3isn't enough there'smedian5or the causalema_causal(no lag, but it can blur fast motion).
The honest expectation: this isn't magic for a genuinely semi-transparent subject like smoke - no matting model fully is. But for hair, fur, and glass edges from a SAM mask, it's the difference between a sloppy cut and a real one.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Source image batch [B, H, W, 3]. | |
| mask | MASK | Coarse binary or soft MASK [B, H, W] (e.g. from SAM3 Detect or SAM3 Video Track). A single-frame mask is broadcast across the image batch. | |
| model | COMBO | vitmatte-base-composition-1k | ViTMatte variant. 'base' = ~370 MB (recommended for best edge quality), 'small' = ~96 MB (faster, lower detail). 'composition-1k' is the standard matting benchmark; 'distinctions-646' is more diverse. |
| trimap_erode_px | INT | 100–128 | Erosion radius for the confident foreground core. Higher = thinner certain-foreground, more soft edges (better for hair). |
| trimap_dilate_px | INT | 200–128 | Dilation radius for the unknown band beyond the mask. Higher = ViTMatte gets more context around the object (helps fly-away hair / fur). 20 is a good default; bump to 32+ if the source mask is tight around hair/fur. |
| max_resolutionopt | INT | 20480–4096 | Long-edge cap (px) for ViTMatte inference. ViTMatte uses global self-attention in some ViT blocks; on 4K input that single attention matrix needs ~25 GB of VRAM. The frame is downscaled before inference and the resulting alpha is upscaled back to native size. 0 = use the native resolution (only safe for small images / lots of VRAM). |
| auto_crop_by_maskopt | BOOLEAN | true | Crop the frame to the mask's bounding box (plus padding) before running ViTMatte. Saves enormous amounts of VRAM and time when the object is small compared to the frame. Has no effect when the mask covers the whole frame. |
| crop_padding_pctopt | INT | 150–100 | Padding around the mask bbox in percent of bbox size when ``auto_crop_by_mask`` is on. 15 = 15% context margin. |
| precisionopt | COMBO | auto | Inference precision on CUDA. 'auto' picks bf16 on Ampere+ (more numerically robust, no fp16 inf/nan on extreme alpha) and fp16 elsewhere. Force 'fp32' for diagnostics. CPU always runs fp32. |
| temporal_smoothopt | COMBO | median3 | Smooth alpha across frames to reduce 'boiling' edges in video. 'median3' (default) kills random 1-frame flicker with minimal overhead and is a no-op for single images. 'median5' for stronger flicker (2-frame lag at clip boundaries). 'ema_causal' is causal exponential averaging — no lag, but can blur fast motion. 'off' disables. Peak RAM grows by ~N*H*W*4 bytes during the pass. |
| ema_alphaopt | FLOAT | 0.500–0.99 | Strength of the causal EMA when temporal_smooth = 'ema_causal'. Higher = more smoothing (lag for moving objects); lower = closer to raw per-frame alpha. |
| mask_bluropt | INT | 00–64 | Final Gaussian blur on the alpha output (px). |
| mask_offsetopt | INT | 0-20–20 | Shrink (-) / expand (+) the final alpha mask. |
| invert_outputopt | BOOLEAN | false | Invert the alpha output. |
| backgroundopt | COMBO | Alpha | Output background mode. |
| background_coloropt | COLOR | #ffffff | Solid background colour when 'background' = 'Color'. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | Cutout image (RGBA or composited on the chosen background). |
| MASK | MASK | Refined alpha matte. |
| MASK_IMAGE | IMAGE | Alpha matte as a grayscale image for preview. |