Mask to Coordinates V2 (SAM2)
Mask to Coordinates V2
- mask
- image
- coordinates_positive
- coordinates_negative
The original Mask to Coordinates turns a painted mask into SAM2 click points. V2 is the version that remembers SAM is actually a two-sided tool: positive points say "segment this," negative points say "definitely not this." That negative channel is how you stop SAM from bleeding a mask onto a similar-looking region right next to your subject, and until V2, generating those negative points from the ComfyUI canvas was a manual chore.
The idea is simple: you keep painting the mask for positives, and you paint on the image itself with a colored brush for negatives. The color you pick is the signal. negative_color defaults to red (the tooltip spells out the palette: red=#FF0000, green=#00FF00, blue=#0000FF, magenta=#FF00FF), and any pixels of that exact color in the optional image input become negative SAM points.
So a typical V2 workflow: paint a mask over the person you want (positives), connect the original image, brush a red swipe over the background area that SAM keeps grabbing (negatives), and run. Out come two JSON strings - coordinates_positive and coordinates_negative - in the same [{"x": ..., "y": ...}] format the SAM2 point-prompt nodes expect, and you feed both into SAM. It's the difference between fighting SAM's mistakes and just telling it where the edge really is.
The inputs that matter
mask- your painted mask; drives the positive points, using the same threshold/contour pipeline as the original (threshold 0.65 default,max_regions50,points_per_region1).image(optional) - the source image you brush negatives onto. Connect it, or you get positives only.negative_color- which exact color means "negative." If you're painting on a photo that already contains red, switch to magenta or blue so the color detection doesn't fire on your subject's red shirt.
Under the hood the negative side is exact-color matching via OpenCV (inRange with the chosen RGB value), then the same contour + random-point-in-contour routine as the positive side. That's the one practical gotcha: it's exact matching, so a soft anti-aliased brush stroke can produce fewer or different points than you expect. Solid, saturated strokes work best.
Same caveats as V1 carry over: a solid-color mask degrades to a default (0,0) positive point with a console warning, and the node doesn't run SAM itself - it only generates the point prompts, so you still need a SAM2 model loader elsewhere. If no negatives are detected, the negative output is just an empty JSON array, which most SAM2 nodes treat correctly as "no negative points."
Installing it
This is in lhaoyun6/ComfyUI-lhyNodes, installable through ComfyUI Manager by searching for lhyNodes, or:
cd ComfyUI/custom_nodes
git clone https://github.com/lihaoyun6/ComfyUI-lhyNodes.git
python -m pip install -r ComfyUI-lhyNodes/requirements.txt
Restart ComfyUI afterward. It's pure NumPy/OpenCV - the opencv-python in the shared requirements does the color matching - so it's instant, costs no VRAM, and needs no model files.
For any SAM2 segmentation that keeps hugging the wrong edge, V2 is the upgrade I'd reach for first. The only reason to stay on the V1 node is if you genuinely never need negative points - and if that's true, you haven't segmented anything next to a similar object yet.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | Mark on the mask to generate positive conditions. | |
| threshold | FLOAT | 0.650–1 | — |
| max_regions | INT | 501–100 | — |
| points_per_region | INT | 11–100 | — |
| negative_color | COMBO | red | red=#FF0000, green=#00FF00, blue=#0000FF, magenta=#FF00FF. |
| imageopt | IMAGE | Mark the image using a colored brush to generate negative conditions. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| coordinates_positive | STRING | — |
| coordinates_negative | STRING | — |