計算圖片相似度的方法

文章目錄

  • 1.余弦相似度計算
  • 2.哈希算法計算圖片的相似度
  • 3.直方圖計算圖片的相似度
  • 4.SSIM(結構相似度度量)計算圖片的相似度
  • 5.基于互信息(Mutual Information)計算圖片的相似度

1.余弦相似度計算

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

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 = vectorsa_norm, b_norm = norms# dot返回的是點積,對二維數組(矩陣)進行計算res = dot(a / a_norm, b / b_norm)return res
image1 = Image.open('010.jpg')
image2 = Image.open('011.jpg')
cosin = image_similarity_vectors_via_numpy(image1, image2)
print('圖片余弦相似度', cosin)

2.哈希算法計算圖片的相似度

感知哈希算法是一類算法的總稱,包括aHash、pHash、dHash。顧名思義,感知哈希不是以嚴格的方式計算Hash值,而是以更加相對的方式計算哈希值,因為“相似”與否,就是一種相對的判定。

幾種hash值的比較:

aHash:平均值哈希。速度比較快,但是常常不太精確。
pHash:感知哈希。精確度比較高,但是速度方面較差一些。
dHash:差異值哈希。精確度較高,且速度也非常快
值哈希算法、差值哈希算法和感知哈希算法都是值越小,相似度越高,取值為0-64,即漢明距離中,64位的hash值有多少不同。三直方圖和單通道直方圖的值為0-1,值越大,相似度越高。

