Yogurt Sa2VA Image Segmentation V2
The V2 that turns rough Sa2VA masks into hair-level alpha mattes
- sa2va_model
- vitmatte_model
- image
- text_output
- masks
This is the flagship of the YogurtSa2VA pack, and the reason the two loaders exist. Plain Sa2VA gives you object masks with jagged, object-level edges - fine for inpainting, embarrassing for a cutout. V2 keeps the prompt-based segmentation but pipes each mask through VITMatte, a matting model that predicts per-pixel alpha on the hard edges. The result is a mask that survives hair, fur, whiskers, and semi-transparent glass like the object was actually photographed on a green screen.
It's the classic two-stage recipe, and it's the right architecture: Sa2VA understands what you want (no boxes, no DINO), VITMatte refines the boundary (it doesn't re-segment, it mattes). Neither alone does both.
How it works
Run Yogurt Sa2VA Model Loader → this node → Yogurt VITMatte Model Loader → this node, plus your image. The node prompts Sa2VA, gets the coarse mask, then builds a trimap: erode the mask by detail_erode (6 px default) and dilate by detail_dilate (6 px) to mark the band of unknown edge pixels. VITMatte only has to solve that band, which is exactly why it's good at hair - all its capacity goes into the boundary. The predicted alpha gets stretched by black_point (0.15) and white_point (0.99) to push semi-transparent smears toward clean 0/1, and max_megapixels (2.0 default) caps VITMatte's working resolution so a 4K frame doesn't blow your VRAM. Turn process_detail off and the node degrades gracefully to plain Sa2VA binarization.
The other inputs are the usual suspects: sa2va_model, vitmatte_model, image (RGB), segmentation_prompt, and threshold for the initial binary step. Outputs are text_output (STRING) and masks (MASK). Wire masks into InvertMask → Join Image with Alpha and you've got a transparent cutout with intact hair - the V2 chain is literally what the pack's example workflow does.
The honest trade-offs
- Slower. VITMatte is a second model doing real work on the boundary. A couple of seconds per image is typical; that's the price of hair that doesn't look cropped.
- The threshold caveat travels with this node too. On non-Qwen Sa2VA models the initial threshold slider goes inert (raw-mask patch only covers the Qwen line), but
process_detailstill does its thing - you just lose fine control over the coarse mask. - Needs opencv-python. VITMatte and the trimap/morphology machinery depend on it, and it's not in
requirements.txt. The README calls it out separately; skip it and this node breaks in a way that looks like a model problem.
Install
Whole pack, one install:
cd ComfyUI\custom_nodes
git clone https://github.com/yogurt7771/ComfyUI-YogurtSa2VA
cd ComfyUI-YogurtSa2VA
python -m pip install -r requirements.txt
python -m pip install opencv-python
Then get both models. VITMatte goes in ComfyUI/models/vitmatte (default hustvl/vitmatte-small-composition-1k; the -base variant is the heavier fallback). Sa2VA in ComfyUI/models/sa2va. huggingface-cli download --local-dir is the recommended way so config.json lands where the dropdown scans. If a model dir is missing, the loaders fall back to downloading from Hugging Face on first run.
Recurring pack gotchas apply: dropdown not showing a fresh model means bad directory structure (no config.json) or no restart; "VITMatte node not available" means opencv or a broken model dir; 8-bit load failures mean bitsandbytes is missing.
Is V2 overkill? For clean subjects with hard edges - a car, a box, a building - plain V1 is faster and you won't see the difference. For people, animals, hair, or anything with transparency, this is the node that makes the mask look like it was made by a person, not an algorithm. It's the one I'd reach for.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| sa2va_model | YOGURT_SA2VA_MODEL | — | |
| vitmatte_model | YOGURT_VITMATTE_MODEL | — | |
| image | IMAGE | Input image to segment. Should be in RGB format. | |
| segmentation_prompt | STRING | Please provide segmentation masks for all objects. | Text prompt describing what objects to segment in the image. |
| threshold | FLOAT | 0.500–1 | Threshold for converting probability masks to binary masks. |
| process_detail | BOOLEAN | true | Enable VITMatte post-processing for smooth edges and fine details. |
| detail_erode | INT | 61–255 | Erosion kernel size for trimap generation. |
| detail_dilate | INT | 61–255 | Dilation kernel size for trimap generation. |
| black_point | FLOAT | 0.150.01–0.98 | — |
| white_point | FLOAT | 0.990.02–0.99 | — |
| max_megapixels | FLOAT | 2.00.5–10 | Max resolution for VITMatte processing. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| text_output | STRING | Text output from the model |
| masks | MASK | Generated segmentation masks |