Nodes/ComfyUI-QuasimondoNodes/Coordinates From Mask
ComfyUI Node

Coordinates From Mask

Turn a mask into a scatter of points (and a point mask)

By Quasimondo·Created 2 years ago·Updated about a year ago· 15
Coordinates From Mask
  • mask
  • coordinates
  • point_mask
percentage0.10
min_distance_from_edge5
max_points100
seed1234

Any time you have a mask and you need places to put things, this node earns its keep. Do you want point targets for a detailer pass, spawn points for a particle or animation system, anchor points to drive a warping node, or just a set of coordinates to feed a JSON-driven workflow? Coordinates From Mask samples the interior of your mask and hands you both the points and a picture of them.

How it works

The pipeline is short and deterministic:

  1. Threshold the mask to binary.
  2. Run an OpenCV distance transform, so every white pixel knows how far it is from the nearest black (edge) pixel.
  3. Keep only points at least min_distance_from_edge pixels away from an edge - that's your "valid" pool.
  4. Sample a fraction of that pool using a Poisson-disk-style sampler - points get spread out evenly-ish instead of clumping - and cap it with max_points.
  5. Return the points as a JSON string and as a new mask with a white dot on each point.

Poisson disk sampling is the nice part. If it just picked random points you'd get clusters; this walks the valid points and refuses to add one that's too close to an already-chosen point (a grid-based distance check). The result is a nicely distributed scatter, seedable so you can reproduce it.

The inputs that matter

  • mask - the region to sample. Only the first mask in the batch is used.
  • percentage - the fraction of valid points to select (default 0.1). Not a fraction of the whole mask - a mask with a lot of edge-near area will have fewer valid points to begin with.
  • min_distance_from_edge - minimum distance from the mask edge (default 5 pixels). Raise it to keep points safely inside, away from fiddly borders.
  • max_points - hard cap (default 100). percentage picks the number, this sets the ceiling.
  • seed - reproducibility. The code applies abs(seed), so a negative seed doesn't error, it just becomes positive.

The outputs

Two outputs, and they're aimed at different consumers:

  • coordinates - a STRING of JSON, e.g. [{"x": 120, "y": 80}, ...]. In ComfyUI a raw string isn't that useful on its own - you'll want a JSON-parse node (or something that reads coordinates) downstream to actually split it into numbers. If you're feeding a node that expects coordinate text, this is your wire.
  • point_mask - a MASK with a white pixel at each selected point. Plug this straight into anything that takes a mask.

Install

From the Quasimondo pack, installed the usual ways - ComfyUI Manager, search ComfyUI-QuasimondoNodes, install and restart, or by hand:

cd ComfyUI/custom_nodes
git clone https://github.com/Quasimondo/ComfyUI-QuasimondoNodes
cd ComfyUI-QuasimondoNodes
pip install -r requirements.txt

No models to download. This node uses OpenCV (the pack's opencv-contrib-python dependency) for the threshold and distance transform, plus a touch of numpy - nothing heavy.

Where people get burned

The main trip-up is expecting the coordinates string to do something on its own. It's text; you have to route it to something that consumes text and parses it. The point_mask output is the more immediately useful one for most workflows.

Second: percentage is relative to the valid points, and min_distance_from_edge heavily influences how many of those exist. Crank min_distance_from_edge to 100 on a small mask and you may get zero valid points - and zero coordinates back. Start low (5–10) and raise it while watching the count.

Also worth knowing: with max_points at 1 you get exactly one point, which makes this a cheap "find a good spot inside this region" picker - a poor-man's Distance Map, if you will.

Categorygenerator

Inputs (5)

NameTypeDefaultDescription
maskMASK
percentageFLOAT0.100–1
min_distance_from_edgeINT50–100
max_pointsINT1001–1000
seedINT1234-9007199254740991–9007199254740991

Outputs (2)

NameTypeDescription
coordinatesSTRING
point_maskMASK