Nodes/ComfyUI CV/cv2.insertChannel
ComfyUI Node

cv2.insertChannel

Gluing single channels back into a colour image (the pack does it in its own Wiener filter)

By bmad4ever·Created 4 months ago·Updated 14 days ago· 1
cv2.insertChannel
  • src
  • dst
  • result
◄coi0►

Some of the best classical image operations are single-channel by nature: deconvolution, most denoisers, anything built on a grayscale model of the world. Run one on a colour photo and the standard recipe is: split, process each plane, reassemble. cv2.insertChannel is the reassemble step, one channel at a time.

It's a low-level wrapper from bmad4ever/comfyui_cv, and it earns its place in the docs because the pack uses it in a shipped subgraph. Look at CV Wiener Filter (deblur, color): three single-channel deblurs, a three-channel zero canvas, and then three insertChannel nodes with coi 0, 1 and 2 labelled "Insert B", "Insert G", "Insert R". That's the node's whole job, and it's the clearest description of it you'll find.

Mechanism: dst is the canvas, src is the plane

cv2.insertChannel(src, dst, coi) writes the single-channel src into channel index coi of the multi-channel dst, and returns the result. Two things follow from the pack's own implementation notes:

  • The output echoes dst, not src. The node's primary input is explicitly dst for exactly this reason - the result's nature is the canvas's nature. So if you're into a 3-channel IMAGE, you get an IMAGE out (COMFY_MATCHTYPE_V3, so the wire keeps its type).
  • Your dst array is not mutated. cv2's native version writes in place; the wrapper hands cv2 a private copy and returns that instead, which matters the moment you branch one source array into two places in the graph.

coi is a plain INT and it's 0-based: 0 = first channel. On an OpenCV image that arrives from ComfyUI, channel order is BGR - so 0 is blue, 1 green, 2 red. The shipped Wiener subgraph labels them that way, which is a useful reminder that "channel 2" in this pack means red only if nothing upstream swapped the order.

Its inverse is cv2_extractChannel - same coi, one channel out. Splitting and reassembling is how you do per-channel work in this pack, and there are ready-made subgraphs for the common cases (CV Split Channels (3), CV Merge Channels (3)).

Where it's genuinely useful

  • Per-channel filtering. Wiener deconvolution, per-channel sharpening, channel-wise denoise, or a chromatic-aberration fix that scales each plane separately.
  • Assembling a synthetic image. Build a three-plane image - depth as one channel, a mask as another, an index map as a third - and hand it downstream as one thing.
  • Channel surgery. Replace the blue channel of a shot with something else and see what the composite looks like. Cheaper than a Photoshop round trip when you're iterating.

Installing the pack

Manager → search comfyui_cv, or:

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

Python ≥ 3.12 and a recent ComfyUI built on the V3 node API; the OpenCV line is curated against 5.0.0.93. insertChannel itself is core OpenCV, so it's there as long as the pack loads at all. If any of the pack's nodes are missing, that's your clue to check the contrib wheel situation - a plain opencv-python install over a contrib one strips contrib submodules silently, and tools/repair_opencv_contrib.py --check tells you whether that's what happened.

Gotchas

Sizes and dtypes must line up. cv2 asserts if src isn't single-channel, if dst doesn't have that many channels, or if the two aren't the same width/height/type. When you build a canvas with a zeros node, give it the same dtype as the planes you'll insert - float planes into a uint8 canvas is the mistake that produces a white or black image with no error you'd notice.

dst has to exist first. There's no "make a 3-channel image from scratch" mode here. The pattern is: create a three-channel canvas (the subgraph multiplies an image by 0 to get one of matching shape and dtype), then insert into it three times, chaining each node's output into the next node's dst.

Watch the BGR order. If your "red" channel ends up in the blue slot you'll get a colour cast that looks like a bug elsewhere.

As with everything in this pack: it's a personal, LLM-assisted project, and the README says not to run it in production without reviewing the code you rely on. This node is a thin wrapper around a stable cv2 call, which is the reassuring end of that spectrum.

Categoryimage/CV/low-level/cv2 I

Inputs (3)

NameTypeDefaultDescription
srcNPARRAY,IMAGE,MASKinput array 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.
dstCOMFY_MATCHTYPE_V3output array The image output(s) echo this input's format. The low-level cv2 function writes its result into this array in place, but this wrapper passes cv2 a private copy, so your input array is never modified. 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.
coiINT0-2147483648–2147483647index of channel for insertion

Outputs (1)

NameTypeDescription
resultCOMFY_MATCHTYPE_V3Echoes the 'dst' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY.