美文网首页
图像相似度计算【python】

图像相似度计算【python】

作者: 小小杨树 | 来源:发表于2021-09-26 17:56 被阅读0次

一.利用直方图距离计算图片相似度

计算公式:

image

其中,G和S为两张图片的图像颜色分布直方图,N为颜色空间样点数。这里使用分块的方法计算相似度,用以提高各部分的特征,防止图片颜色相似导致计算的相似度高。

import matplotlib.pyplot as plt

# 正则化图像
def regularizeImage(img, size = (256, 256)):
    return img.resize(size).convert('RGB')

# 画出直方图图像
def drawHistogram(hg1, hg2):
    plt.plot(range(len(hg1)), hg1, color='blue', linewidth=1.5, label='img1')
    plt.plot(range(len(hg2)), hg2, color='red', linewidth=1.5, label='img2')
    plt.legend(loc='upper left')
    plt.title('Histogram Similarity')
    plt.show()

# 分块图像4x4
def splitImage(img, part_size = (64, 64)):
    w, h = img.size
    pw, ph = part_size
    data = []
    for i in range(0, w, pw):
        for j in range(0, h, ph):
            data.append(img.crop((i, j, i + pw, j + ph)).copy())
    return data

# 利用单块图片的直方图距离计算相似度
def calSingleHistogramSimilarity(hg1, hg2):
    if len(hg1) != len(hg2):
        raise Exception('样本点个数不一样')
    sum = 0
    for x1, x2 in zip(hg1, hg2):
        if x1 != x2:
            sum += 1 - float(abs(x1 - x2) / max(x1, x2))
        else:
            sum += 1
    return sum / len(hg1)

# 利用分块图片的直方图距离计算相似度
def calMultipleHistogramSimilarity(img1, img2):
    answer = 0
    for sub_img1, sub_img2 in zip(splitImage(img1), splitImage(img2)):
        answer += calSingleHistogramSimilarity(sub_img1.histogram(), sub_img2.histogram())
    return float(answer / 16.0)

—————————————————————————————————————————————————————————————————

二.利用平均哈希算法计算图片相似度

计算步骤:

1.缩放图片:一般大小为8*8,64个像素值
2.简化色彩,转化为灰度图:可以使用Image的convert('L')方法
3.计算平均值:计算出灰度图所有像素点的像素值的平均值
4.比较像素灰度值:遍历灰度图的每一个像素值与上一步计算的平均值,大于平均值记录为1,否则为0
5.得到64位图像指纹
6.记录两张图片的图像指纹的汉明距离,计算图片相似度
# 正则化图像
def regularizeImage(img, size = (8, 8)):
    return img.resize(size).convert('L')

# 计算hash值
def getHashCode(img, size = (8, 8)):

    pixel = []
    for i in range(size[0]):
        for j in range(size[1]):
            pixel.append(img.getpixel((i, j)))

    mean = sum(pixel) / len(pixel)

    result = []
    for i in pixel:
        if i > mean:
            result.append(1)
        else:
            result.append(0)
    
    return result

# 比较hash值
def compHashCode(hc1, hc2):
    cnt = 0
    for i, j in zip(hc1, hc2):
        if i == j:
            cnt += 1
    return cnt

# 计算平均哈希算法相似度
def calaHashSimilarity(img1, img2):
    img1 = regularizeImage(img1)
    img2 = regularizeImage(img2)
    hc1 = getHashCode(img1)
    hc2 = getHashCode(img2)
    return compHashCode(hc1, hc2)

__all__ = ['calaHashSimilarity']

—————————————————————————————————————————————————————————————————

三.利用感知哈希算法计算图片相似度

计算步骤:

3.1 缩放图片:一般大小为32*32,这样方便DCT计算
3.2 简化色彩,转化为灰度图:可以使用Image的convert('L')方法
3.3 计算DCT【离散余弦变换】
3.3.1 获得图像的二维数据矩阵f(x,y)
3.3.2 求离散余弦变换的系数矩阵[A]
3.3.3 求系数矩阵对应的转置矩阵[A]T
3.3.4 根据公式[F(u,v)]=[A][f(x,y)][A]T 计算离散余弦变换
3.4 缩小DCT:DCT计算后的矩阵是3232,保留左上角的88,这些代表的图片的最低频率
3.5 计算平均值:计算缩小DCT后的所有像素点的平均
3.6 进一步减小DCT:大于平均值记录为1,否则为0
3.7 得到64位信息指纹
3.8 记录两张图片的图像指纹的汉明距离,计算图片相似度
import math
import unittest

# 正则化图像
def regularizeImage(img, size = (32, 32)):
    return img.resize(size).convert('L')