import cv2
import numpy as np
from PIL import Image
import requests
from io import BytesIO
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as pltdef aHash(img):# 均值哈希算法# 縮放為8*8img = cv2.resize(img, (8, 8))# 轉換為灰度圖gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# s為像素和初值為0,hash_str為hash值初值為''s = 0hash_str = ''# 遍歷累加求像素和for i in range(8):for j in range(8):s = s+gray[i, j]# 求平均灰度avg = s/64# 灰度大于平均值為1相反為0生成圖片的hash值for i in range(8):for j in range(8):if gray[i, j] > avg:hash_str = hash_str+'1'else:hash_str = hash_str+'0'return hash_strdef dHash(img):# 差值哈希算法# 縮放8*8img = cv2.resize(img, (9, 8))# 轉換灰度圖gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)hash_str = ''# 每行前一個像素大于后一個像素為1,相反為0,生成哈希for i in range(8):for j in range(8):if gray[i, j] > gray[i, j+1]:hash_str = hash_str+'1'else:hash_str = hash_str+'0'return hash_strdef pHash(img):# 感知哈希算法# 縮放32*32img = cv2.resize(img, (32, 32))   # , interpolation=cv2.INTER_CUBIC# 轉換為灰度圖gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 將灰度圖轉為浮點型,再進行dct變換dct = cv2.dct(np.float32(gray))# opencv實現的掩碼操作dct_roi = dct[0:8, 0:8]hash = []avreage = np.mean(dct_roi)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 calculate(image1, image2):# 灰度直方圖算法# 計算單通道的直方圖的相似值hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])# 計算直方圖的重合度degree = 0for i in range(len(hist1)):if hist1[i] != hist2[i]:degree = degree + \(1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))else:degree = degree + 1degree = degree / len(hist1)return degreedef classify_hist_with_split(image1, image2, size=(256, 256)):# RGB每個通道的直方圖相似度# 將圖像resize后,分離為RGB三個通道,再計算每個通道的相似值image1 = cv2.resize(image1, size)image2 = cv2.resize(image2, size)sub_image1 = cv2.split(image1)sub_image2 = cv2.split(image2)sub_data = 0for im1, im2 in zip(sub_image1, sub_image2):sub_data += calculate(im1, im2)sub_data = sub_data / 3return sub_datadef cmpHash(hash1, hash2):# Hash值對比# 算法中1和0順序組合起來的即是圖片的指紋hash。順序不固定,但是比較的時候必須是相同的順序。# 對比兩幅圖的指紋,計算漢明距離,即兩個64位的hash值有多少是不一樣的,不同的位數越小,圖片越相似# 漢明距離:一組二進制數據變成另一組數據所需要的步驟,可以衡量兩圖的差異,漢明距離越小,則相似度越高。漢明距離為0,即兩張圖片完全一樣n = 0# hash長度不同則返回-1代表傳參出錯if len(hash1) != len(hash2):return -1# 遍歷判斷for i in range(len(hash1)):# 不相等則n計數+1,n最終為相似度if hash1[i] != hash2[i]:n = n + 1return ndef getImageByUrl(url):# 根據圖片url 獲取圖片對象html = requests.get(url, verify=False)image = Image.open(BytesIO(html.content))return imagedef PILImageToCV():# PIL Image轉換成OpenCV格式path = "/Users/waldenz/Documents/Work/doc/TestImages/t3.png"img = Image.open(path)plt.subplot(121)plt.imshow(img)print(isinstance(img, np.ndarray))img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)print(isinstance(img, np.ndarray))plt.subplot(122)plt.imshow(img)plt.show()def CVImageToPIL():# OpenCV圖片轉換為PIL imagepath = "/Users/waldenz/Documents/Work/doc/TestImages/t3.png"img = cv2.imread(path)# cv2.imshow("OpenCV",img)plt.subplot(121)plt.imshow(img)img2 = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))plt.subplot(122)plt.imshow(img2)plt.show()def bytes_to_cvimage(filebytes):# 圖片字節流轉換為cv imageimage = Image.open(filebytes)img = cv2.cvtColor(np.asarray(image), cv2.COLOR_RGB2BGR)return imgdef runAllImageSimilaryFun(para1, para2):# 均值、差值、感知哈希算法三種算法值越小,則越相似,相同圖片值為0# 三直方圖算法和單通道的直方圖 0-1之間,值越大,越相似。 相同圖片為1# t1,t2   14;19;10;  0.70;0.75# t1,t3   39 33 18   0.58 0.49# s1,s2  7 23 11     0.83 0.86  挺相似的圖片# c1,c2  11 29 17    0.30 0.31if para1.startswith("http"):# 根據鏈接下載圖片,并轉換為opencv格式img1 = getImageByUrl(para1)img1 = cv2.cvtColor(np.asarray(img1), cv2.COLOR_RGB2BGR)img2 = getImageByUrl(para2)img2 = cv2.cvtColor(np.asarray(img2), cv2.COLOR_RGB2BGR)else:# 通過imread方法直接讀取物理路徑img1 = cv2.imread(para1)img2 = cv2.imread(para2)hash1 = aHash(img1)hash2 = aHash(img2)n1 = cmpHash(hash1, hash2)print('均值哈希算法相似度aHash:', n1)hash1 = dHash(img1)hash2 = dHash(img2)n2 = cmpHash(hash1, hash2)print('差值哈希算法相似度dHash:', n2)hash1 = pHash(img1)hash2 = pHash(img2)n3 = cmpHash(hash1, hash2)print('感知哈希算法相似度pHash:', n3)n4 = classify_hist_with_split(img1, img2)print('三直方圖算法相似度:', n4)n5 = calculate(img1, img2)print("單通道的直方圖", n5)print("%d %d %d %.2f %.2f " % (n1, n2, n3, round(n4[0], 2), n5[0]))print("%.2f %.2f %.2f %.2f %.2f " % (1-float(n1/64), 1 -float(n2/64), 1-float(n3/64), round(n4[0], 2), n5[0]))plt.subplot(121)plt.imshow(Image.fromarray(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)))plt.subplot(122)plt.imshow(Image.fromarray(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)))plt.show()if __name__ == "__main__":p1="https://ww3.sinaimg.cn/bmiddle/007INInDly1g336j2zziwj30su0g848w.jpg"p2="https://ww2.sinaimg.cn/bmiddle/007INInDly1g336j10d32j30vd0hnam6.jpg"runAllImageSimilaryFun(p1,p2)

3.直方圖計算圖片的相似度

利用直方圖計算圖片的相似度時,是按照顏色的全局分布情況來看待的,無法對局部的色彩進行分析,同一張圖片如果轉化成為灰度圖時,在計算其直方圖時差距就更大了。對于灰度圖可以將圖片進行等分,然后在計算圖片的相似度。

