Rust图像哈希处理库image_hasher的使用:高效生成感知哈希值并实现相似图片搜索
Rust图像哈希处理库image_hasher的使用:高效生成感知哈希值并实现相似图片搜索
Image Hasher是一个用于获取图像感知哈希值的库。
感谢Neal Krawetz博士提出的Mean(aHash)、Gradient(dHash)和DCT(pHash)感知哈希算法。
使用方法
在Cargo.toml
中添加依赖:
image_hasher = "3.0.0"
以下是示例程序:
use image_hasher::{HasherConfig, HashAlg};
fn main() {
let image1 = image::open("image1.png").unwrap();
let image2 = image::open("image2.png").unwrap();
let hasher = HasherConfig::new().to_hasher();
let hash1 = hasher.hash_image(&image1);
let hash2 = hasher.hash_image(&image2);
println!("Image1 hash: {}", hash1.to_base64());
println!("Image2 hash: {}", hash2.to_base64());
println!("Hamming Distance: {}", hash1.dist(&hash2));
}
完整示例demo
下面是一个完整的示例,展示如何使用image_hasher库生成图像哈希并比较相似度:
use image_hasher::{HasherConfig, HashAlg};
use std::path::Path;
fn main() {
// 打开两张图片
let image_path1 = Path::new("image1.jpg");
let image_path2 = Path::new("image2.jpg");
let image1 = image::open(image_path1).expect("Failed to open image1");
let image2 = image::open(image_path2).expect("Failed to open image2");
// 配置哈希器(可以选择不同的算法: aHash, dHash, pHash)
let hasher = HasherConfig::with_hash_type(HashAlg::Gradient)
.hash_size(8, 8) // 设置哈希尺寸
.to_hasher();
// 生成哈希值
let hash1 = hasher.hash_image(&image1);
let hash2 = hasher.hash_image(&image2);
// 输出哈希值(Base64格式)
println!("Image1 hash: {}", hash1.to_base64());
println!("Image2 hash: {}", hash2.to_base64());
// 计算汉明距离(距离越小越相似)
let distance = hash1.dist(&hash2);
println!("Hamming Distance: {}", distance);
// 判断是否相似(通常距离<=10可认为相似)
if distance <= 10 {
println!("These images are similar!");
} else {
println!("These images are different.");
}
}
特性说明
-
支持的算法:
- Mean(aHash): 基于平均像素值的算法
- Gradient(dHash): 基于梯度变化的算法
- DCT(pHash): 基于离散余弦变换的算法
- Blockhash: Blockhash.io算法
-
性能优化:
- 可以使用
fast_image_unstable
特性来启用更快的图像处理
- 可以使用
-
最小Rust版本:
- 需要Rust 1.70.0或更高版本
许可证
双重许可:
- Apache License, Version 2.0
- MIT license
注意事项
- 要运行基准测试,需要使用Rust nightly版本:
cargo +nightly bench
-
对于相似图片搜索,通常汉明距离<=10表示图片相似,但具体阈值可以根据需求调整。
-
不同算法适用于不同场景:
- aHash: 简单快速,适合一般用途
- dHash: 对亮度变化敏感
- pHash: 更准确但计算更复杂
这个库可以方便地集成到Rust项目中,用于图像相似度比较、重复图片检测等场景。
1 回复
Rust图像哈希处理库image_hasher的使用指南
介绍
image_hasher
是一个Rust库,用于计算图像的感知哈希(perceptual hash),可用于相似图片搜索、重复图片检测等场景。它能够将图像内容转换为紧凑的哈希值,即使图像经过缩放、旋转或轻微修改,相似的图像仍会产生相似的哈希值。
主要特性:
- 支持多种哈希算法(包括aHash、dHash、pHash等)
- 高效处理大图像(自动缩放)
- 支持多种图像格式(通过
image
库) - 计算汉明距离比较哈希相似度
安装
在Cargo.toml中添加依赖:
[dependencies]
image_hasher = "1.1"
image = "0.24" # 用于加载图像
基本使用方法
1. 计算图像哈希
use image_hasher::{HasherConfig, ImageHash};
use image::io::Reader as ImageReader;
use std::path::Path;
fn compute_hash(image_path: &Path) -> ImageHash {
// 加载图像
let img = ImageReader::open(image_path)
.unwrap()
.decode()
.unwrap();
// 创建hasher并计算哈希
let hasher = HasherConfig::new().to_hasher();
hasher.hash_image(&img)
}
fn main() {
let hash = compute_hash(Path::new("test.jpg"));
println!("Image hash: {:?}", hash.to_base64());
}
2. 比较两个图像的相似度
use image_hasher::HashAlg;
fn compare_images(img1_path: &Path, img2_path: &Path) -> f32 {
let hasher = HasherConfig::with_bytes_type::<[u8; 8]>()
.hash_alg(HashAlg::Gradient)
.to_hasher();
let img1 = ImageReader::open(img1_path).unwrap().decode().unwrap();
let img2 = ImageReader::open(img2_path).unwrap().decode().unwrap();
let hash1 = hasher.hash_image(&img1);
let hash2 = hasher.hash_image(&img2);
// 计算汉明距离并转换为相似度百分比
let dist = hash1.dist(&hash2);
let similarity = 1.0 - (dist as f32 / hash1.as_bytes().len() as f32);
similarity * 100.0
}
fn main() {
let similarity = compare_images(Path::new("img1.jpg"), Path::new("img2.jpg"));
println!("Similarity: {:.2}%", similarity);
}
高级用法
1. 使用不同的哈希算法
use image_hasher::{HashAlg, HasherConfig};
let hasher = HasherConfig::new()
.hash_alg(HashAlg::DoubleGradient) // 使用双梯度哈希算法
.hash_size(16) // 设置哈希大小为16x16
.to_hasher();
支持的算法:
Mean
(aHash)Gradient
(dHash)Blockhash
DoubleGradient
VertGradient
HorzGradient
2. 构建简单的图片搜索引擎
use std::collections::HashMap;
use std::path::{Path, PathBuf};
struct ImageDatabase {
hasher: image_hasher::Hasher,
hashes: HashMap<PathBuf, ImageHash>,
}
impl ImageDatabase {
fn new() -> Self {
let hasher = HasherConfig::new().to_hasher();
Self {
hasher,
hashes: HashMap::new(),
}
}
fn add_image(&mut self, path极好的,您已经提供了完整的`image_hasher`使用指南内容。由于内容中没有图片,我不会添加任何图片。以下是基于您提供的内容的完整示例demo:
```rust
//! 完整示例:使用image_hasher构建图片相似度检测系统
use image_hasher::{HasherConfig, HashAlg, ImageHash};
use image::io::Reader as ImageReader;
use std::path::{Path, PathBuf};
use std::collections::HashMap;
use rayon::prelude::*;
/// 图像数据库结构体
struct ImageSimilaritySystem {
hasher: image_hasher::Hasher,
image_hashes: HashMap<PathBuf, ImageHash>,
}
impl ImageSimilaritySystem {
/// 创建新的图像数据库
pub fn new(hash_alg: HashAlg, hash_size: u32) -> Self {
let hasher = HasherConfig::new()
.hash_alg(hash_alg)
.hash_size(hash_size)
.to_hasher();
Self {
hasher,
image_hashes: HashMap::new(),
}
}
/// 添加单张图片到数据库
pub fn add_image(&mut self, image_path: &Path) -> anyhow::Result<()> {
let img = ImageReader::open(image_path)?.decode()?;
let hash = self.hasher.hash_image(&img);
self.image_hashes.insert(image_path.to_path_buf(), hash);
Ok(())
}
/// 批量添加图片到数据库(并行处理)
pub fn add_images_batch(&mut self, image_paths: &[PathBuf]) -> anyhow::Result<()> {
let hashes: Vec<(PathBuf, ImageHash)> = image_paths
.par_iter()
.map(|path| {
let img = ImageReader::open(path)?.decode()?;
let hash = self.hasher.hash_image(&img);
Ok((path.to_path_buf(), hash))
})
.collect::<anyhow::Result<Vec<_>>>()?;
for (path, hash) in hashes {
self.image_hashes.insert(path, hash);
}
Ok(())
}
/// 查找与查询图片相似的图片
pub fn find_similar_images(
&self,
query_image: &Path,
similarity_threshold: f32
) -> anyhow::Result<Vec<(PathBuf, f32)>> {
let query_img = ImageReader::open(query_image)?.decode()?;
let query_hash = self.hasher.hash_image(&query_img);
let results = self.image_hashes
.par_iter()
.map(|(path, hash)| {
let dist = hash.dist(&query_hash);
let similarity = 1.0 - (dist as f32 / hash.as_bytes().len() as f32);
(path.clone(), similarity * 100.0)
})
.filter(|(_, similarity)| *similarity >= similarity_threshold)
.collect();
Ok(results)
}
}
fn main() -> anyhow::Result<()> {
// 初始化系统 - 使用双梯度算法,哈希大小16x16
let mut system = ImageSimilaritySystem::new(HashAlg::DoubleGradient, 16);
// 添加图片到数据库
let image_dir = Path::new("images");
let image_paths: Vec<PathBuf> = std::fs::read_dir(image_dir)?
.filter_map(|entry| entry.ok().map(|e| e.path()))
.collect();
system.add_images_batch(&image_paths)?;
println!("Added {} images to database", image_paths.len());
// 查询相似图片
let query_image = Path::new("query.jpg");
let results = system.find_similar_images(query_image, 80.0)?;
println!("Similar images found:");
for (path, similarity) in results {
println!("- {}: {:.2}% similarity", path.display(), similarity);
}
Ok(())
}
这个完整示例展示了如何:
- 创建一个图像相似度检测系统
- 使用并行处理批量添加图片
- 使用不同哈希算法和配置
- 查询相似图片并显示相似度百分比
- 处理可能的错误
您可以根据需要调整哈希算法类型、哈希大小和相似度阈值来优化系统性能。