Nodes/opencv-comfyui/OpenCV inRange_0
ComfyUI Node

OpenCV inRange_0

Keep only the pixels inside a color range

By geroldmeisinger·Created about a year ago·Updated about a year ago· 35
OpenCV inRange_0
  • src
  • lowerb
  • upperb
  • dst
  • nparray

OpenCV's inRange is the classic way to say "keep every pixel whose color is between these two bounds, zero out the rest" - and OpenCV inRange_0 is a straight wrapper around it. You feed it an image, a lower bound, an upper bound, and you get back a binary mask that's 255 where the pixel fit the range and 0 everywhere else. In a ComfyUI workflow that mask is gold: it's the thing you wire into a compositing or inpainting branch so the model only re-renders the pixels you actually care about. Think "cut out the blue sky," "keep the red dress," or isolate a color band before running a detailer on it.

How it works

cv2.inRange(src, lowerb, upperb) compares each pixel against the bounds per channel, and every channel has to be inside its own [lowerb[c], upperb[c]] for the pixel to survive - the bounds are inclusive, so a pixel exactly equal to lowerb or upperb counts as inside. For a single-channel grayscale image the bounds are effectively scalars; for a 3-channel BGR image they're 3-element arrays, one range per channel. The output is a single-channel uint8 mask with values 0 and 255.

Where beginners get tripped up with this node specifically: the bounds are NPARRAY inputs, not numbers you type. The pack works in raw OpenCV arrays (see the Image2Nparray / Nparrays2Image conversion nodes), and lowerb and upperb are no exception. So you need a way to produce a small array for the range - an array-holding nparray from another node or a scripting node. If you don't have one handy, reach for the pack's threshold_0 instead, which takes a plain FLOAT and is far friendlier for a single-value cutoff. inRange earns its keep when you genuinely want a multi-channel color band, not when you want "brighter than X."

Inputs and outputs

Only four, and three of them matter:

  • src - your image as an NPARRAY, converted with Image2Nparray first (RGB in, BGR out, remember).
  • lowerb / upperb - NPARRAYs with the per-channel range. For a grayscale src they can be a single value; for BGR, three values.
  • dst - optional output array (the author auto-generates out-parameters when OpenCV types them | None). You can safely ignore it; the node returns the result either way.
  • Output nparray - the 0/255 mask.

Because the pack only handles batch_size == 1, feed a single image - use ImageFromBatch with length=1 if your batch is bigger.

Installing the pack

This node ships in opencv-comfyui, Gerold Meisinger's auto-generated pack of ~635 OpenCV wrappers. Install it once and every OpenCV * node in this pack comes with it:

cd ComfyUI/custom_nodes
git clone https://github.com/geroldmeisinger/opencv-comfyui
cd opencv-comfyui
pip install -r requirements.txt

requirements.txt is just opencv-contrib-python, numpy, and torch - no model files, nothing to download. ComfyUI Manager finds it too, if you search "opencv-comfyui". Restart ComfyUI and you're done.

Gotchas

The mask output is grayscale (CV_8UC1), so the conversion node handles previewing it fine. The pack's other signature error, img.type() == CV_8UC1, means "this function wanted a single-channel image" - if a node demands grayscale, convert with cvtColor (code 6 = BGR2GRAY) before feeding it. Also: remember this pack auto-generates from OpenCV stubs, and the author's own README opens with "Expect dragons!" - the numbering (inRange_0 vs inRange_1) is just OpenCV's overloads, and the two variants behave identically, so pick whichever your graph already references.

Categoryimage/OpenCV

Inputs (4)

NameTypeDefaultDescription
srcNPARRAY
lowerbNPARRAY
upperbNPARRAY
dstoptNPARRAY

Outputs (1)

NameTypeDescription
nparrayNPARRAY