图片相似度检测技术综述 
1. 图片相似度检测方法概述 
图片相似度检测是计算机视觉中的重要任务,广泛应用于图片去重、版权检测、以图搜图等场景。本文介绍几种常见的图片相似度检测方法。
2. 图片哈希算法 
图片哈希算法通过计算图片的哈希值来判断相似度,具有计算速度快、占用空间小的优点。
2.1 均值哈希算法(Average Hash, aHash) 
原理:
均值哈希算法利用图片的低频信息来生成哈希值。具体步骤:
- 缩小尺寸:将图片缩小至 8×8 像素,共 64 个像素点 - 去除图片细节,只保留结构、明暗等基本信息
- 消除不同尺寸、比例带来的差异
 
- 转换灰度:将缩小后的图片转为 64 级灰度图 
- 计算均值:计算所有 64 个像素的灰度平均值 
- 比较像素:将每个像素的灰度与平均值比较 - 大于或等于平均值,记为 1
- 小于平均值,记为 0
 
- 生成指纹:将比较结果组合成 64 位整数,即为图片指纹 
特点:
- ✅ 计算简单快速
- ✅ 对缩放、旋转有一定鲁棒性
- ❌ 对亮度变化敏感
2.2 感知哈希算法(Perceptual Hash, pHash) 
原理:
- Block Hash(块哈希):将图片分块后分别计算哈希
- Median Hash(中值哈希):使用中值代替均值
- Wavelet Hash(小波哈希):基于小波变换的哈希算法
2.5 实现示例 
使用 Python 的 imagehash 库:
python
from PIL import Image
import imagehash
# 读取图片
img1 = Image.open('image1.jpg')
img2 = Image.open('image2.jpg')
# 计算不同类型的哈希
ahash1 = imagehash.average_hash(img1)
ahash2 = imagehash.average_hash(img2)
phash1 = imagehash.phash(img1)
phash2 = imagehash.phash(img2)
dhash1 = imagehash.dhash(img1)
dhash2 = imagehash.dhash(img2)
# 计算汉明距离(值越小越相似)
print(f"Average Hash 距离: {ahash1 - ahash2}")
print(f"Perceptual Hash 距离: {phash1 - phash2}")
print(f"Difference Hash 距离: {dhash1 - dhash2}")3. 直方图方法 
3.1 单通道直方图 
计算灰度图像的像素分布直方图,通过比较两个直方图的相似度来判断图片相似度。
python
import cv2
import numpy as np
def compare_histogram(img1_path, img2_path):
    # 读取图片并转换为灰度
    img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
    img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)
    
    # 计算直方图
    hist1 = cv2.calcHist([img1], [0], None, [256], [0, 256])
    hist2 = cv2.calcHist([img2], [0], None, [256], [0, 256])
    
    # 归一化
    hist1 = cv2.normalize(hist1, hist1).flatten()
    hist2 = cv2.normalize(hist2, hist2).flatten()
    
    # 计算相似度(相关系数)
    similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
    return similarity3.2 三通道直方图 
分别计算 RGB 三个通道的直方图,综合比较:
python
def compare_color_histogram(img1_path, img2_path):
    img1 = cv2.imread(img1_path)
    img2 = cv2.imread(img2_path)
    
    # 分别计算三个通道
    similarity_total = 0
    for i in range(3):
        hist1 = cv2.calcHist([img1], [i], None, [256], [0, 256])
        hist2 = cv2.calcHist([img2], [i], None, [256], [0, 256])
        
        hist1 = cv2.normalize(hist1, hist1).flatten()
        hist2 = cv2.normalize(hist2, hist2).flatten()
        
        similarity_total += cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
    
    return similarity_total / 34. 特征提取方法 
4.1 SIFT 特征 
SIFT(Scale-Invariant Feature Transform,尺度不变特征变换)是经典的特征提取算法:
python
import cv2
def sift_similarity(img1_path, img2_path):
    img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
    img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)
    
    # 创建 SIFT 检测器
    sift = cv2.SIFT_create()
    
    # 检测关键点和描述符
    kp1, des1 = sift.detectAndCompute(img1, None)
    kp2, des2 = sift.detectAndCompute(img2, None)
    
    # 使用 FLANN 匹配器
    FLANN_INDEX_KDTREE = 1
    index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
    search_params = dict(checks=50)
    flann = cv2.FlannBasedMatcher(index_params, search_params)
    
    matches = flann.knnMatch(des1, des2, k=2)
    
    # 应用比率测试
    good_matches = []
    for m, n in matches:
        if m.distance < 0.7 * n.distance:
            good_matches.append(m)
    
    return len(good_matches) / max(len(kp1), len(kp2))5. 深度学习嵌入方法 
