• 简单的图像相似度计算方法


    塑料瓶图像检测

    目的:用于判断一张图片是否为塑料瓶;

    条件:总计300多张图片分为70多类,同一类塑料瓶分别放置在同一个文件夹;

    思路:选取每个文件夹的一张图片与目标图片对比计算返回相似度最高的值,通过多次试验确定阈值,超过阈值则判定为是塑料瓶,否则不是;

    目录:

    @

    说明

    • 所有测试结果均为程序第一次运行结果

    • 每一组测试的第一个(第一个样本)都是同一张图片相互比对

    • 每一组测试的第二三四五个测试样本均是与第一个测试样本比对

    • 以下为选用的5个测试样本

    • 图片放置在与程序同一位置的images文件夹

    1.方法

    • 直方图

    • 互信息

    • 余弦相似度

    • 感知哈希算法

    2.测试结果(单张图片比对)

    直方图

    from time import *
    begin_time = time()
    
    from PIL import Image
    
    
    def make_regalur_image(img, size=(256, 256)):
        return img.resize(size).convert('RGB')
    
    
    def hist_similar(lh, rh):
        assert len(lh) == len(rh)
        return sum(1 - (0 if l == r else float(abs(l - r)) / max(l, r)) for l, r in zip(lh, rh)) / len(lh)
    
    
    def calc_similar(li, ri):
        return hist_similar(li.histogram(), ri.histogram())
    
    
    if __name__ == '__main__':
        img1 = Image.open('images/WIN_20200111_21_56_10_Pro.jpg')
        img1 = make_regalur_image(img1)
        img2 = Image.open('images/WIN_20200111_21_56_52_Pro.jpg')
        img2 = make_regalur_image(img2)
        print(calc_similar(img1, img2))
    
    end_time = time()
    run_time = end_time-begin_time
    print ('该程序运行时间:',run_time)
    
    测试方式 (图像)文件名 耗时(s) Result
    素材(自比) WIN_20200111_21_56_10_Pro.jpg 0.055361032485961914 1.0
    两张图片比对 WIN_20200111_21_56_52_Pro.jpg 0.06594681739807129 0.6108132256943336
    两张图片比对 WIN_20200111_21_57_05_Pro.jpg 0.05501222610473633 0.6398035067201021
    两张图片比对 WIN_20200111_21_58_01_Pro.jpg 0.05424642562866211 0.7139745065909696
    两张图片比对 WIN_20200111_22_02_08_Pro.jpg 0.07813024520874023 0.7189068678053613

    互信息

    from time import *
    begin_time = time()
    
    from sklearn import metrics as mr
    from scipy.misc import imread
    import numpy as np
     
    img1 = imread('1.jpg')
    img2 = imread('2.jpg')
     
    img2 = np.resize(img2, (img1.shape[0], img1.shape[1], img1.shape[2]))
     
    img1 = np.reshape(img1, -1)
    img2 = np.reshape(img2, -1)
    print(img2.shape)
    print(img1.shape)
    mutual_infor = mr.mutual_info_score(img1, img2)
     
    print(mutual_infor)
    
    end_time = time()
    run_time = end_time-begin_time
    print ('该程序运行时间:',run_time)
    
    测试方式 (图像)文件名 耗时(s) Result
    素材(自比) WIN_20200111_21_56_10_Pro.jpg 1.459466791152954 (6220800,)
    (6220800,)
    4.842347326725792
    两张图片比对 WIN_20200111_21_56_52_Pro.jpg 1.531355381011963 (6220800,)
    (6220800,)
    1.3835594221461103
    两张图片比对 WIN_20200111_21_57_05_Pro.jpg 1.5626063346862793 (6220800,)
    (6220800,)
    1.2697158354875515
    两张图片比对 WIN_20200111_21_58_01_Pro.jpg 1.5668601989746094 (6220800,)
    (6220800,)
    1.40573402284614
    两张图片比对 WIN_20200111_22_02_08_Pro.jpg 1.5644567012786865 (6220800,)
    (6220800,)
    0.6813656974353114

    余弦相似度

    from time import *
    begin_time = time()
    
    from PIL import Image
    from numpy import average, linalg, dot
    
    def get_thumbnail(image, size=(1200, 750), greyscale=False):
        image = image.resize(size, Image.ANTIALIAS)
        if greyscale:
            image = image.convert('L')
        return image
    
    
    def image_similarity_vectors_via_numpy(image1, image2):
        image1 = get_thumbnail(image1)
        image2 = get_thumbnail(image2)
        images = [image1, image2]
        vectors = []
        norms = []
        for image in images:
            vector = []
            for pixel_tuple in image.getdata():
                vector.append(average(pixel_tuple))
            vectors.append(vector)
            norms.append(linalg.norm(vector, 2))
        a, b = vectors
        a_norm, b_norm = norms
        res = dot(a / a_norm, b / b_norm)
        return res
    
    
    image1 = Image.open('images/WIN_20200111_21_56_10_Pro.jpg')
    image2 = Image.open('images/WIN_20200111_21_56_10_Pro.jpg')
    cosin = image_similarity_vectors_via_numpy(image1, image2)
    
    print(cosin)
    
    end_time = time()
    run_time = end_time-begin_time
    print ('该程序运行时间:',run_time)
    
    测试方式 (图像)文件名 耗时(s) Result
    素材(自比) WIN_20200111_21_56_10_Pro.jpg 19.579540729522705 0.9999999999999746
    两张图片比对 WIN_20200111_21_56_52_Pro.jpg 19.23276400566101 0.9751567803348392
    两张图片比对 WIN_20200111_21_57_05_Pro.jpg 19.25089430809021 0.9726385998457207
    两张图片比对 WIN_20200111_21_58_01_Pro.jpg 0.9807553738212222 19.210497856140137
    两张图片比对 WIN_20200111_22_02_08_Pro.jpg 0.9038901804349453 19.01563835144043

    感知哈希算法

    from time import *
    begin_time = time()
    
    import cv2
    import numpy as np
    import os
    
    #感知哈希算法
    def pHash(image):
        image = cv2.resize(image,(32,32), interpolation=cv2.INTER_CUBIC)
        image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    #     cv2.imshow('image', image)
    #     cv2.waitKey(0)
    #     cv2.destroyAllWindows()
        # 将灰度图转为浮点型,再进行dct变换
        dct = cv2.dct(np.float32(image))
    #     print(dct)
        # 取左上角的8*8,这些代表图片的最低频率
        # 这个操作等价于c++中利用opencv实现的掩码操作
        # 在python中进行掩码操作,可以直接这样取出图像矩阵的某一部分
        dct_roi = dct[0:8,0:8]
        avreage = np.mean(dct_roi)
        hash = []
        for i in range(dct_roi.shape[0]):
            for j in range(dct_roi.shape[1]):
                if dct_roi[i,j] > avreage:
                    hash.append(1)
                else:
                    hash.append(0)
        return hash
    
    #计算汉明距离
    def Hamming_distance(hash1,hash2):
        num = 0
        for index in range(len(hash1)):
            if hash1[index] != hash2[index]:
                num += 1
        return num
    
    if __name__ == "__main__":
    
        image_file1 = 'images/WIN_20200111_21_56_10_Pro.jpg'
        image_file2 = 'images/1.jpg'
    
        img1 = cv2.imread(image_file1)
        img2 = cv2.imread(image_file2)
        hash1 = pHash(img1)
        hash2 = pHash(img2)
        dist = Hamming_distance(hash1, hash2)
        #将距离转化为相似度
        similarity = 1 - dist * 1.0 / 64
        print(dist)
        print(similarity)
    
    end_time = time()
    
    run_time = end_time-begin_time
    print ('该程序运行时间:',run_time)
    
    
    测试方式 (图像)文件名 耗时(s) distance similarity
    素材(自比) WIN_20200111_21_56_10_Pro.jpg 0.20314764976501465 0 1.0
    两张图片比对 WIN_20200111_21_56_52_Pro.jpg 0.2085726261138916 4 0.9375
    两张图片比对 WIN_20200111_21_57_05_Pro.jpg 0.20518183708190918 0 1.0
    两张图片比对 WIN_20200111_21_58_01_Pro.jpg 0.20314764976501465 5 0.921875
    两张图片比对 WIN_20200111_22_02_08_Pro.jpg 0.18751096725463867 8 0.875

    3.评价

    • 直方图计算结果与直观视觉严重不符合
    • 余弦相似度准确度较高,但太耗时,比对平均耗时19s
    • 互信息的方法从耗时和准确度上粗略观察,介于直方图和余弦相似度之间
    • 感知哈希算法耗时较为可接受,且比对结果较有区分度且符合直观视觉
  • 相关阅读:
    简单优化:Zipalign
    Using lists in Android (ListView)
    6410移植RT3070无线模块,WPA加密方式,并开机自动加载
    html表格的动态增加删除
    html 中表格长度固定
    跨域 Iframe 通信解决方案(兼容 IE 系列浏览器。)
    Sass 基础和入门
    javascript 模块化编程 1
    Canvas的方法覆盖和实现新的API
    获取鼠标点击相对于Canva位置的2种方法
  • 原文地址:https://www.cnblogs.com/MemoryDrive/p/13301645.html
Copyright © 2020-2023  润新知