RetinaHash
Lightweight, pure-NumPy perceptual hashing for images
RetinaHash computes compact, rotation-invariant fingerprints of images using only NumPy...no OpenCV, no PIL, no Scipy.
Perfect for duplicate detection, near-duplicate search, and lightweight image clustering.
Features
- Pure NumPy – runs anywhere Python runs
- Rotation invariant – same hash for 0°, 90°, 180°, 270° rotations
- Auto-crop – strips solid scanner borders automatically
- Extensible – plug-in architecture for new hash algorithms
- Fast – ~1 ms per 512×512 image on a laptop CPU (TRUST ME BRO Benchmark, lol.)
Install
pip install retinahash
Or better, because you are sane and use uv to manage your projects:
uv add retinahash
(or drop the retinahash/ folder into your project—zero dependencies beyond NumPy).
Quick Start
import imageio.v3 as iio # any loader will do but numpy array is expected
from retinahash import RetinaHash
img = iio.imread("photo.jpg")
h = RetinaHash.phash(img, rotation_invariant=True)
print(h) # 16-char hex string, e.g. 'a5f3c1e8d2b4906e'
Compare two images (via Hamming distance):
h1 = RetinaHash.phash(img1)
h2 = RetinaHash.phash(img2)
distance = RetinaHash.distance(h1, h2)
API
RetinaHash.hash(image, method='phash', hash_size=8, rotation_invariant=False, auto_crop=False)
RetinaHash.phash(image, **kwargs) – convenience wrapper
RetinaHash.distance(hex1, hex2) – Hamming distance between two hex hashes
Algorithms
| Key | Description |
|---|---|
phash |
DCT-based perceptual hash (default) |
More algorithms (ahash, dhash, whash, …) can be added by dropping a new module into retinahash/strategies/ and registering it in STRATEGIES.
Customisation
# 16-bit hash, auto-crop on, rotation invariant
h = RetinaHash.hash(img, method='phash', hash_size=16,
auto_crop=True, rotation_invariant=True)
License
MIT – do what you want, just keep the copyright notice. See LICENSE file.
That’s it—clone, hash, dedupe.
Metadata
Release files for retinahash 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| retinahash-0.1.1.tar.gz | 4.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| retinahash-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 10.4 kB
Release files / retinahash-0.1.1.tar.gz
| Download URL | retinahash-0.1.1.tar.gz |
|---|---|
| Size | 4.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2093f8aad8565f72e795ae8ea7fcf302876d6ffe2a2d19b2f44d37b30ed82311
|
|
BLAKE2b-256 checksum How to use checksums |
4995a7b63c33b4bad7fdd650b6bf75076ac2d9e1b3f5e78504da65337e9dd691
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / retinahash-0.1.1-py3-none-any.whl
| Download URL | retinahash-0.1.1-py3-none-any.whl |
|---|---|
| Size | 6.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4e85d51bf047f86eb38433064ff3033b3f35bae503440da7a31ce80831276192
|
|
BLAKE2b-256 checksum How to use checksums |
aaf334329ccfd4d4e7f84a52292473d3b3cb198c4ee8542f861ca5a287945089
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|