cv2.ximgproc.qdft
A Fourier transform for colour images that actually treats colour as one thing
- img
- nparray
Every routine colour operation you've ever done starts by collapsing the colour: convert to grey, run the filter, optionally re-colour. A quaternion Fourier transform refuses to do that. It treats the three channels as the imaginary parts of a quaternion (with a real part of zero) and transforms the whole thing as one complex-valued object, so the phase relationship between channels is part of the maths. That's the entire premise of the quaternion image-processing literature, and cv2.ximgproc.qdft is OpenCV's implementation of it. Colour edge detection, colour-sensitive denoising, colour watermarking: all of it starts here.
Be honest with yourself about the audience, though. This is research-grade code with essentially no documentation, and if "I want colour edges" is your actual goal, Canny over a colour-difference image gets you 90% of the way with 5% of the ceremony. This node is for when you're reproducing a paper.
How it works
Input has to be a 4-channel quaternion image, which you don't have in ComfyUI - you build it. The generated cv2.ximgproc.createQuaternionImage wrapper takes an 8-bit or float BGR image and returns a 4-channel (real, B, G, R) array; the pack's tooltip is explicit that this goes to the other q* nodes and never to an image consumer. That's the front door for the whole family: qconj, qunitary, qmultiply and this node all expect that format.
Then:
- img - the 4-channel quaternion array.
- flags -
forward (0)orDFT_INVERSE. OpenCV's own note is that it supports the inverse flag and nothing else; there's no scaling or shift bit to reach for here. - sideLeft - multiply the hypercomplex exponential on the left (
true) or the right (false). They are different transforms, and the author's tooltip has the rule you must not break: pair a forward and an inverse with the same side, or your round trip won't come back.
Output is a plain NPARRAY - it can't be anything else, because a 4-channel float quaternion array is not a picture. To see anything, you take the real part, slice a plane with CV Slice Array, or combine planes with the generated cv2.magnitude wrapper, then hand the result to CV Array → Image.
The standard round trip
Quaternion frequency-domain filtering: createQuaternionImage → qdft (forward) → modify the spectrum, either by qmultiply with a kernel that has been qdft'd itself, or by zeroing/masking coefficients with the pack's array nodes → qdft with DFT_INVERSE and the same sideLeft → take the real part or magnitude → convert back. Nothing in the chain is displayable until the last step, so build it with Inspect CV Data on each wire and verify shapes before you debug by eye.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
Restart ComfyUI, or install ComfyUI CV from ComfyUI Manager. Python ≥3.12, a recent ComfyUI on the V3 node API, opencv-contrib-python-headless~=5.0.0.93. No downloads. Contrib-only: qdft lives in ximgproc, so a non-contrib OpenCV wheel sharing that site-packages/cv2 makes it disappear from the menu. tools/repair_opencv_contrib.py --check tells you, --apply fixes it.
Common issues
Overload errors. You passed a 3-channel image. qdft wants four channels - the zero real part is not optional.
The inverse transform doesn't undo the forward one. Different sideLeft, or you skipped qunitary/conjugation where the recipe called for it. Quaternion multiplication doesn't commute, so order and side both matter everywhere in this family.
Output looks like noise. It is the spectrum. You're looking at it with the wrong eyes - take the magnitude and log-scale it if you want a "spectrum picture", which is what the pack's array maths nodes are for.
Zero community coverage. This pack has essentially no footprint in the ComfyUI discussion corpus, and these quaternion wrappers are the least-exercised part of it. The README's disclaimers are unusually relevant here: the pack was built with heavy LLM assistance, its own author warns that test-overfitted bugs may exist, and updates are not planned. Read the source before trusting a pipeline you can't see working.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| img | NPARRAY,IMAGE,MASK | - - - 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. | |
| flags | COMBO | forward (0) | - - - |
| sideLeft | BOOLEAN | false | - - - |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |