How a perceptual hash works

Re-save a photo and its SHA-256 changes from end to end, even though — to the eye — it is the very same image. That is the correct behaviour of a cryptographic hash, and it is exactly what makes it useless for answering the question you are actually asking: «is this the same photo as that one?»

The problem, in one example

Take a photograph. Open it, save it at quality 80 instead of 95. The visual content is indistinguishable, but the bytes are another matter: JPEG compression recomputed every block. And the cryptographic hash, designed to amplify any one-bit difference until half the digest changes, tells you the two files have nothing in common.

It is right. The two files have nothing in common. But you were not asking about files.

CRYPTOGRAPHIC HASH — answers «these are different files» photo.jpg photo.jpg re-saved at q80 SHA-256 a72c479e834af13a7ffb7765… 7f82fc11cb2d79f7cdbed898… no relationship recoverable · the avalanche effect erases similarity PERCEPTUAL HASH — answers «this is the same image» photo.jpg photo.jpg re-saved at q80 pHash 1011 0110 1100 1001 … 1011 0110 1110 1000 2 bits differ out of 64 · 96.9% similarity
Same content, two different files. The cryptographic and the perceptual hash answer two different questions, and both answer correctly.

The idea: invert the avalanche effect

A perceptual hash is built with the opposite goal to SHA-256's. It wants small changes in the image to cause small changes in the fingerprint. It is no longer a one-way function: it is a function that compresses visual appearance into a few dozen bits, throwing away everything the eye does not register — noise, fine detail, compression micro-differences — and keeping what remains.

The procedure is always the same, whichever algorithm you pick:

  1. Shrink the image to a tiny grid, typically 8×8 pixels. Every detail vanishes: the structure of lights and shadows remains.
  2. Convert to greyscale. To these algorithms, colour is noise.
  3. Compare each cell against a threshold (the mean, the neighbouring pixel, the median of the coefficients). Each comparison yields one bit: 1 or 0.
  4. Concatenate the bits. Sixty-four comparisons, sixty-four bits: that is the perceptual fingerprint.

Resizing, re-compressing, changing format: none of these operations meaningfully moves the lights and shadows of an 8×8 grid. So none of them changes more than a few bits.

Reading the result: Hamming distance

Two perceptual fingerprints are not compared by asking «are they equal?». They are compared by counting how many bits differ. That number is the Hamming distance, and it has an immediate meaning: how many of the sixty-four questions about the image's structure got a different answer.

Probatio also turns it into a percentage, with a formula that is exactly what it looks like:

similarity = (1 − distance ÷ total bits) × 100

Two 64-bit fingerprints differing by 2 bits give 96.9% similarity. If they differ by 32 — half, the expected value between two randomly chosen images — similarity is 50%, which is the technical way of saying «no relationship».

50%75%87%95%100% 32 bits16 bits8 bits3 bits0 bits Hamming distance over 64 bits unrelated images crop · retouch · adjacent frames re-compressed · resized Probatio issues no «same / different» verdict: it shows distance and percentage for all three algorithms. You choose the threshold, and you declare it in the report.
The bands are indicative, not normative: they depend on the algorithm, on bit depth and on the kind of images involved. Calibrate them on the case at hand.

No automatic verdict, and that is a feature

Many tools spit out a «match / no match» based on a threshold someone else picked. Probatio does not: image comparison returns, for each of the three algorithms (aHash, dHash, pHash), the fingerprint of both images, the Hamming distance and the similarity percentage.

The reason is procedural before it is technical. A threshold is a decision, and in an expert report decisions are declared and justified. Writing «the tool said match» is indefensible; writing «the two images differ by 4 bits out of 64 across all three algorithms, a value consistent with re-compression and inconsistent with different subjects» is a statement that survives cross-examination.

Depth: 64, 144 or 256 bits

Probatio computes fingerprints at three depths, corresponding to 8×8, 12×12 and 16×16 grids.

  • 64 bits is the classic value, suited to finding the same image again after re-compression or resizing. It is tolerant — sometimes too tolerant on images that resemble each other.
  • 144 and 256 bits retain more structure and better separate images that look alike (two consecutive video frames, say), but become more sensitive to crops and rotations.

There is no universally right choice. There is a right choice for the question: finding an image again demands tolerance, telling apart two similar images demands resolution.

What a perceptual hash does not do

  • It is not proof of identity. Two images at distance zero are visually indistinguishable at the grid's resolution, not necessarily identical. For identity there is SHA-256.
  • It is not one-way. A fingerprint leaks a very vague idea of the distribution of lights and shadows. Do not treat it as anonymous data.
  • It does not resist an adversary. Anyone who knows the algorithm can craft an image with whatever fingerprint they like. It is for searching, not for sealing.
  • It does not reason about content. It has no idea what the image depicts. It sees a grid of greys.

In a case file the two live together nicely: SHA-256 seals the file, the perceptual hash finds the image. The first question is «was it altered?». The second is «have we seen it before?». Conflating them is the fastest way to answer both badly.