# 將圖片轉化為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_simif __name__ == '__main__':image1 = Image.open('123.jpg')image1 = make_regalur_image(image1)image2 = Image.open('456.jpg')image2 = make_regalur_image(image2)print("圖片間的相似度為", calc_similar(image1, image2))

4.SSIM(結構相似度度量)計算圖片的相似度

SSIM是一種全參考的圖像質量評價指標,分別從亮度、對比度、結構三個方面度量圖像相似性。SSIM取值范圍[0, 1],值越大,表示圖像失真越小。在實際應用中,可以利用滑動窗將圖像分塊,令分塊總數為N,考慮到窗口形狀對分塊的影響,采用高斯加權計算每一窗口的均值、方差以及協方差,然后計算對應塊的結構相似度SSIM,最后將平均值作為兩圖像的結構相似性度量,即平均結構相似性SSIM。

# -*- coding: utf-8 -*-
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)

5.基于互信息(Mutual Information)計算圖片的相似度

通過計算兩個圖片的互信息來表征他們之間的相似度,如果兩張圖片尺寸相同,還是能在一定程度上表征兩張圖片的相似性的。但是,大部分情況下圖片的尺寸不相同,如果把兩張圖片尺寸調成相同的話,又會讓原來很多的信息丟失,所以很難把握。經過實際驗證,此種方法的確很難把握。

from sklearn import metrics as mr
from scipy.misc import imread
import numpy as npimg1 = 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)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/535194.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/535194.shtml
英文地址,請注明出處:http://en.pswp.cn/news/535194.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

.size .shape .size() type的運用

.size ndarray.size 數組元素的總個數,相當于 .shape 中 n*m 的值 a np.array([2,2]) print(a.size)2.shap ndarray.shape 數組的維度,對于矩陣,n 行 m 列 a np.array([2,2]) print(a.shape) (1,2)torch.tensor 數組的維度 x torch.r…

矩陣相加

tensor 類型 a torch.randn(1,3,3) b torch.randn(1,3,3) c a b numpy.array 類型 a np.array([2,2]) b np.array([2,2]) print(type(a)) print(ab)[4,4]

Latex 生成的PDF增加行號 左右兩邊

增加行號 \usepackage[switch]{lineno}\linenumbers \begin{document} \end{document}

pytorh .to(device) 和.cuda()的區別

原理 .to(device) 可以指定CPU 或者GPU device torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # 單GPU或者CPU model.to(device) #如果是多GPU if torch.cuda.device_count() > 1:model nn.DataParallel(model,devic…

Linux 修改用戶名的主目錄 家目錄

首先root 登陸 sudo -i 輸入密碼然后 vim /etc/passwd 找到用戶名 然后修改后面的路徑即可

ubunt16.04 安裝3090顯卡驅動 cuda cudnn pytorch

安裝驅動 需要的安裝包 30系列顯卡是新一代架構,新驅動不支持cuda9以及cuda10,所以必須安裝cuda11、而pytorch現在穩定版為1.6,最高僅支持到cud10.2。所以唯一的辦法就是使用上處于beta測試的1.7或1.8。這也是為啥一開始就強調本文的寫作時…

3090顯卡 torch.cuda.is_available()返回false的解決辦法

問題 1.執行Nvidia-smi 命令沒有報錯,能夠顯示驅動信息; 2.執行 torch.backends.cudnn.enabled is TRUE 3.torch.cuda.is_available()一直返回False 解決 把torch,torchvision等相關安裝包全部刪除,安裝適合版本的torch。 30系…

測試項目:車牌檢測,行人檢測,紅綠燈檢測,人流檢測,目標識別

本項目為2020年中國軟件杯A組第一批賽題"基于計算機視覺的交通場景智能應用".項目用python實現,主要使用YOLO模型實現道路目標如人、車、交通燈等物體的識別,使用開源的"中文車牌識別HyperLPR&a…

pytorch: 在訓練中保存模型,加載模型

