OpenCV watershed_0
Split touching objects into separate mattes with marker-based segmentation
- image
- markers
- nparray
If you've ever gotten a mask from a segmentation model that treats three overlapping apples as one blob, you know the exact problem watershed exists to solve. It's OpenCV's classic marker-based segmentation: given an image and a set of labeled seed regions, it "floods" the image from those seeds along gradients, and where two floods collide it draws a boundary line. The result is separate regions for separate objects - the tool for splitting a clump into individual mattes when you have a rough idea of where each object is.
How it works
The watershed metaphor is literal: imagine the image's gradient as a terrain, and your markers as water sources. Water floods outward from each source until it meets another flood, and the meeting points become the watershed lines. You drive it with two things:
image- an 8-bit 3-channelNPARRAY(BGR, as this pack handles images).markers- an int32, single-channelNPARRAYthe same size, seeded with labels:1, 2, 3, …for pixels you're sure belong to each region,0for unknown pixels you want classified, and-1reserved for watershed boundaries in the output.
The output is the modified markers array - the same int32 map, now with unknown pixels assigned to regions and -1 where boundaries formed. Important: this output is not a pretty RGB image, and it's not a 0/1 mask. It's a label map. You visualize it by mapping each label to a color, or you extract per-region masks (e.g. markers == 1) for downstream use.
The classic recipe
The standard way to build good markers: threshold a mask, run the pack's distanceTransform to find the "centers" of the blobs, apply connectedComponents to label those centers, and feed that as markers. The pack ships all of those - threshold, distanceTransform, connectedComponents - so the whole chain is doable in-comfy, just with several nodes and careful dtype handling. The -1/0/positive convention is strict: it must be int32, and your seeds have to be disjoint or watershed merges them.
Inputs and outputs
image- 8-bit BGRNPARRAY.markers- int32 single-channelNPARRAYwith0unknown, positive labels, and optionally pre-marked-1.- Output:
nparray- the updated label map.
Installing
Standard:
cd ComfyUI/custom_nodes
git clone https://github.com/geroldmeisinger/opencv-comfyui
or ComfyUI Manager, search "opencv-comfyui", install, restart. Dependencies: opencv-contrib-python, numpy, torch.
The honest friction
This is one of the fiddliest nodes in the pack, and the README's "expect dragons" warning applies hard. Three things bite people: the int32 markers requirement (a normal RGB image as markers will fail or produce nonsense), the label-map output that needs colorizing before it looks like anything, and the seed quality - bad seeds give you chopped or merged regions. If you just want a foreground matte, a model-based background removal is far less painful; watershed_0 earns its keep specifically when you need to separate touching instances inside a single mask. Use it for that and it's quietly excellent.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| image | NPARRAY | — | |
| markers | NPARRAY | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |