hashimage a simple crate to compute image hashes.
Computing an image hash should be fast and dead simple. For those reason, we use a Rust to perform all complex computation, while leaving to Python the ability to create and build upon the low-level implementation.
For Python3 bindings see shimagepy.
Warning
Until a stable-enough version is specified it won't be uploaded to either pypi.org or cargo.io. Therefore, be prepared to install via git clones.
You can easily install this library directly from the repository using cargo
cargo add --git https://github.com/ladezai/shimage.gitNote
Cargo will automatically fetch and compile the library when you build your project.
The shimage crate provides the following additional feature:
image: adds a compatibility layer between image-rs and this crate.
To enable features, just add the flag --features [FEATURE_NAME] to the cargo add command above.
The following hash techniques are implemented:
Perceptual, seesrc/phash.rs;Average, seesrc/ahash.rs;Median, seesrc/mhash.rs;DifferenceHashseesrc/dhash.rs.SimplexHashseesrc/shash.rs.
To read the rust documentation, with all its features, run
cargo doc --open --features image
inside the repository's clone.
A toy-example for the rust API, using the same interface as std::hash,
use shimage::{AverageHash, HashableImage};
use std::hash::{Hash, Hasher};
let mut data = Vec::from([15_u8; 64]);
let image = HashableImage::new().with_data(&data);
let mut hasher = AverageHash::new();
image.hash(&mut hasher);
assert_eq!(hasher.finish(), 0_u64);Moreover, images might be loaded via the image-rs crate using the feature image of the library,
use shimage::{AverageHash, HashableImage};
use image::{ImageBuffer, Rgb, ImageReader};
use std::hash::{Hash, Hasher};
// load the image using image-rs crate
let img: ImageBuffer<Rgb<u8>, Vec<u8>> = ImageReader::open("path/to/image.jpg")?
.decode()?
.to_rgb8(); // NOTE: GrayAlphaImage, GrayImage, Rgb32FImage, RgbImage, Rgba32FImage, RgbaImage are also supported
// load the image into the HashableImage type, add a pre-process to fasten the hashing procedure
let himage: HashableImage = HashableImage::from(img).with_preprocessing(PreProcess::Resize(32, 32));
let mut hasher = AverageHash::new();
himage.hash(&mut hasher);
println!("The image has average hash = {}", hasher.finish());We welcome contributions, but beware that this is a small side-project, hence I won't review fairly often. Please see CONTRIBUTING.md, for more details.
Similar repositories and projects:
- phash: far more complete than this crate, written in C/C++. Probably best for deployment usage.
- perception: a very feature rich implementation of the same core ideas, far more complete that this crate would ever be. Quite slow in comparison, but allows for multi-threading. Moreover, see Performance.
- imagehash: key difference is that this is written in python, we offer
python bindings via PyO3 (see the
shimagepyandshimagepy_core). Moreover, see Performance. - imagehash-rs: key difference is that this is not strictly dependent on the awesome
image-rs crate. Moreover, we use the same interface via Hash and Hasher traits from rust's
std.
Performance comparison between shimagepy and imagehash, were measured in benches/bench.py. The following bar plots are the result measure on an Apple M2 Air.
Warning
All measurements were executed via Python3 bindings. Memory measurements were not consistent as I measure them, therefore they are not showcased yet.

