1. 程式人生 > >Python計算圖片之間的相似度

Python計算圖片之間的相似度

1.cosin相似度(餘弦相似度)

把圖片表示成一個向量,通過計算向量之間的餘弦距離來表徵兩張圖片的相似度

 
 
# -*- coding: utf-8 -*-
# !/usr/bin/env python
# @Time    : 2018/11/17 14:52
# @Author  : xhh
# @Desc    : 餘弦相似度計算
# @File    : difference_image_consin.py
# @Software: PyCharm
from PIL import Image
from numpy import average, dot, linalg

# 對圖片進行統一化處理
def get_thum(image, size=(64,64), greyscale=False):
    # 利用image對影象大小重新設定, Image.ANTIALIAS為高質量的
    image = image.resize(size, Image.ANTIALIAS)
    if greyscale:
        # 將圖片轉換為L模式,其為灰度圖,其每個畫素用8個bit表示
        image = image.convert('L')
    return image

# 計算圖片的餘弦距離
def image_similarity_vectors_via_numpy(image1, image2):
    image1 = get_thum(image1)
    image2 = get_thum(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)
        # linalg=linear(線性)+algebra(代數),norm則表示範數
        # 求圖片的範數??
        norms.append(linalg.norm(vector, 2))
    a, b = vectors
    a_norm, b_norm = norms
    # dot返回的是點積,對二維陣列(矩陣)進行計算
    res = dot(a / a_norm, b / b_norm)
    return res


image1 = Image.open('../dataset/100002.png')
image2 = Image.open('../dataset/100001.png')
cosin = image_similarity_vectors_via_numpy(image1, image2)
print('圖片餘弦相似度',cosin)

執行結果:

該方法運算量較大,速度明顯比ssim方法慢,但如果不計較快慢的話感受結果比ssim靠譜

 

2.利用SSIM(結構相似度度量)計算圖片的相似度

是一種全參考的影象質量評價指標,分別從亮度、對比度、結構三個方面度量影象相似性。

SSIM取值範圍[0, 1],值越大,表示影象失真越小。

在實際應用中,可以利用滑動窗將影象分塊,令分塊總數為N,考慮到視窗形狀對分塊的影響,採用高斯加權計算每一視窗的均值、方差以及協方差,然後計算對應塊的結構相似度SSIM,最後將平均值作為兩影象的結構相似性度量,即平均結構相似性SSIM

# -*- coding: utf-8 -*-
# !/usr/bin/env python
# @Time    : 2018/11/17 14:26
# @Author  : xhh
# @Desc    : 結構相似度量,計算圖片之間的相似度
# @File    : difference_image_ssim.py
# @Software: PyCharm
from skimage.measure import compare_ssim
from scipy.misc import imread
import numpy as np

# 讀取圖片
img1 = imread('../dataset/100002.png')
img2 = imread('../dataset/100001.png')
img2 = np.resize(img2, (img1.shape[0], img1.shape[1], img1.shape[2]))
print(img1.shape)
print(img2.shape)
ssim =  compare_ssim(img1, img2, multichannel = True)
print(ssim)

本來是打算使用opencv的imread來讀取圖片的,但是沒想到報錯了,但是隨後改為

scipy.misc import imread成功了,最後又改成了opencv又好了,有點懵逼了

結果:

該方法通常用來衡量一張圖片壓縮後的失真度,很少用來計算兩圖的相似度。

3.通過直方圖計算

# -*- coding: utf-8 -*-
# !/usr/bin/env python
# @Time    : 2018/11/17 16:04
# @Author  : xhh
# @Desc    : 通過直方圖計算圖片的相似度
# @File    : difference_image_hist.py
# @Software: PyCharm
from PIL import Image

# 將圖片轉化為RGB
def make_regalur_image(img, size=(64, 64)):
    gray_image = img.resize(size).convert('RGB')
    return gray_image

# 計算直方圖
def hist_similar(lh, rh):
    assert len(lh) == len(rh)
    hist = sum(1 - (0 if l == r else float(abs(l-r))/max(l,r))for l, r in zip(lh, rh))/len(lh)
    return hist

# 計算相似度
def calc_similar(li, ri):
    calc_sim = hist_similar(li.histogram(), ri.histogram())
    return calc_sim

if __name__ == '__main__':
    image1 = Image.open('../dataset/100002.png')
    image1 = make_regalur_image(image1)
    image2 = Image.open('../dataset/100001.png')
    image2 = make_regalur_image(image2)
    print("圖片間的相似度為",calc_similar(image1, image2))


執行結果:

直方圖過於簡單,只能捕捉顏色資訊的相似性,捕捉不到更多的資訊。只要顏色分佈相似,就會判定二者相似度較高。

所以本菜鳥利用之前做驗證碼時的用灰度圖和彩色圖進行了對比:

執行的結果為:

結果為0.54,有點差強人意了。。

4.還有通過感知雜湊演算法(或者也稱為圖片指紋的形式的,嗯,我是這樣子理解的)

具體的程式碼看之前的文章:https://blog.csdn.net/weixin_39121325/article/details/84174876

。。。。佔時就這些了,還有的遇到了在更新吧