评估数据相似度的几种方法

1、结构化相似性指数 (SSIM)

优点:综合考虑了亮度、对比度和结构(图像中的边缘和纹理等高频信息)等因素。

缺点:不考虑色彩信息

python 复制代码
import cv2

# 函数:计算两张图片的结构化相似性(SSIM)
def calculate_ssim(image1, image2):
    # 读取图片
    img1 = cv2.imread(image1)
    img2 = cv2.imread(image2)

    # 将图片转换为灰度图
    gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

    # 计算SSIM,分数范围通常是 ([-1, 1]),其中 1 表示完全相似,-1 表示完全不同,0 表示没有任何相似性
    (score, _) = cv2.compareSSIM(gray1, gray2, full=True)
    return score

【注】转为灰度的原因是1、不考虑色彩信息;2、加快计算速度。

2、峰值信噪比 (PSNR)

主要用于比较同一图像的不同版本之间的质量,如图像压缩算法评估、图像复原等, 而不是用于比较不同图像之间的质量。

【注意】因为 PSNR 的计算是基于图像的像素值之间的均方误差(MSE)来衡量的,即使两张图像的质量相同,但如果它们的像素值分布不同,PSNR 的值也可能不同,所以PSNR 主要用于比较同一图像的不同版本之间的质量,而不是用于比较不同图像之间的质量。

python 复制代码
import cv2

# 函数:计算两张图片的峰值信噪比(PSNR)
def calculate_psnr(image1, image2):
    # 读取图片
    img1 = cv2.imread(image1)
    img2 = cv2.imread(image2)

    # 计算PSNR,其返回值范围通常是正值。PSNR 的值越高,表示图像质量越好,对于 8 位图像,PSNR 的典型范围在 20 到 50 之间,取决于图像的内容和失真程度。
    psnr = cv2.PSNR(img1, img2)
    return psnr

3、直方图比较

通过比较图像的直方图来评估它们的相似度。适用于颜色分布较为重要的场景,如图像检索、图像分类等。

python 复制代码
import cv2
# 函数:计算两张图片的直方图相似度
def calculate_hist_similarity(image1, image2):
    # 读取图片
    img1 = cv2.imread(image1)
    img2 = cv2.imread(image2)

    # 计算直方图
    hist1 = cv2.calcHist([img1], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])
    hist2 = cv2.calcHist([img2], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])

    # 计算直方图相似度,返回值范围通常在0到1之间,0 表示两个直方图之间完全不相似,1 表示两个直方图之间完全相同。
    similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
    return similarity

4、均值哈希 (Average Hash)

将图像转换为哈希码,并比较哈希码之间的差异来评估图像相似度。适用于快速计算图像相似度的场景,如图像搜索、重复图片检测等。

缺点:

1、均值哈希是基于图像的整体信息,即将图像缩小为一个小尺寸的图像,然后计算其均值作为哈希值。在这个过程中,大量的图像细节信息被丢失,导致哈希值无法捕捉到图像的局部特征和细微变化。因此,对于涉及到局部特征变化的复杂变换,均值哈希往往无法准确地区分不同图像之间的差异

2、均值哈希通常只使用灰度信息来计算哈希值,不会考虑到像素的颜色信息

python 复制代码
import imagehash
from PIL import Image

# 函数:计算两张图片的均值哈希(Average Hash)相似度,介于0到1之间的浮点数,如果返回值接近1,表示两个图像非常相似;如果返回值接近0,表示两个图像差异很大。
def calculate_avg_hash_similarity(image1, image2):
    hash1 = imagehash.average_hash(Image.open(image1))
    hash2 = imagehash.average_hash(Image.open(image2))
    similarity = 1 - (hash1 - hash2) / len(hash1.hash) ** 2
    return similarity

5、感知哈希 (Perceptual Hash)

类似于均值哈希,但在计算哈希码时考虑了图像的感知特征,使得哈希码更加符合人类视觉系统的感知。适用于图像搜索、版权保护等场景。

优点:

1、 感知哈希考虑了图像的颜色信息,但对于颜色的变化并不敏感,因此在一定程度上可以应对色彩变化。

2、感知哈希在计算哈希值时会考虑到图像的局部特征,能够比较好地应对一些常见的图像变换,因此在图像检索、相似度匹配等应用中表现较为稳定。

缺点:

1、感知哈希算法通常涉及到较复杂的图像处理和特征提取过程,因此计算复杂

