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

cv2.img_hash.colorMomentHash

The one hash that doesn\u2019t care about rotation

By bmad4ever·Created 4 months ago·Updated 14 days ago· 1
cv2.img_hash.colorMomentHash
  • inputArr
  • nparray

Every other hash in this pack is a bitmap comparison wearing a clever mask. Turn the image 90 degrees and the bits shuffle, because the pixels moved. colorMomentHash is different: it summarises the image by its colour moments instead of its spatial layout, so a rotated version of the same picture hashes to nearly the same value. That is a rare property, and it is the reason to reach for this node specifically.

The trade is that it stops being a byte string. The hash is a short vector of floating-point moments, so the comparison is an L2 distance, not a Hamming count - the author's tooltip warns about exactly this, and also flags it as the family's rotation-tolerant member. That is a different comparison contract from its four siblings, and mixing them up produces nonsense numbers rather than an error.

Use it when rotation is plausible: matching a reference against scanned or photographed material at unknown orientation, finding the same product shot from different angles of a turntable, de-duplicating generated variations where the subject rotates. Use pHash when the answer should be "same picture, same orientation".

How it works

Colour moments are statistical summaries of the colour distribution - mean, variance, skew across channels, and the cross terms between them. Because they describe what colours are present and how they are distributed rather than where, a rotation does not move them. That also means two completely different images with a similar palette can hash close together, which is why this is a coarse similarity signal and not an identity check.

Two consequences worth internalising before you build on it:

  • Compare with an L2 norm, not Hamming. The values are floats and can be small; the pack's curated compare node uses much smaller thresholds for this algorithm (around 1) than for the bit-based hashes (tens of bits).
  • The per-frame behaviour is the same as its siblings: this function is in the pack's per-frame list, so a batch of images is hashed image by image and the results come back stacked.

Inputs and output

  • inputArr - 8-bit, 3-channel colour in practice. The generic tooltip allows 1/3/4 channels, but this operation bins and gains colour channels, and the pack treats it as a function that needs 3-channel BGR input - so a single-channel MASK input does not get the batch treatment the colour path gets. Feed it a real colour image.
  • Output nparray - the float moment vector. Data, not pixels; read it with CV Array To Text if you need it as a string, Preview CV Array if you want to see the shape of the values.

Comparison: the curated CV Image Hash Compare node is the right tool. It lists "colour moment" among its algorithms, converts every algorithm to the same "0 = identical, larger = more different" contract (which matters here, because cv2's own compare is inconsistent across the family), and lets you set a per-algorithm threshold. If you are comparing raw hashes yourself, use cv2.norm with NORM_L2.

Install

Manager → search comfyui_cv (bmad4ever), 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 on the V3 node API, one pinned dependency, no models. img_hash is contrib-only: on a non-contrib OpenCV build this node simply does not exist, and because all four OpenCV distributions share one site-packages/cv2, a later pip install opencv-python from another pack can remove it silently. tools/repair_opencv_contrib.py --check / --apply in the pack repo handles the repair.

When it goes wrong

  • Distances in the hundreds. You are treating a float vector as a bit mask, or comparing it against a byte hash. Check the algorithm on both sides of the comparison - this is the one family member with a different metric.
  • Two visually unrelated images score as similar. Expected: colour statistics are coarse. Two images of the same palette, or a crop of a photo against the whole photo, can land close. Combine it with a structural hash (pHash) when you need both "same content" and "same layout".
  • A grayscale input gives you something odd. Feed colour. The operation is defined on colour channels.
  • Rotation robustness is not flip or perspective robustness. A mirrored image has different colour moments; a strong perspective change moves them too. It is specifically about rotation and (mild) scale.
  • You expected the same threshold as pHash. The curated node's default of 10 bits is calibrated for bit-based hashes; for colour moments you want a value near 1. Tune from a known pair, not from the default.
Categoryimage/CV/low-level/img_hash

Inputs (1)

NameTypeDefaultDescription
inputArrNPARRAY,IMAGE,MASKinput image want to compute hash value, type should be CV_8UC4, CV_8UC3 or 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.

Outputs (1)

NameTypeDescription
nparrayNPARRAY—