Nodes/ComfyUI CV/cv2.img_hash.radialVarianceHash
ComfyUI Node

cv2.img_hash.radialVarianceHash

The hash that survives a rotation, and reads its score backwards

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.img_hash.radialVarianceHash
  • inputArr
  • nparray
◄sigma1.0000►
◄numOfAngleLine180►

"Did I already generate this?" is a harder question than it looks. A rerun with a nudged seed comes back 2% different, a rescaled copy has different pixels at every coordinate, and a pixel diff says "totally unrelated" to both. Perceptual hashes exist to answer that question, and this node computes one specific flavour of them: radial variance.

It's one of the ~470 auto-generated cv2.* wrappers in bmad4ever/comfyui_cv, a pack that exposes OpenCV to ComfyUI as nodes. If you've been reaching for ImageMagick and a shell script to batch-check for duplicates, this is that job, in the graph.

What it actually computes

Blur the image a little, draw a set of rays out from the centre, and measure how much the pixel values vary along each ray. That's the whole trick. Rotating an image slides content along those rays rather than across them, so the variance profile barely moves - which is why radial variance (with colorMomentHash, the other one) is the rotation-tolerant member of the img_hash family. The pHash sibling is more robust to rescaling and compression; this one is the one you want when your "duplicate" has been rotated.

The output is a raw hash array. inputArr takes a ComfyUI IMAGE or MASK directly (frame 0 of a batch, or the whole batch frame-by-frame if you pass the same batch size everywhere), or an NPARRAY; 8-bit 1/3/4-channel input is what cv2 expects. Two advanced widgets sit under it: sigma (the Gaussian blur applied before the projections, default 1.0) and numOfAngleLine (how many projection angles, default 180 - more angles means finer rotation discrimination).

The trap: this hash's score means the opposite

Here's the part that bites. cv2's ImgHashBase.compare() is not consistent across the family. Most algorithms return a distance - 0 means identical. radialVarianceHash returns a peak-correlation similarity, where 1.0 means identical. Write distance <= threshold by hand and for this algorithm alone you've inverted your test: it will call every unrelated pair a match.

The pack knows this (the comment in its source is unusually blunt about it) and its curated CV Image Hash Compare node converts the score so that 0 = identical, larger = more different, for every algorithm. It also hashes and compares in one node, which is the only shape that's actually usable in a workflow - a lone hash is not a decision. Reach for that node first; reach for this raw wrapper when you want the hash as data (to store, to build your own comparison, or to feed cv2_norm with NORM_HAMMING yourself).

Installing the pack

ComfyUI Manager → search comfyui_cv → install → restart, 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 (the V3 node API) are required, and the OpenCV version matters: the pack is curated against 5.0.0.93 and other builds may behave differently.

Gotchas

Contrib, not core. img_hash lives in OpenCV's contrib modules. If anything installed plain opencv-python or opencv-python-headless on top of your contrib wheel, it overwrote the shared cv2 in site-packages with a core-only build and every contrib node silently disappears - no error, just missing nodes. The pack ships tools/repair_opencv_contrib.py --check to diagnose it and --apply to fix it, but there's no install-time guard.

Change sigma, lose your archive. The hash is a function of those two widgets. If you've stored hashes from an earlier run with different settings, they aren't comparable anymore.

Node ids come from your install. The registry is generated from whatever the installed OpenCV exposes, so a function your build lacks simply isn't there. If the node is absent after a restart, that's usually why - not a broken install.

One honest note about the pack itself: the README says plainly that it was built with heavy use of LLMs, that some code may be overfitted to its own test cases, and that it isn't recommended for production without your own review. For a duplicate-detection helper in a personal workflow, that's fine. Just validate on your own images rather than trusting a threshold you read somewhere.

Categoryimage/CV/low-level/img_hash

Inputs (3)

NameTypeDefaultDescription
inputArrNPARRAY,IMAGE,MASKinput image want to compute hash value, type should be CV_8UC4, CV_8UC3, CV_8UC1. 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.
sigmaoptFLOAT1.0000-1e+38–1e+38Gaussian kernel standard deviation Preset to the OpenCV default (1.0).
numOfAngleLineoptINT180-2147483648–2147483647The number of angles to consider Preset to the OpenCV default (180).

Outputs (1)

NameTypeDescription
nparrayNPARRAY—