簡(jiǎn)單的圖像相似度計(jì)算方法

[toc]

塑料瓶圖像檢測(cè)

目的:用于判斷一張圖片是否為塑料瓶;

條件:總計(jì)300多張圖片分為70多類,同一類塑料瓶分別放置在同一個(gè)文件夾;

思路:選取每個(gè)文件夾的一張圖片與目標(biāo)圖片對(duì)比計(jì)算返回相似度最高的值,通過多次試驗(yàn)確定閾值,超過閾值則判定為是塑料瓶,否則不是;

目錄:

@[toc]

說明

  • 所有測(cè)試結(jié)果均為程序第一次運(yùn)行結(jié)果

  • 每一組測(cè)試的第一個(gè)(第一個(gè)樣本)都是同一張圖片相互比對(duì)

  • 每一組測(cè)試的第二三四五個(gè)測(cè)試樣本均是與第一個(gè)測(cè)試樣本比對(duì)

  • 以下為選用的5個(gè)測(cè)試樣本

  • 圖片放置在與程序同一位置的images文件夾

<center><img src="https://auto2dev.coding.net/p/ImageHostingService/d/ImageHostingService/git/raw/master/md/20200114104340189-1592736787820.jpg" width="40%"/></center>
<center><img src="https://auto2dev.coding.net/p/ImageHostingService/d/ImageHostingService/git/raw/master/md/20200114104446378-1592736787433.jpg" width="40%"/></center>

<center><img src="https://auto2dev.coding.net/p/ImageHostingService/d/ImageHostingService/git/raw/master/md/202001141044484-1592736787888.jpg" width="40%"/></center>

<center><img src="https://auto2dev.coding.net/p/ImageHostingService/d/ImageHostingService/git/raw/master/md/20200114104502540-1592736787890.jpg" width="40%"/></center>

<center><img src="https://auto2dev.coding.net/p/ImageHostingService/d/ImageHostingService/git/raw/master/md/20200114104509945-1592736787431.jpg" width="40%"/></center>

1.方法

  • 直方圖

  • 互信息

  • 余弦相似度

  • 感知哈希算法

2.測(cè)試結(jié)果(單張圖片比對(duì))

直方圖

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 ('該程序運(yùn)行時(shí)間:',run_time)
測(cè)試方式 (圖像)文件名 耗時(shí)(s) Result
素材(自比) WIN_20200111_21_56_10_Pro.jpg 0.055361032485961914 1.0
兩張圖片比對(duì) WIN_20200111_21_56_52_Pro.jpg 0.06594681739807129 0.6108132256943336
兩張圖片比對(duì) WIN_20200111_21_57_05_Pro.jpg 0.05501222610473633 0.6398035067201021
兩張圖片比對(duì) WIN_20200111_21_58_01_Pro.jpg 0.05424642562866211 0.7139745065909696
兩張圖片比對(duì) 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 ('該程序運(yùn)行時(shí)間:',run_time)
測(cè)試方式 (圖像)文件名 耗時(shí)(s) Result
素材(自比) WIN_20200111_21_56_10_Pro.jpg 1.459466791152954 (6220800,)
(6220800,)
4.842347326725792
兩張圖片比對(duì) WIN_20200111_21_56_52_Pro.jpg 1.531355381011963 (6220800,)
(6220800,)
1.3835594221461103
兩張圖片比對(duì) WIN_20200111_21_57_05_Pro.jpg 1.5626063346862793 (6220800,)
(6220800,)
1.2697158354875515
兩張圖片比對(duì) WIN_20200111_21_58_01_Pro.jpg 1.5668601989746094 (6220800,)
(6220800,)
1.40573402284614
兩張圖片比對(duì) 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 ('該程序運(yùn)行時(shí)間:',run_time)
測(cè)試方式 (圖像)文件名 耗時(shí)(s) Result
素材(自比) WIN_20200111_21_56_10_Pro.jpg 19.579540729522705 0.9999999999999746
兩張圖片比對(duì) WIN_20200111_21_56_52_Pro.jpg 19.23276400566101 0.9751567803348392
兩張圖片比對(duì) WIN_20200111_21_57_05_Pro.jpg 19.25089430809021 0.9726385998457207
兩張圖片比對(duì) WIN_20200111_21_58_01_Pro.jpg 0.9807553738212222 19.210497856140137
兩張圖片比對(duì) 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()
    # 將灰度圖轉(zhuǎn)為浮點(diǎn)型,再進(jìn)行dct變換
    dct = cv2.dct(np.float32(image))
#     print(dct)
    # 取左上角的8*8,這些代表圖片的最低頻率
    # 這個(gè)操作等價(jià)于c++中利用opencv實(shí)現(xiàn)的掩碼操作
    # 在python中進(jìn)行掩碼操作,可以直接這樣取出圖像矩陣的某一部分
    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

#計(jì)算漢明距離
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)
    #將距離轉(zhuǎn)化為相似度
    similarity = 1 - dist * 1.0 / 64
    print(dist)
    print(similarity)

end_time = time()

run_time = end_time-begin_time
print ('該程序運(yùn)行時(shí)間:',run_time)

測(cè)試方式 (圖像)文件名 耗時(shí)(s) distance similarity
素材(自比) WIN_20200111_21_56_10_Pro.jpg 0.20314764976501465 0 1.0
兩張圖片比對(duì) WIN_20200111_21_56_52_Pro.jpg 0.2085726261138916 4 0.9375
兩張圖片比對(duì) WIN_20200111_21_57_05_Pro.jpg 0.20518183708190918 0 1.0
兩張圖片比對(duì) WIN_20200111_21_58_01_Pro.jpg 0.20314764976501465 5 0.921875
兩張圖片比對(duì) WIN_20200111_22_02_08_Pro.jpg 0.18751096725463867 8 0.875

3.評(píng)價(jià)

  • 直方圖計(jì)算結(jié)果與直觀視覺嚴(yán)重不符合
  • 余弦相似度準(zhǔn)確度較高,但太耗時(shí),比對(duì)平均耗時(shí)19s
  • 互信息的方法從耗時(shí)和準(zhǔn)確度上粗略觀察,介于直方圖和余弦相似度之間
  • 感知哈希算法耗時(shí)較為可接受,且比對(duì)結(jié)果較有區(qū)分度且符合直觀視覺
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容