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

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
相关推荐
这可就有点麻烦了6 分钟前
强化学习笔记之【TD3算法】
linux·笔记·算法·机器学习
苏宸啊11 分钟前
顺序表及其代码实现
数据结构·算法
lin zaixi()15 分钟前
贪心思想之——最大子段和问题
数据结构·算法
FindYou.15 分钟前
C - Separated Lunch
算法·深度优先
夜雨翦春韭21 分钟前
【代码随想录Day30】贪心算法Part04
java·数据结构·算法·leetcode·贪心算法
Kent_J_Truman32 分钟前
【平方差 / C】
算法
一直学习永不止步33 分钟前
LeetCode题练习与总结:H 指数--274
java·数据结构·算法·leetcode·数组·排序·计数排序
Amor风信子1 小时前
华为OD机试真题---跳房子II
java·数据结构·算法
戊子仲秋1 小时前
【LeetCode】每日一题 2024_10_2 准时到达的列车最小时速(二分答案)
算法·leetcode·职场和发展
邓校长的编程课堂1 小时前
助力信息学奥赛-VisuAlgo:提升编程与算法学习的可视化工具
学习·算法