Saturation Mask Builder
Select Vivid Colors Without Tuning a Segmenter
- image
- mask
JHPixelProSaturationMask builds a mask straight from how saturated each pixel is. It's the simplest selection tool in the PixelPro color group: no SAM model, no text prompt, no point clouds. Just "give me everything colorful" or "give me everything neutral," based on the HLS saturation channel.
Why you'd want it: masking the vivid regions is the fastest way to gate a creative grade so it only hits the colorful parts of the frame, or to suppress neutral/gray areas in a retouch chain. It's a mask builder, so the output feeds anything that takes a MASK - ImageBlend, a LUT apply, a compositor. Lightweight, deterministic, instant. That's the appeal.
How it works: convert to HLS, take the S channel, and threshold it. sat_min and sat_max define the included range (default 0.3..1.0), and feather softens the threshold edges (default 0.1). One nuance worth understanding: the feather is in saturation space, not pixel space. It smooths how the mask value ramps across the saturation threshold; it does not spatially blur the mask edge. If you need a spatial blur, that's the mask Edge Smoother's job.
Inputs:
image- RGB IMAGE.sat_min- minimum saturation included (default 0.3).sat_max- maximum included (default 1.0). Must be greater thansat_minor the node raises a ValueError.feather- soft edge width for the thresholds (default 0.1).
Output: a single MASK.
Install is the shared pack install:
cd ComfyUI/custom_nodes
git clone https://github.com/jetthuangai/ComfyUI-JH-PixelPro.git
cd ComfyUI-JH-PixelPro
pip install -r requirements.txt
Restart and it's under ComfyUI-JH-PixelPro/color, or use ComfyUI Manager → search "ComfyUI-JH-PixelPro".
Troubleshooting: the classic confusion is expecting a spatial selection. A saturated red object next to a saturated blue object both land in the mask, because the node selects by color intensity, not by object. If you want "just the red thing," you need a hue-based selection - the pack has Hue/Saturation per Range for that, or a proper segmenter - and then this node becomes the fallback. Also, grayscale pixels have zero saturation, so they're excluded by definition, which is usually what you want anyway. And remember the sat_max > sat_min rule; it's the one validation that'll throw if you drag the sliders past each other.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| sat_min | FLOAT | 0.300–1 | Minimum saturation included in the output mask. |
| sat_max | FLOAT | 1.000–1 | Maximum saturation included in the output mask. |
| feather | FLOAT | 0.100–1 | Soft edge width for the saturation thresholds. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |