美文网首页
图像相似度计算【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