python 复制代码
import imagehash
from PIL import Image

# 函数:计算两张图片的感知哈希(Perceptual Hash)相似度,介于0到1之间的浮点数,如果返回值接近1,表示两个图像非常相似;如果返回值接近0,表示两个图像差异很大。
def calculate_phash_similarity(image1, image2):
    hash1 = imagehash.phash(Image.open(image1))
    hash2 = imagehash.phash(Image.open(image2))
    similarity = 1 - (hash1 - hash2) / len(hash1.hash) ** 2
    return similarity

6、结构化相似矩阵 (SSD)

比较两个结构化数据(例如文本、图像、音频等)之间相似性的方法

缺点:

1、计算复杂度高: 计算结构化相似度矩阵需要对每对数据进行特征提取和相似度计算,这在数据规模较大时会导致计算复杂度较高。

2、依赖特征提取方法: 结构化相似度矩阵的计算结果很大程度上取决于所选择的特征提取方法。

3、数据结构要求高: SSD通常要求数据具有一定的结构性,比如图像要具有明显的区域、文本要有清晰的语义等。对于一些非结构化数据或者噪声较多的数据,SSD可能无法有效地计算相似度。

4、难以处理高维数据: 高维数据(如高分辨率图像、大规模文本数据)的相似度计算通常会面临维度灾难问题,SSD在处理这些数据时可能会受到限制。

python 复制代码
import cv2
import numpy as np

# 函数:计算两张图片的结构化相似度矩阵(SSD)
def calculate_ssd(image1, image2):
    # 读取图片
    img1 = cv2.imread(image1, cv2.IMREAD_GRAYSCALE)
    img2 = cv2.imread(image2, cv2.IMREAD_GRAYSCALE)

    # 计算SSD,返回值范围是非负实数,表示两幅图像之间的差异程度。越大,表示两幅图像之间的差异越大,反之则表示两幅图像之间的相似度越高。
    ssd = np.sum((img1 - img2) ** 2)
    return ssd

结合使用

在实际使用时,可以将多个维度的指标结合起来

如,将直方图和SSMI结合:

直方图捕获图像的颜色分布信息,而 SSMI 则可以考虑图像的结构信息。

python 复制代码
import cv2
import numpy as np
from skimage.metrics import structural_similarity as ssim

def calculate_image_similarity(image1, image2):
    # 读取彩色图像
    img1 = cv2.imread(image1)
    img2 = cv2.imread(image2)

    # 转换为 HSV 颜色空间
    hsv1 = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV)
    hsv2 = cv2.cvtColor(img2, cv2.COLOR_BGR2HSV)

    # 计算彩色直方图
    hist1 = cv2.calcHist([hsv1], [0, 1], None, [180, 256], [0, 180, 0, 256])
    hist2 = cv2.calcHist([hsv2], [0, 1], None, [180, 256], [0, 180, 0, 256])

    # 归一化直方图
    hist1 /= hist1.sum()
    hist2 /= hist2.sum()

    # 计算直方图相似度
    hist_similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)

    # 转换为灰度图像
    img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

    # 计算结构相似度
    ssmi, _ = ssim(img1_gray, img2_gray, full=True)

    # 组合得分,组合的方式可以自行定义
    final_score = 0.5 * hist_similarity + 0.5 * ssmi

    return final_score
相关推荐
火星机器人life2 小时前
基于ceres优化的3d激光雷达开源算法
算法·3d
虽千万人 吾往矣2 小时前
golang LeetCode 热题 100(动态规划)-更新中
算法·leetcode·动态规划
arnold663 小时前
华为OD E卷(100分)34-转盘寿司
算法·华为od
ZZTC3 小时前
Floyd算法及其扩展应用
算法
lshzdq3 小时前
【机器人】机械臂轨迹和转矩控制对比
人工智能·算法·机器人
2401_858286114 小时前
115.【C语言】数据结构之排序(希尔排序)
c语言·开发语言·数据结构·算法·排序算法
猫猫的小茶馆4 小时前
【数据结构】数据结构整体大纲
linux·数据结构·算法·ubuntu·嵌入式软件
u0107735144 小时前
【字符串】-Lc5-最长回文子串(中心扩展法)
java·算法
帅逼码农5 小时前
K-均值聚类算法
算法·均值算法·聚类
姚先生975 小时前
LeetCode 209. 长度最小的子数组 (C++实现)
c++·算法·leetcode