Nodes/ComfyUI CV/cv2.cvtColor
ComfyUI Node

cv2.cvtColor

Gray, HSV, and the two traps nobody mentions

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.cvtColor
  • src
  • nparray
◄codeCOLOR_BGR2GRAY►
◄dstCn0►
◄hintALGO_HINT_DEFAULT►

If you install this pack for one node, it's this one. cv2.cvtColor is the colour-space conversion workhorse: BGR to gray for a mask, BGR to HSV when you want to select by saturation instead of brightness, Lab or YCrCb when you're doing colour statistics, BGRA when something downstream wants alpha. There's no model, no VRAM, no pass - it's the deterministic "cheap primitive" half of image processing, and it runs instantly.

How it works

One conversion code does both jobs: it names the source space and the destination space, COLOR_BGR2GRAY, COLOR_BGR2HSV, COLOR_Lab2BGR and a few hundred friends. There is no "from" and "to" pair to keep in sync, which is why people who've only used Photoshop get tripped up by the names.

Crucially, the source is BGR, not RGB. The pack converts every incoming ComfyUI IMAGE tensor to BGR before cv2 sees it, so COLOR_BGR2GRAY is the correct conversion for a loaded photo and COLOR_RGB2GRAY would be wrong - for grayscale the difference is a slightly different luminance weighting, but for a red/blue swap it's a mess.

Inputs and outputs

src takes an NPARRAY link, or a ComfyUI IMAGE/MASK directly. The code dropdown defaults to COLOR_BGR2GRAY, which is the single most common thing anyone wants here. dstCn (default 0) lets you force an output channel count - 0 means "derive it from the code", and you should leave it alone unless you know you need otherwise. hint is OpenCV's algorithm hint, ALGO_HINT_DEFAULT by default; set it to ACCURATE or APPROX only if you're chasing a specific implementation.

The output is one NPARRAY - not an echoed IMAGE, unlike most filters in this pack, and this is deliberate. The pack's own source spells out why: its format-restoring path applies COLOR_BGR2RGB to any three-channel result, so a BGR2HSV output handed back as an IMAGE would come out with H and V swapped, and the output channel count is decided by a widget, which a static socket type can't express. Practically: wire the output into CV Array → Image to see it. For a single-channel result like gray, that node also turns it into a viewable image.

A MASK link is accepted, but a mask is single-channel by nature - the BGR codes expect three channels and will raise on it. If your source really is a mask, this pack's Mask → CV Array node is the intended entry point (it hands cv2 uint8 0–255 by default).

What people use it for

Gray for masking and conditioning: COLOR_BGR2GRAY → CV Array → Mask → any mask consumer. HSV when luminance is the wrong discriminator - saturation lives entirely in the S channel, so COLOR_BGR2HSV followed by cv2.extractChannel and a threshold gives you a "vivid vs washed-out" mask that a gray conversion can't produce. Note HSV in OpenCV is not 0–360/0–100: hue runs 0–179 and S/V run 0–255, because everything is squeezed into uint8. Lab/YCrCb for colour matching and white balance work, where you want a channel that separates colour from brightness properly.

Install

Manager → Install Custom Nodes → ComfyUI CV (publisher bmad4ever), or:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"

Restart ComfyUI. Requires Python ≥ 3.12 and a recent V3-API ComfyUI. cvtColor is core OpenCV so no models are needed, but keep the contrib wheel: installing plain opencv-python over it shares the same site-packages/cv2 and silently removes the contrib nodes from this pack - python tools/repair_opencv_contrib.py --check diagnoses that. The pack is GPL-3.0, forked from geroldmeisinger/opencv-comfyui, heavily LLM-assisted, and its author explicitly warns it isn't production-ready.

Common issues

  • (-215:Assertion failed) ... scn == 3 || scn == 4. You fed a single-channel array to a three-channel conversion, usually a MASK or an already-gray image. Check with Inspect CV Data or CV Array Shape before the conversion.
  • Your HSV or Lab output looks wrong when previewed. You previewed the raw NPARRAY. Convert it back with CV Array → Image and accept that H/S/V shown as RGB channels is always going to look strange - that's data, not a picture.
  • Colours are inverted compared to the node's name. Almost always a BGR/RGB expectation: the pack feeds BGR, and any round trip through an IMAGE output applies RGB ordering. Stay in NPARRAY if you're doing multi-step colour math.
Categoryimage/CV/low-level/cv2 C

Inputs (4)

NameTypeDefaultDescription
srcNPARRAY,IMAGE,MASKinput image: 8-bit unsigned, 16-bit unsigned ( CV_16UC... ), or single-precision floating-point. Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
codeCOMBOCOLOR_BGR2GRAYcolor space conversion code (see #ColorConversionCodes).
dstCnoptINT0-2147483648–2147483647number of channels in the destination image; if the parameter is 0, the number of the channels is derived automatically from src and code. Preset to the OpenCV default (0).
hintoptCOMBOALGO_HINT_DEFAULTImplementation modification flags. See #AlgorithmHint

Outputs (1)

NameTypeDescription
nparrayNPARRAY—