文章目錄1. 保存整個模型2.僅保存和加載模型參數(推薦使用)3. 保存其他參數到模型中,比如optimizer,epoch 等1. 保存整個模型 torch.save(model, model.pkl) model torch.load(model.pkl)2.僅保存和加載模型參數(推薦使用) torch.save(model_object.state_dict()…

Pytorch:保存圖片

1. 直接保存Tensor #!/usr/bin/env python # _*_ coding:utf-8 _*_ import torch from torchvision import utils as vutilsdef save_image_tensor(input_tensor: torch.Tensor, filename):"""將tensor保存為圖片:param input_tensor: 要保存的tensor:param fi…

Python List:合并多個list,listd的合并

第一種方法 a [1,3,3] b [2,3,3] a a b print(a) [1,3,3,2,3,3]第二種方法 a [1,3,3] b [2,3,3] a.extend(b) print(a) [1,3,3,2,3,3]

掛載硬盤問題:mount: wrong fs type, bad option, bad superblock on /dev/sdb,

mount: wrong fs type, bad option, bad superblock on /dev/sdb,missing codepage or helper program, or other error 解決方案: # create mount dir sudo mkdir /hdd6T# new file system sudo mkfs.ext4 /dev/sdc# mount drive sudo mount /dev/sdc /hdd6T/# c…

linux 安裝python3.8的幾種方法

1.命令行搞定 git clone https://github.com/waketzheng/carstino cd carstino python3 upgrade_py.py2.離線安裝 自己在官網下載安裝包 https://www.python.org/ftp/python/3.8.0/ 解壓: tar -zvf Python-3.8.0.tgz安裝 cd Python-3.8.0 ./configure --prefix/u…

面試題目:欠擬合、過擬合及如何防止過擬合

對于深度學習或機器學習模型而言,我們不僅要求它對訓練數據集有很好的擬合(訓練誤差),同時也希望它可以對未知數據集(測試集)有很好的擬合結果(泛化能力),所產生的測試誤…

LaTeX:equation, aligned 書寫公式換行,頂部對齊

使用aligined 函數,其中aligned就是用來公式對齊的,在中間公式中,\ 表示換行, & 表示對齊。在公式中等號之前加&,等號介紹要換行的地方加\就可以了。 \begin{equation} \begin{aligned} L_{task} &\lamb…

Latex: 表格中 自動換行居中

1、在導言區添加宏包: \usepackage{makecell}2、環境:tabular 命令: \makecell[居中情況]{第1行內容 \\ 第2行內容 \\ 第3行內容 ...} \makecell [c]{ResNet101\\ (11.7M)}參數說明: [c]是水平居中,[l]水平左居中&am…

argparse:shell向Python中傳參數

一般是 python train.py --bath_size 5利用argparse解析參數 import argparse parser argparse.ArgumentParser() parser.add_argument(integer, typeint, helpdisplay an integer) args parser.parse_args()參數類型 可選參數 import argparse parser argparse.Argumen…

FTP命令:下載,上傳FTP服務器中的文件

步驟 1: 建立 FTP 連接 想要連接 FTP 服務器,在命令上中先輸入ftp然后空格跟上 FTP 服務器的域名 domain.com 或者 IP 地址例如:1.ftp domain.com2.ftp 192.168.0.13.ftp userftpdomain.com注意: 本例中使用匿名服務器。替換下面例子中 IP 或域名為你的服務器地址。…

Tensorflow代碼轉pytorch代碼 函數的轉換

tensoflow函數和pytorch函數之間的轉換 tensorflowpytrochtf.reshape(input, shape)input.view()tf.expand_dims(input, dim)input.unsqueeze(dim) / input.view()tf.squeeze(input, dim)torch.squeeze(dim)/ input.view()tf.gather(input1, input2)input1[input2]tf.tile(inp…

在服務器上遠程使用tensorboard查看訓練loss和準確率

本人使用的是vscode 很簡單 from torch.utils.tensorboard import SummaryWriter writer SummaryWriter(./logs)writer.add_scalar(train_loss,loss.val(),iteration) # 名字,數據,迭代次數訓練的過程中會產生一個./logs的文件夾,里面存放的…