Mask Segments (Swwan)
Feed your hand-drawn masks into Impact's detailer loop
- mask
- segs
- segs
- mask
The idea worth understanding first
In ComfyUI, automatic detailing runs on a container called SEGS - Impact Pack's "set of detected segments." Detectors emit SEGS, a detailer iterates them, a paste node composes them back. The whole loop is: crop a region, re-render it at proper resolution, paste it in. It's the ComfyUI version of A1111's ADetailer, and it's why faces in wide shots stop turning into mush.
The catch is that SEGS normally comes from a detector - a YOLO or SAM model you have to download, install and trust. Mask Segments produces SEGS without any model, from a mask you painted or got from anywhere else. That's the whole pitch: your own mask, the full detailing machinery, no Ultralytics in your dependency tree.
It's pure SEGS plumbing reimplemented from Impact Pack - the seven-field SEG structure (cropped_image, cropped_mask, confidence, crop_region, bbox, label, control_net_wrapper) with no detector or model imports anywhere in the file.
The four operations
operation is the mode switch, and it decides which of the other inputs matter:
from_mask- the main one. Takes aMASKand producesSEGS. Each connected blob-ish region of your mask becomes a segment with its own bbox and crop region.crop_factor(default 3.0) is the padding multiplier on the crop: a 100px-wide bbox at 3× crops 300px, i.e. context around the target so the sampler isn't working on a bare face against nothing.bbox_fill,drop_sizeandcontour_fillcontrol whether regions are stored as filled boxes, the minimum size to keep, and whether contours are traced. Feed thesegsoutput into Impact'sDetailerForEach,FaceDetailer-style nodes orSEGSPasteand the loop runs on your regions.combined_mask- SEGS back to one MASK with everything unioned. Handy to visualise what the detailer is about to work on.mask_batch- SEGS back to a batch of masks, one per segment. This is how you preview or process regions individually.filter- reorder, subset and cull existing SEGS (yours or a detector's) without touching pixels.
filter gets the six interesting controls: sort_rule (面积大小 area, 宽度大小 width, 高度大小 height, 左右上下 reading order, 左右下上 alternate), sort_order (正序/反序), start_index and count to slice out a window, and group_threshold (default 50) for grouping nearby segments. The author's description flags the semantics: positive count indexes cyclically, so asking for more segments than exist wraps around rather than erroring. Coordinates come from the first canvas, and the "keep soft masks" note matters - filtering preserves 0–1 values, while the combined and batch paths keep Impact's byte quantisation.
Outputs are segs and mask, and which mask you get depends on the mode: combined for combined_mask, a per-segment stack for mask_batch.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/aining2022/ComfyUI_Swwan
cd ComfyUI_Swwan
python -m pip install -r requirements.txt
Restart, hard-refresh the browser, search Swwan. The SEGS consumers still come from Impact Pack (this pack supplies the container, not the detailer), so you'll want Impact installed for the downstream half - but nothing here needs a detector model, and the pack never downloads weights.
Common issues
from_mask requires mask / filter requires SEGS. Fine, but every non-from_mask operation needs segs connected. The error names the missing input; read it rather than assuming the node is broken.
Detailer gets zero segments. Your mask has nothing above the drop_size threshold, or it's connected but not resampled to the canvas size. Check combined_mask output visually first.
You asked for 5 segments and got 5 that repeat. Cyclic indexing. Set count to something ≤ the real segment count.
Segments are in the wrong place downstream. They're stored in first-canvas coordinates. If your image was resized after the mask was made, the geometry no longer matches.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| operation | COMBO | 4 options: from_mask, combined_mask, mask_batch, filter | |
| maskopt | MASK | — | |
| segsopt | SEGS | — | |
| combinedopt | BOOLEAN | false | — |
| crop_factoropt | FLOAT | 3.001–100 | — |
| bbox_fillopt | BOOLEAN | false | — |
| drop_sizeopt | INT | 101–16384 | — |
| contour_fillopt | BOOLEAN | false | — |
| sort_ruleopt | COMBO | 5 options: 面积大小, 宽度大小, 高度大小, 左右上下, 左右下上 | |
| sort_orderopt | COMBO | 2 options: 正序, 反序 | |
| start_indexopt | INT | 00–9223372036854776000 | — |
| countopt | INT | 10–9223372036854776000 | — |
| group_thresholdopt | INT | 501–500 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| segs | SEGS | — |
| mask | MASK | — |