ZML_遮罩分离-二
Split one mask into a left and right half by what's actually in it
- 输入遮罩
- 靠左遮罩
- 靠右遮罩
A mask node that doesn't cut down the middle - it looks at what's in the mask and splits where the actual gap is. That's the whole trick, and it's why you'd reach for this over just cropping a mask in half.
The name "分离" means "separate," and the node is the two-way member of a small family in ComfyUI-ZML-Image (the three-way sibling is ZML_MaskSeparateThree). The author's own framing in the README: this exists so you can take a single detected mask and hand its pieces to different downstream branches - the classic use being YOLO-based regional processing, like running a face-detail pass on only one side of an image (see the KB's detailing doc for that whole detect → mask → re-render loop).
How it works
Under the hood it's straightforward computer vision, not AI. The mask is binarized, then cv2.connectedComponentsWithStats finds every blob of white pixels. Each blob that survives your 最小面积比例 (minimum area, as a fraction of the whole image) becomes a candidate "piece." The node then sorts the pieces left-to-right by their centroid x-position and finds the biggest gap between consecutive pieces. If that gap is bigger than your 分离阈值 times the image width, it splits there: everything left of the gap goes to one output, everything right goes to the other.
Two edge cases worth knowing. If there's only one significant piece, the whole mask goes to 靠左遮罩 and the right output is empty - which is the correct behavior, not a bug. And if the biggest gap is smaller than the threshold, everything lands on the left output. The threshold is your "how much separation counts" knob; at 0.2 (the default) it takes a real visual gap of 20% of the image width to trigger a split.
The inputs that matter
- 输入遮罩 - the MASK you want split.
- 分离阈值 (0–1, default 0.2) - the minimum gap, as a fraction of image width, that counts as a split. Raise it if the node splits when it shouldn't.
- 最小面积比例 (0–1, default 0.01) - pieces smaller than this fraction of the image are ignored as noise.
Outputs are 靠左遮罩 and 靠右遮罩, both full-resolution masks you can wire straight into masks-to-image, a detailer, or a SetLatentNoiseMask. They sit under the 遮罩 (mask) subcategory with the rest of the ZML mask tools.
Installing it
This node ships in the ComfyUI-ZML-Image pack (160+ nodes, all under the 图像 → ZML_图像 category). Install once, get them all:
cd ComfyUI/custom_nodes
git clone https://github.com/zml-w/ComfyUI-ZML-Image
# restart ComfyUI
Or use ComfyUI Manager → search "ComfyUI-ZML-Image" → install. The pack's requirements.txt pulls in opencv-python, numpy, Pillow, and friends (plus ultralytics, which you don't need for this node but Manager will install anyway). One real gotcha: the UI is Chinese-first. If the node labels look like wall text, grab the author's translation patch at https://github.com/zml-w/ZZZ_ZML_English_Patch.
Where people get burned
The author is one person building for his own workflow, and he says so flat out in the README: heavily-used nodes are polished, others may have bugs - file an issue or PR if you hit one. For this node specifically, the failure mode people run into is feeding it a mask with one giant connected blob where the "two regions" are actually touching. Connected components can't split a single blob, so you get everything on the left output. If your mask's regions touch, break them apart first or use a three-way separation with a lower threshold instead.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| 输入遮罩 | MASK | — | |
| 分离阈值 | FLOAT | 0.200–1 | — |
| 最小面积比例 | FLOAT | 0.0100–1 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| 靠左遮罩 | MASK | — |
| 靠右遮罩 | MASK | — |