Color Range Mask
Pick a hex, get a skin (or shirt) mask
- image
- limit_mask
- mask
- debug_image
Color Range Mask is a chroma-key in a node: give it a target color, and it produces a mask of every pixel near that color. The pack frames it for skin detection, clothing detection, and region isolation - and that's exactly how it earns its keep in a decal workflow. Want the decal to only touch skin and not wander onto the shirt? Mask the skin with this, intersect it with a placement region via Body Decal Mask Combine, and feed the result in as a clip mask. It's the kind of utility that reads boring and then quietly solves your whole edge problem.
How it works
The node converts the image to HSV and tests each pixel against the target color in all three channels: hue_tolerance, sat_tolerance, and val_tolerance. The hue comparison is circular - it computes min(|h − target|, 1 − |h − target|) - so a target near red wraps correctly instead of breaking at the 0/1 seam. If all three differences are within tolerance, the pixel is in the mask. That's it; no machine learning, no threshold on brightness alone.
The target_color is a hex string, default #f0b6a5, which is a light skin tone - the author's way of saying "skin detection is the intended use, and here's a starting point." The frontend even registers an EyeDropper button on the node ("Pick target color") in browsers that support it, so you can click on a pixel in your base image and have the hex filled in for you. That's the single best workflow tip for this node: don't guess hex values, click the actual pixel.
Inputs and outputs
Required: image, target_color (hex), and the three tolerances. hue_tolerance runs 0–0.5 (default 0.06), while sat_tolerance and val_tolerance run 0–1 (defaults 0.35 / 0.45). Then feather (0–80 px gaussian soften), invert, and debug. The optional limit_mask multiplies into the result, restricting the color mask to an already-masked area - a classic pair-up with Body Decal Region's region_mask.
Outputs: mask (MASK) and debug_image (the base with the mask tinted cyan so you can see what got selected without guessing).
The tolerance tuning dance
Real-world color-keying is a three-way trade, and this node is no exception. hue_tolerance is the one that matters most - skin tones are all within a narrow hue band, so cranking it makes the mask bleed onto anything warm-colored (wood, hair, tan clothing). sat_tolerance and val_tolerance handle the "same hue, different shade" problem, but they're floaty: a dark shadow on skin has different value and saturation than lit skin, so if your mask has holes in shadows, raise val_tolerance before you raise hue. Expect to iterate - toggle debug on, look at the cyan overlay, nudge, repeat.
Gotchas
Big one: colors in the same hue family with very different lighting will split the mask. A lit face and a shadowed neck are technically the same skin but map to different HSV values, and one tolerance setting may not catch both. Also, invert flips after the limit_mask multiply, so "everything except skin" respects your limit area - useful, but remember the ordering. Install with the pack: Manager "ComfyUI Body Decal", or git clone https://github.com/verias/comfyui-body-decal.git into custom_nodes and restart; deps are numpy + Pillow.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| target_color | STRING | #f0b6a5 | — |
| hue_tolerance | FLOAT | 0.0600–0.5 | — |
| sat_tolerance | FLOAT | 0.350–1 | — |
| val_tolerance | FLOAT | 0.450–1 | — |
| feather | INT | 60–80 | — |
| invert | BOOLEAN | false | — |
| debug | BOOLEAN | true | — |
| limit_maskopt | MASK | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |
| debug_image | IMAGE | — |