Use ImageHashers for image processing
mainperception.hashers.hasher.ImageHasher class. You can use the functions provided in the perception.hashers.image module to generate hashes for image data.repository·main·Indexed 41 days ago
https://github.com/thorn-oss/perceptionA toolkit for perceptual hashing research, development, and production use, designed for media deduplication and content identification. It supports various hashing algorithms including PHash, PDQ, DHash, AverageHash, Marr-Hildreth, Color Moment, Block Mean, and WaveletHash. The library includes comprehensive benchmarking tools for image and video datasets, transformation pipelines, and recall metric evaluation.
perception.hashers.hasher.ImageHasher class. You can use the functions provided in the perception.hashers.image module to generate hashes for image data.perception.hashers.hasher.VideoHasher class. You can use the functions provided in the perception.hashers.video module to generate hashes for video data.You can evaluate the performance of different image hashers by applying various transformations (like blur, noise, or rotation) to a dataset and measuring how well the hashers maintain similarity. The process involves loading a dataset, applying transformations, computing hashes, and calculating recall metrics at a specific precision threshold.
Key steps:
benchmarking.BenchmarkImageDataset.from_tuples to create a dataset from file paths and metadata.dataset.transform() to apply a dictionary of transformation functions. This can save the results to a storage_dir for later reloading.benchmarking.BenchmarkImageTransforms.load() to reload a previously computed transformed dataset from a directory or zip file.transformed.compute_hashes(hashers=...) where hashers is a dictionary mapping names to hasher instances.hashes.compute_threshold_recall(precision_threshold=...) to get performance metrics like recall and precision.import os
import glob
from perception import benchmarking, hashers
from perception.hashers.image.pdq import PDQHash
# 1. Load dataset
dataset = benchmarking.BenchmarkImageDataset.from_tuples(files=[
(filepath, filepath.split(os.path.sep)[-2]) for filepath in glob.glob('path/to/images/*.jpg')
])
# 2. Define transforms and apply them
transforms = {'blur': some_blur_func, 'noop': lambda x: x}
transformed = dataset.transform(transforms=transforms, storage_dir='transformed', errors="raise")
# 3. (Optional) Reload later
transformed = benchmarking.BenchmarkImageTransforms.load(path_to_zip_or_directory='transformed')
# 4. Define hashers and compute
hashers_dict = {'phash': hashers.PHash(hash_size=16), 'pdq': PDQHash()}
hashes = transformed.compute_hashes(hashers=hashers_dict)
# 5. Compute recall at 99.99% precision
metrics = hashes.compute_threshold_recall(precision_threshold=99.99).reset_index()You can evaluate how well different hashers perform against various video transformations using the perception.benchmarking module. The process involves:
BenchmarkVideoDataset.from_tuples to create a dataset from file paths and metadata (e.g., scene labels).perception.benchmarking.video_transforms. A noop (no-operation) transform is required as the baseline.dataset.transform(transforms=..., storage_dir=...) to generate the transformed video files. This can be reloaded later using BenchmarkVideoTransforms.load().perception.hashers) and use transformed.compute_hashes(hashers=..., max_workers=...) to generate the hash data.BenchmarkHashes.load() and call compute_threshold_recall() to find the optimal thresholds for a target precision.import perception.benchmarking
import perception.hashers
# 1. Load dataset
dataset = perception.benchmarking.BenchmarkVideoDataset.from_tuples(
files=df[['filepath', 'scene']].itertuples(index=False)
)
# 2. Define transforms (noop is required)
transforms = {
'noop': perception.benchmarking.video_transforms.get_simple_transform(width=240, height=240),
'shrink': perception.benchmarking.video_transforms.get_simple_transform(width='ceil(0.7*iw/2)*2', height='ceil(0.7*ih/2)*2')
}
# 3. Transform and save
transformed = dataset.transform(transforms=transforms, storage_dir='benchmarking_videos')
# 4. Compute hashes
hashers = {
'my_hasher': perception.hashers.PHashU8(hash_size=12)
}
hashes = transformed.compute_hashes(hashers=hashers, max_workers=5)
hashes.save('hashes.csv')
# 5. Evaluate
benchmark_hashes = perception.benchmarking.BenchmarkHashes.load('hashes.csv')
benchmark_hashes.compute_threshold_recall(precision_threshold=99.9, grouping=['transform_name'])Video deduplication is achieved by extracting representative frames from each video and comparing those frames across the dataset.
hashers.FramewiseHasher to extract hashes from video frames.frames_per_second to control sampling density.interframe_threshold and quality_threshold to ensure extracted frames are sufficiently different and high quality.hasher.compute_parallel to generate hashes for all files.tools.deduplicate_hashes to find matches.import perception.hashers
import perception.tools
# 1. Setup the frame hasher
frame_hasher = perception.hashers.PHash(hash_size=16)
video_hasher = perception.hashers.FramewiseHasher(
frames_per_second=1,
frame_hasher=frame_hasher,
interframe_threshold=50,
quality_threshold=90
)
# 2. Compute hashes for video files
filepaths = ['video1.m4v', 'video2.gif']
hashes = video_hasher.compute_parallel(filepaths=filepaths)
# 3. Flatten hashes into (filepath, hash_string) tuples
hashes_flattened = perception.tools.flatten([
[(h['filepath'], h_str) for h_str in h['hash']]
for h in hashes
])
# 4. Find duplicates across the flattened hashes
duplicates = perception.tools.deduplicate_hashes(
hashes=hashes_flattened,
threshold=50,
hasher=video_hasher
)Install the core perception package using pip:
pip install perceptionTo make deduplication more robust against rotations or flips, use the isometric=True flag in tools.deduplicate. This will compare not just the original images, but also their 8 isometric transformations.
To improve performance on large datasets (like the Caltech 256 dataset), group files by category (e.g., by folder) and run deduplication within each group to avoid unnecessary pairwise comparisons between unrelated categories.
from perception import hashers, tools
# Grouping files by category (example logic)
# current_filepaths = [list of files in one category]
comparison_hashers = [(hashers.PHash(hash_size=16), 0.2)]
duplicate_pairs = tools.deduplicate(
files=current_filepaths,
hashers=comparison_hashers,
isometric=True
)To install the latest version directly from the GitHub repository, use the following command:
pip install git+https://github.com/thorn-oss/perception.git#egg=perceptionIf you need to perform performance comparisons or benchmarking, install the benchmarking extra. This includes the necessary dependencies for these tasks.
# Install from PyPi with benchmarking support
pip install perception[benchmarking]
# Install from GitHub with benchmarking support
pip install opencv-python git+https://github.com/thorn-oss/perception.git#egg=perception[benchmarking]You can install perception using pip. Note that you must install opencv-python separately as a prerequisite.
# Install OpenCV prerequisite
pip install opencv-python
# Install perception from PyPi
pip install perceptionThe tools.SaferMatcher class supports different authentication methods depending on your Thorn Safer service subscription:
api_key parameter.The perception package provides optional extras for specific functionalities.
approximate-deduplication: FAISS-based approximate-nearest-neighbor deduplication and graph community/clique detection (used by perception.approximate_deduplication and perception.local_descriptor_deduplication).benchmarking: Tools for benchmarking perceptual hashes.matching: Async matching utilities.pdq: Facebook's PDQ hash support.If you use uv, extras are handled automatically:
uv pip install "perception[benchmarking]"Installing the benchmarking extra introduces a conflict because it depends on albumentations (which requires opencv-python-headless), while perception requires opencv-contrib-python-headless. To resolve this with plain pip, you must force-reinstall the contrib variant:
pip install "perception[benchmarking]"
pip install --force-reinstall --no-deps opencv-contrib-python-headless