5.1 使用 CLIP 模型 
CLIP(Contrastive Language-Image Pre-Training)是 OpenAI 开发的多模态模型:
python
from PIL import Image
import torch
from transformers import CLIPProcessor, CLIPModel
# 加载模型
model = CLIPModel.from_pretrained("openai/clip-vit-large-patch14")
processor = CLIPProcessor.from_pretrained("openai/clip-vit-large-patch14")
def get_image_embedding(image_path):
    image = Image.open(image_path)
    inputs = processor(images=image, return_tensors="pt")
    with torch.no_grad():
        image_features = model.get_image_features(**inputs)
    return image_features
def cosine_similarity(emb1, emb2):
    return torch.nn.functional.cosine_similarity(emb1, emb2).item()
# 使用示例
emb1 = get_image_embedding('image1.jpg')
emb2 = get_image_embedding('image2.jpg')
similarity = cosine_similarity(emb1, emb2)5.2 常用骨干网络 
不同的骨干网络适用于不同场景:
| 模型 | 特点 | 适用场景 | 
|---|---|---|
| 简单 CNN | 轻量快速 | 基础嵌入 | 
| MobileNetV3 | 移动端优化 | 移动应用 | 
| VGG16 | 经典骨干网络 | 通用场景 | 
| ResNet | 残差网络,深层训练稳定 | 高精度要求 | 
| ViT | Transformer 架构 | 大规模数据 | 
| CLIP | 多模态预训练 | 通用图像理解 | 
| SWAV | 无监督对比聚类 | 无标注数据 | 
| EfficientNet | 效率优化 | 平衡性能和速度 | 
5.3 第三方库推荐 
imagededup:
功能丰富的图片去重库,支持多种算法:
bash
pip install imagededuppython
from imagededup.methods import PHash
phasher = PHash()
encodings = phasher.encode_images(image_dir='path/to/images')
duplicates = phasher.find_duplicates(encoding_map=encodings)官方文档:https://idealo.github.io/imagededup/
imgbeddings:
基于深度学习的图片嵌入库:
bash
pip install imgbeddingspython
from imgbeddings import imgbeddings
from PIL import Image
ibed = imgbeddings()
img = Image.open('image.jpg')
embedding = ibed.to_embeddings(img)GitHub:https://github.com/minimaxir/imgbeddings
6. 方法对比与选择 
6.1 性能对比 
| 方法 | 速度 | 精度 | 内存占用 | 适用场景 | 
|---|---|---|---|---|
| 哈希算法 | 极快 | 中等 | 极小 | 大规模去重、快速筛选 | 
| 直方图 | 快 | 低 | 小 | 颜色相似度比较 | 
| SIFT/SURF | 中 | 高 | 中 | 局部特征匹配、物体识别 | 
| 深度学习嵌入 | 慢 | 极高 | 大 | 高精度要求、语义相似度 | 
6.2 选择建议 
- 大规模图片去重:优先使用哈希算法(pHash 推荐)
- 高精度相似度:使用深度学习方法(CLIP、ViT)
- 实时应用:使用轻量级哈希或 MobileNet
- 离线批处理:可以使用更复杂的深度学习模型
- 移动端应用:使用 MobileNet 或哈希算法
7. 参考资料 
- https://testerhome.com/articles/26924 - 相似图像的检测方法
- https://content-blockchain.org/research/testing-different-image-hash-functions/ - 图片哈希函数测试对比
- https://github.com/JohannesBuchner/imagehash - Python 图片哈希库
- https://huggingface.co/blog/zh/image-similarity - 基于 Hugging Face 的图像相似性搜索
- https://blog.csdn.net/imwaters/article/details/117426488 - 基于 PyTorch 的图片搜索
- https://arxiv.org/abs/1905.02244 - MobileNetV3 论文
- https://arxiv.org/abs/2006.09882 - SWAV 论文
- https://github.com/facebookresearch/swav - SWAV 代码实现