Install DinoHash via npm:
npm install @proteus-labs/dinohashPackage links:
Don't want to run the model yourself? A free hosted endpoint is available on Hugging Face Spaces (CPU). Send an image, get a perceptual hash back — no setup and no per-request cost.
Endpoint: proteus-photos/DINOHash (Space)
from gradio_client import Client, handle_file
client = Client("proteus-photos/DINOHash")
hex_hash, bits = client.predict(
handle_file("image.jpg"),
"dinov2-512bit (flagship)", # model
api_name="/dinohash",
)
print(hex_hash)The endpoint runs on a free CPU instance and sleeps when idle (it wakes automatically on the next request). For high throughput, self-host the ONNX model with the npm package below.
Use DinoHash in your JavaScript or TypeScript projects. The package uses ONNX Runtime for inference.
const { downloadModel, loadModel, hash } = require('@proteus-labs/dinohash');
const path = require('path');
async function main() {
// Download the model from Hugging Face
const modelUrl = 'https://huggingface.co/proteus-photos/DINOHash/resolve/main/dinov2_vits14_reg_96bit_dynamic.onnx';
const modelPath = path.join(__dirname, './models/dinov2_vits14_reg_96bit.onnx');
// Download and load the model
await downloadModel(modelUrl, modelPath);
const session = await loadModel(modelPath, 'cpu'); // Use 'cuda' for GPU inference if available
// Hash images
const imagePaths = [
path.join(__dirname, 'image1.jpg'),
path.join(__dirname, 'image2.jpg')
];
const results = await hash(session, imagePaths);
console.log(results);
}
main();import { downloadModel, loadModel, hash } from '@proteus-labs/dinohash';
import path from 'path';
const modelUrl = 'https://huggingface.co/proteus-photos/DINOHash/resolve/main/dinov2_vits14_reg_96bit_dynamic.onnx';
const modelPath = path.join(process.cwd(), './models/dinov2_vits14_reg_96bit.onnx');
await downloadModel(modelUrl, modelPath);
const session = await loadModel(modelPath, 'cpu');
const hashes = await hash(session, ['image1.jpg', 'image2.jpg']);Download the ONNX model from Hugging Face to a local path.
modelUrl (string): URL to the ONNX model file (e.g., from Hugging Face)modelPath (string): Local file path where the model should be savedPromise<void> - Resolves when download completesLoad the ONNX model for inference.
modelPath (string): Path to the downloaded ONNX model fileprovider (string): Inference provider - 'cpu' or 'cuda' (for GPU)Promise<InferenceSession> - ONNX Runtime inference sessionGenerate perceptual hashes for one or more images using the loaded model session.
session (InferenceSession): The loaded ONNX model sessionimagePaths (string | string[]): Single image path or array of image pathsPromise<string | string[]> - Hash string(s) for the input image(s)The DinoHash model is hosted on Hugging Face:
Model: proteus-photos/DINOHash
License: MIT
Model Type: Image Feature Extraction (ONNX)
Architecture: DINOv2 ViT-S/14
The ONNX model file can be downloaded directly:
https://huggingface.co/proteus-photos/DINOHash/resolve/main/dinov2_vits14_reg_96bit_dynamic.onnxThe recommended DinoHash models output hash bits directly (one bit per output logit — positive → 1, negative → 0), with the PCA projection baked into the ONNX graph. Download by URL and pass to loadModel:
| Model | Bits | File |
|---|---|---|
| DINOv2 ViT-B/14 (flagship) | 512 | proteus-photos/DINOHash/resolve/main/dinov2_vitb14_reg_512bit_dynamic.onnx |
| DINOv2 ViT-S/14 | 96 | proteus-photos/DINOHash/resolve/main/dinov2_vits14_reg_96bit_dynamic.onnx |
Prefix any file above with https://huggingface.co/ to get the full download URL.
Additional backbones — DINOv3 (ViT-S/16, ViT-S/16+, ConvNeXt-Tiny/Small), distilled students (ResNet, EfficientNet, MobileNet, ViT-Tiny, XCiT-Tiny) and self-supervised baselines (DINO, MoCo, SwAV, MAE-Lite) — output raw image embeddings (apply your own PCA / sign-binarization). All of them, plus the raw training checkpoints, live in proteus-photos/DINOHash.
const { downloadModel, loadModel, hash } = require('@proteus-labs/dinohash');
const path = require('path');
const fs = require('fs');
async function hashImages(imagePaths) {
// Ensure models directory exists
const modelsDir = path.join(__dirname, 'models');
if (!fs.existsSync(modelsDir)) {
fs.mkdirSync(modelsDir, { recursive: true });
}
// Model configuration
const modelUrl = 'https://huggingface.co/proteus-photos/DINOHash/resolve/main/dinov2_vits14_reg_96bit_dynamic.onnx';
const modelPath = path.join(modelsDir, 'dinov2_vits14_reg_96bit.onnx');
// Download model if not already present
if (!fs.existsSync(modelPath)) {
console.log('Downloading model...');
await downloadModel(modelUrl, modelPath);
}
// Load model (use 'cuda' for GPU if available)
const session = await loadModel(modelPath, 'cpu');
// Generate hashes
const hashes = await hash(session, imagePaths);
return hashes;
}
// Usage
hashImages(['image1.jpg', 'image2.jpg'])
.then(hashes => {
console.log('Hashes:', hashes);
// Compare hashes (hamming distance)
if (hashes.length === 2) {
const similarity = compareHashes(hashes[0], hashes[1]);
console.log('Similarity:', similarity);
}
})
.catch(console.error);
function compareHashes(hash1, hash2) {
// Simple hamming distance comparison
let distance = 0;
for (let i = 0; i < Math.min(hash1.length, hash2.length); i++) {
if (hash1[i] !== hash2[i]) distance++;
}
return 1 - (distance / Math.max(hash1.length, hash2.length));
}Check out our documentation or contact us for support and custom integrations.