# 获得图像像素矩阵
def getMatrix(img):
    matrix = []
    size = img.size
    for i in range(size[1]):
        pixel = []
        for j in range(size[0]):
            pixel.append(img.getpixel((j, i)))
        matrix.append(pixel)
    return matrix

# 计算系数矩阵
def getCoefficient(length):
    matrix = []
    sqr = 1.0 / math.sqrt(length)
    value = []
    for i in range(length):
        value.append(sqr)
    matrix.append(value)
    for i in range(1, length):
        value = []
        for j in range(0, length):
            value.append(math.sqrt(2.0 / length) * math.cos(i * math.pi * (j + 0.5) / length))
        matrix.append(value)
    return matrix

# 计算矩阵转秩
def getTranspose(matrix):
    new_matrix = []
    for i in range(len(matrix)):
        value = []
        for j in range(len(matrix[i])):
            value.append(matrix[j][i])
        new_matrix.append(value)
    return new_matrix

# 计算矩阵乘法
def getMultiply(matrix1, matrix2):
    new_matrix = []
    for i in range(len(matrix1)):
        value = []
        for j in range(len(matrix2[i])): 
            ans = 0.0
            for h in range(len(matrix1[i])):
                ans += matrix1[i][h] * matrix2[h][j]
            value.append(ans)
        new_matrix.append(value)
    return new_matrix

# 计算DCT
def DCT(matrix):
    length = len(matrix)
    A = getCoefficient(length)
    AT = getTranspose(A)
    temp = getMultiply(A, matrix)
    DCT_matrix = getMultiply(matrix, AT)
    return DCT_matrix

# 计算左上角8*8并转化为list
def submatrix_list(matrix, size = (8, 8)):
    value = []
    for i in range(size[0]):
        for j in range(size[1]):
            value.append(matrix[i][j])
    return value

# 计算hash值
def getHashCode(sub_list):
    length = len(sub_list)
    mean = sum(sub_list) / length
    
    result = []
    for i in sub_list:
        if i > mean:
            result.append(1)
        else:
            result.append(0)

    return result

# 比较hash值
def compHashCode(hc1, hc2):
    cnt = 0
    for i, j in zip(hc1, hc2):
        if i == j:
            cnt += 1
    return cnt

# 计算感知哈希算法相似度
def calpHashSimilarity(img1, img2):
    img1 = regularizeImage(img1)
    img2 = regularizeImage(img2)

    matrix1 = getMatrix(img1)
    matrix2 = getMatrix(img2)

    DCT1 = DCT(matrix1)
    DCT2 = DCT(matrix2)
    
    sub_list1 = submatrix_list(DCT1)
    sub_list2 = submatrix_list(DCT2)

    hc1 = getHashCode(sub_list1)
    hc2 = getHashCode(sub_list2)
    return compHashCode(hc1, hc2)

# 单元测试
class TestpHash(unittest.TestCase):
    def test_getHashCode(self):
        self.assertEqual(getHashCode([1, 2, 3]), [0, 0, 1])

if __name__ == '__main__':
    unittest.main()

__all__ = ['calpHashSimilarity']

—————————————————————————————————————————————————————————————————

四.利用差异哈希算法计算图片相似度

计算步骤:

4.1 缩放图片:一般大小为9*8,以留下多一行的像素数据进行差异计算
4.2 简化色彩,转化为灰度图:可以使用Image的convert('L')方法
4.3 计算差异值:dHash算法工作在相邻像素之间,这样每行9个像素之间产生了8个不同的差异,一共8行,则产生了64个差异哈希值
4.4 得到64位信息指纹:如果左边的像素比右边的更亮,则记录为1,否则为0
4.5 记录两张图片的图像指纹的汉明距离,计算图片相似度
# 正则化图像
def regularizeImage(img, size = (9, 8)):
    return img.resize(size).convert('L')

# 计算hash值
def getHashCode(img, size = (9, 8)):

    result = []
    for i in range(size[0] - 1):
        for j in range(size[1]):
            current_val = img.getpixel((i, j))
            next_val = img.getpixel((i + 1, j))
            if current_val > next_val:
                result.append(1)
            else:
                result.append(0)
    
    return result

# 比较hash值
def compHashCode(hc1, hc2):
    cnt = 0
    for i, j in zip(hc1, hc2):
        if i == j:
            cnt += 1
    return cnt

# 计算差异哈希算法相似度
def caldHashSimilarity(img1, img2):
    img1 = regularizeImage(img1)
    img2 = regularizeImage(img2)
    hc1 = getHashCode(img1)
    hc2 = getHashCode(img2)
    return compHashCode(hc1, hc2)

__all__ = ['caldHashSimilarity']

转自另一位大佬,忘记地址了

相关文章

网友评论

      本文标题:图像相似度计算【python】

      本文链接:https://www.haomeiwen.com/subject/ptxmiltx.html