cv2.Mahalanobis
The one node in this pack that isn't about images at all
- v1
- v2
- icovar
- float
Most of this pack is image manipulation; cv2.Mahalanobis is statistics. It takes two vectors and a matrix and returns a single number, and the whole point of it is that the number is scale-aware.
Euclidean distance treats every dimension equally, which is wrong the moment your dimensions have different units or spreads. The Mahalanobis distance divides each direction by how much it actually varies and takes the correlations out too: d = sqrt((v1 - v2)ᵀ · Σ⁻¹ · (v1 - v2)). Same numbers, but measured in standard deviations of your own data instead of raw arbitrary units.
In a ComfyUI workflow that shows up as: "is this histogram/embedding/feature vector close to the reference, given that some of its columns are noisy?" It's the classic anomaly-score and nearest-class distance for hand-crafted features - colour histograms, Hu moments, HOG-ish descriptors - and it's the principled version of the threshold you'd otherwise eyeball on plain L2.
The sockets, which are fussier than most
All three inputs are NPARRAY-only. The tooltips are blunt about it: v1, v2 and icovar are "a data array (points / matrix), NOT an image - only an NPARRAY link is accepted here". Which makes sense; a picture isn't a vector.
v1 and v2 are the two 1-D vectors you're comparing, and icovar is the inverse covariance matrix - you inverting it is your job, not the node's. The pack also wraps cv2.calcCovarMatrix and cv2.invert if you'd rather compute the whole thing in-graph, and you'd invert the covariance you compute there with cv2.invert.
The output is a single float on a FLOAT socket - not an array, not a picture. Feed it into whatever decides: a compare, a math expression, a threshold. That's the same shape of output as cv2.matchShapes and the enclosing-shape nodes, and it's why these nodes are plumbing rather than something you preview.
Installing the pack
ComfyUI CV (bmad4ever/comfyui_cv) - search "comfyui_cv" in ComfyUI Manager, 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, V3-API build, one pinned contrib OpenCV wheel, no models - this node does arithmetic on whatever arrays you hand it. cv2.Mahalanobis is core OpenCV, so it survives a non-contrib install; the rest of the pack does not.
Where people get burned
Shape mismatches, and OpenCV barely checks. icovar has to be N×N for N-element vectors, and OpenCV does very little validation before it starts indexing. Get it wrong and you can end up with a plausible-looking number that means nothing, rather than a clean crash. Sizes are on you - CV Array Shape and Inspect CV Data will tell you what you're actually holding.
Forgetting the inverse. Handing the plain covariance matrix in gives you a differently-weighted, wrong answer. It doesn't error.
Expecting it to take an IMAGE. It won't; the socket only accepts NPARRAY. If your data is still a picture, get it into an array first - cv2.calcHist or cv2.mean are the usual ways to squeeze a picture down to a vector.
Precision. The inputs are described as vectors, and float32 is what the rest of this pack produces by default. CV Cast Array if you need float64 for a numerically awkward covariance.
Contrib nodes vanishing. As ever with this pack: when another custom node pack installs a non-contrib opencv-python over the contrib wheel, the contrib-backed nodes silently stop registering because all four wheels share one site-packages/cv2. python tools/repair_opencv_contrib.py --check then --apply.
And a fair warning about the pack itself, because it applies most where the math is hardest to eyeball: the author states the code was written with heavy LLM assistance, warns about test-driven overfitting, and advises against production use without reading the source. A distance function is exactly the sort of thing where a subtle mistake gives you a number that looks fine.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| v1 | NPARRAY | first 1D input vector. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| v2 | NPARRAY | second 1D input vector. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| icovar | NPARRAY | inverse covariance matrix. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| float | FLOAT | — |