cv2.bitwise_and
Mask algebra on masks, bit surgery on photos
- src1
- src2
- mask
- result
Two honest uses. On two masks, bitwise_and is set intersection - the region that's in both. On an image, the mask= input is the standard OpenCV idiom for "keep this region, zero the rest", and that idiom is why this node appears in a dozen of the pack's own workflows.
Everything else you do with it on photographs is bit manipulation on 8-bit numbers, which is not the same thing as combining pictures, and it will look wrong in ways that are hard to reason about. Best to know which of the two you're doing.
How it works
Per-element bitwise AND across src1, src2 and (optionally) a mask that selects which output elements the operation is allowed to touch. Both arrays must have the same size and type. The result echoes src1's format, so MASK in gives MASK out.
Two pack-specific notes worth having:
- The wrapper refuses LATENT here, and the source says why in plain words: bit patterns of floats are meaningless. Don't try to bitwise-AND two latents; the pack won't let you, which is a kindness.
- A MASK arriving through the socket conversion becomes uint8 single-channel (0 or 255), which is what OpenCV's mask input expects. That's why mask wiring works without thinking about it.
The two idioms
Mask intersection. MASK ∧ MASK = the overlap. Two detections that must both be true, a face region inside a hand region, a colour mask inside a depth band. This is set algebra and it behaves exactly as you'd hope.
Apply a mask to an image. src1 = image, src2 = image, mask = your mask. Because the AND of an image with itself is itself, the operation is a no-op and the mask does all the work: masked pixels keep their values, everything else goes to zero (rather than wrapping or blending). This is how you cut a subject out with a mask in OpenCV-land, and the pack's inpaint, paste-through-homography and salt-and-pepper subgraphs all use it.
Inputs and outputs
src1(COMFY_MATCHTYPE_V3) - first array; decides the echoed output format.src2(NPARRAY,IMAGE,MASK) - second array or a scalar (a constant via CV Scalar).mask(optional) - CV_8U single-channel operation mask.- result - echoes
src1: MASK in → MASK out is the one you'll use most.
Where people get burned
A 3-channel image against a 1-channel mask in src2. That's a shape/type mismatch and OpenCV raises. The mask belongs in the mask socket, not in src2.
Soft masks. A feathered guard: 200 AND 100 is 236, not max(200, 100) = 200. Bitwise ops on gradient values produce numbers that are neither the minimum nor the maximum, so a blurred mask ANDed with anything comes back with a strange hard-edged look. For soft mats use arithmetic - cv2_multiply, cv2_divide, cv2_max - and keep booleans for binary masks.
Different sizes. Same rule as every binary op in the pack: same dimensions or an error.
Expecting a blend. AND is not a dissolve. If you want A where the mask is set and B where it isn't, that's cv2_copyTo-style compositing, cv2_addWeighted with a premultiplied alpha, or the pack's curated paste nodes - not boolean algebra.
Sibling confusion. cv2_bitwise_or is the union, cv2_bitwise_not is the complement, and cv2_bitwise_xor (also in the pack) is the symmetric difference - "in one but not both", the useful one for finding disagreement between two masks.
Install
ComfyUI Manager → comfyui_cv (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"
Restart ComfyUI. Python ≥ 3.12 and a recent ComfyUI on the V3 node API; behaviour is curated against OpenCV 5.0.0.93. The contrib wheel is the declared dependency - a non-contrib opencv-python over it silently strips the contrib submodules.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| src1 | COMFY_MATCHTYPE_V3 | first input array or a scalar. 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. | |
| src2 | NPARRAY,IMAGE,MASK | second input array or a scalar. 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. | |
| maskopt | NPARRAY,IMAGE,MASK | optional operation mask, CV_8U, CV_8S or CV_Bool single channel array, that specifies elements of the output array to be changed. 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 (1)
| Name | Type | Description |
|---|---|---|
| result | COMFY_MATCHTYPE_V3 | Echoes the 'src1' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY. |