Quaternion Grayscale
A desaturation node that's pure math
- image
- grayscale_image
ComfyUI already ships a perfectly good ImageToImage-era trick for desaturation: subtract the mean of your RGB channels, or just drop a Color/Brightness node in. So why would you reach for a node that turns every pixel into a quaternion first? Because you want a grayscale that's defined by math, not by perception - and that's honestly a lot more useful than it sounds.
This is a small utility from bemoregt, one node in a one-node pack. It takes any color image, encodes each pixel as a pure quaternion q = R·i + G·j + B·k, and reduces it to a scalar through one of three operations. The output is a standard 3-channel grayscale IMAGE, so it plugs into anything downstream that expects a normal image. There's no model, no download, no GPU grunt - just a bit of torch arithmetic that runs in milliseconds.
The three methods, and when you'd actually care
The method dropdown is the whole show. All three map black to 0 and white to 1; they diverge on colored pixels:
magnitude(default) -√(R²+G²+B²)/√3. The L2 norm of the color vector. Pure red, green, or blue all land at ≈0.577, a mid-gray. This is an equal-weight RMS, so it's the one to pick when no channel deserves extra say.projection-(R+G+B)/3. A plain channel average, dressed up as a projection onto the gray-axis quaternion(i+j+k)/√3. Pure primaries come out at ≈0.333. This is the familiar "average the channels" conversion, just with fancier paperwork.sandwich- rotates the color vector 90° around the gray axis(1,1,1)/√3viaµ·q·µ̄, then takes the vector norm. Same 0.577 primaries as magnitude, and in practice produces nearly identical output for most images - it's the academically interesting one, not the practically different one.
Here's the thing worth knowing before you use this for anything serious: none of these are luminance. A proper grayscale weights channels like 0.299R + 0.587G + 0.114B because human eyes are green-biased. This node deliberately ignores all that - magnitude turns a pure red pixel into a bright mid-gray instead of the dark gray your eyeballs expect. If you're making a mask or a prepass that feeds a model trained on perceptual luminance, you'll get subtly wrong results. But if your RGB channels are data - a normal map, a channel-encoded feature image, anything where the relationship between channels is the information - the symmetric, color-blind math is exactly what you want. That, plus the educational value of seeing sandwich products do something real, is the node's actual niche.
What you wire in
Just two inputs:
image- anyIMAGEtensor in[B, H, W, C], values in[0, 1]. Batch-friendly; the README's own test runs a 4-image batch through cleanly.method- the three-way combo above, defaultmagnitude.
Output is a single grayscale_image in [B, H, W, 3] - three identical channels, so it composes with every standard node that takes an image. A small gotcha from the source: if the input already has fewer than 3 channels, the node passes it through unchanged rather than converting, which is sensible but can quietly confuse you if you were expecting a transform.
Installing it
This is the easy part of the pack - there is no requirements.txt, no model files, nothing but Python ≥3.9 and PyTorch (which ComfyUI already has). Either use ComfyUI Manager and search "Quaternion Grayscale", or:
cd ComfyUI/custom_nodes
git clone https://github.com/bemoregt/ComfyUI_Quaternion_Grayscale
Then restart ComfyUI and look for Quaternion Grayscale under image/quaternion. The README also includes a standalone test_node.py you can run without ComfyUI at all (python test_node.py) - handy for verifying your torch install is sane.
Where people get burned
Honestly? Barely anywhere. No dependencies to conflict, no hidden models, no network calls. The real traps are conceptual, not technical: expecting perceptual luminance when the node is explicitly color-blind, and using it on data-channel images where the equal-weight math subtly changes what the downstream model reads. If you just want a normal desaturation, use ComfyUI's built-in color tools and keep this one for the cases where the math itself is the point. It's a niche node with a niche job - but when that niche hits, nothing else in the graph does it.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| method | COMBO | magnitude | 3 options: magnitude, projection, sandwich |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| grayscale_image | IMAGE | — |