Nodes/comfyui_bmad_nodes/SampleColorHSV
ComfyUI Node Runs on cloud

SampleColorHSV

Stop guessing HSV bounds, steal them from a reference image

By bmad4ever·Created 3 years ago·Updated 9 months ago· 70
SampleColorHSV
  • rgb_image
  • HSV_SAMPLES
sample_size1000
sampling_seed0

The most annoying part of color-based masking is picking the HSV bounds by hand. You think the blue sky is "about 110 hue," you get a mask full of holes, and you slide sliders for twenty minutes. SampleColorHSV is the node that says: stop guessing - sample the actual pixels from a reference image, convert them to HSV, and hand them off to a node that computes the bounds for you.

Give it an image and it grabs sample_size random pixels (default 1000, up to 65536), converts just those samples to HSV, and wraps them in an HSV_SAMPLES object. That object carries the raw samples plus lazily-computed statistics - circular hue mean and standard deviation (hue wraps around, so it can't use plain averages), median, mode, and max deviations for saturation and value. The stats are cached, so downstream nodes can ask for them repeatedly without recomputing.

How you use it

Inputs: rgb_image, sample_size, and sampling_seed. That seed matters more than it looks - it seeds numpy's RNG, so the same seed always picks the same pixels. That's how you keep a color analysis reproducible across runs instead of chasing a mask that drifts every time you hit queue.

The output, HSV_SAMPLES, feeds BuildColorRangeHSV, which turns the sample statistics into an HSV color range. It has several interval strategies - a centered percentile band, mean ± 2 or 3 standard deviations, median-interpolated, and more - each tuned for whether your reference color is tight or messy. The range it produces is an HSV_COLOR pair you can feed straight into InRangeHSV to build the actual mask:

Image → SampleColorHSV → HSV_SAMPLES → BuildColorRangeHSV → HSV_COLOR → InRangeHSV → MASK

This is the workflow that finally made color segmentation click for me: sample a clean patch of the thing you want (a green shirt, a red car), derive the range, and the mask tracks it across frames or variants. For video or batch work, sampling from one representative frame and reusing the seed keeps the same pixels and the same bounds every time.

Installing

Ships in comfyui_bmad_nodes. ComfyUI Manager - search "comfyui_bmad_nodes" (or "Bmad Nodes") - install, restart. Manual:

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

Restart after. No models to download. It's a CV node, so it needs opencv-python (pinned to ~4.8); if your startup log says "Not loaded: CV nodes," install the requirements and restart. Keep ComfyUI current too.

Watch out for

sample_size is capped at 65536 (256²) in the code - plenty for a stable estimate. And remember sampling without replacement means you can't sample more pixels than the image has. One honest note: the stats live inside a custom object type, so this node's output only plugs into the pack's own HSV nodes - that's a feature (it's how the stats get reused) but it does mean the family is a self-contained little ecosystem.

CategoryBmad/CV/Color A.

Inputs (3)

NameTypeDefaultDescription
rgb_imageIMAGE
sample_sizeINT10001–65536
sampling_seedINT00–9223372036854776000

Outputs (1)

NameTypeDescription
HSV_SAMPLESHSV_SAMPLES