cv2.decolor
Grayscale that keeps what your eye actually sees
- src
- grayscale
- color_boost
cv2.decolor is the contrast-preserving grayscale conversion from OpenCV's photo module, and it exists because plain luminance math is bad at one specific thing: two colours with nearly the same brightness. A red apple on green leaves collapses into mush under COLOR_BGR2GRAY - same luminance, no edge - but decolor keeps the boundary visible, because it solves for a grayscale image that best preserves the original's contrast rather than just averaging channels.
Inputs and two outputs
src takes a ComfyUI IMAGE (or an NPARRAY); it must be 8-bit, three-channel. Four channels or a single channel and you'll get an error - the algorithm needs colour to decide how to separate it.
There are two outputs, and this is the nice part:
grayscale- the decoloured result.color_boost- a colour image with the separation pushed harder, which is the paper's "boosted" version. It's a punchy, slightly surreal saturation boost, not a colour correction.
Both echo the input format: wire an IMAGE in and you get IMAGEs back, so unlike most of the raw wrappers in this pack you can preview the result immediately without a CV Array → Image round trip. The pack classifies decolor as a type-preserving function, which is why the socket behaves this way.
Where it earns a slot
Grayscale conversion for conditioning and masks, mostly. If you're building a ControlNet-style line or depth conditioning pass by hand, or you want a clean luminance plate to threshold into a mask, decolor is the version that doesn't lose the edges between differently-coloured but equally-bright regions. That's the exact failure mode people blame on "the mask just doesn't separate the subject" - a red object on a green field going flat.
It also gives you a black-and-white conversion that reads better than the channel average for stylisation passes. And color_boost is a cheap "make it pop" output for a preview or a thumbnail, with the caveat that it's aggressive.
The honest take: this is not free. It's a small optimisation problem, so it's slower than cv2.cvtColor's one-line matrix multiply, and on images where the colours are already well separated in luminance it buys you nothing you'd notice. Reach for it when a grayscale conversion visibly loses something - not as a default replacement for BGR2GRAY. The wider point from our post-processing notes applies: reach for the cheap deterministic primitive first, and upgrade only when you can see the failure it fixes.
Install
Manager → Install Custom Nodes → search ComfyUI CV, or from the CLI:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Restart ComfyUI afterwards. Python ≥ 3.12 and a recent V3-API ComfyUI; the contrib headless wheel is the only real dependency and no models are needed. decolor is a core OpenCV function, but this pack as a whole assumes the contrib build - all four OpenCV wheels share one site-packages/cv2, so a stray pip install opencv-python empties the contrib halves and you'll find contrib nodes missing. python tools/repair_opencv_contrib.py --check (then --apply) repairs it. The pack is GPL-3.0, a fork of geroldmeisinger/opencv-comfyui, largely AI-generated, and the author's own disclaimer says don't put it in production without reviewing it.
Common issues
- A channel/precision assertion on execution. You fed a mask or a four-channel image. Convert or drop the alpha first; the input must be 8-bit 3-channel.
- The result looks uneven, with odd blotches in flat areas. That's the algorithm doing contrast-preserving work on a region where the "best" grayscale is genuinely ambiguous. On a busy photo it can look worse than a straightforward luminance conversion - compare both before committing.
- You expected it to be a colour match. It isn't.
cv2.decolortakes one image and gives you a gray plate plus a boosted colour version; matching one image's colour to another is a different job entirely.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| src | COMFY_MATCHTYPE_V3 | Input 8-bit 3-channel image. The image output(s) echo this input's format. 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. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| grayscale | COMFY_MATCHTYPE_V3 | Echoes the 'src' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY. |
| color_boost | COMFY_MATCHTYPE_V3 | Echoes the 'src' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY. |