HSV顏色空間下的圖片相似性計算(python版)

YouthDance發表於2018-03-26

HSV顏色空間下的圖片相似性計算(python版)

由於,論文需要對兩個圖片的亮度值進行比較。因為,RGB的侷限性,所以選擇了在HSV的顏色空間中進行計算。雖然,opencv中自帶有對直方圖的計算方式,但是由於HSV的特殊性。因此,無論我在C++中獲得的結果還是python中獲得的結果,都有點怪怪的不太正常。所以,想到了自己寫一個演算法來實現hsv顏色空間的圖片相似性計算,當然也可以單獨對H,S,V的距離分別單獨計算。本文就重點關注兩張圖片中的V值相似性值。
本文所有用的HSV三維空間座標轉換主要參考[WKM_WannaKnowMore][1]的部落格。

  • RGB與HSV的轉換
  • python多維矩陣轉換為向量陣列
  • HSV三維空間座標計算公式
  • 具體程式碼實現

RGB與HSV的轉換

對於RGB顏色空間到HSV顏色空間的轉換,網上有很多程式碼都可以作為參考。並且由於讀入圖片方式的不同,其轉換的方式也不同。總結來說就是,方法不唯一,看個人選擇。給出一種本文的實現方式。

python實現圖片讀入和顏色空間轉換:

import math
import cv2  
import numpy as np  
from matplotlib import pyplot as plt
import matplotlib.mlab as mlab  

img = cv2.imread('~/target1.jpg',cv2.IMREAD_COLOR)
HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

多維矩陣轉換為向量陣列

由於,第一步我們將RGB顏色空間轉換為HSV後得到的是多維的矩陣格式。而在python中,無論是畫直方圖還是接下來我們需要使用的歐幾里得距離計算都需要向量表示。因此,在這一步我們需要對第一步獲得結果進行處理,是的最終的表示結果是向量格式。
直接給出程式碼:

H, S, V = cv2.split(HSV)
aH = np.array(H).flatten()
aS = np.array(S1).flatten()
aV = np.array(V).flatten()

HSV三維空間座標計算公式

在斜邊長R,底面圓半徑為r,高為h的HSV圓錐體內,以地面圓心為原點,H=0為x軸正方向建立座標軸。那麼色值是(H,S,V)的點的三維座標(x,y,z)是

x=rVScosHy=rVSsinHz=h(1V)
\begin{aligned} x &= r*V*S*cosH\\ y &= r*V*S*sinH \\ z &= h*(1-V) \end{aligned}

具體程式碼實現:
x1 = r * V1[i] * S1[i] * math.cos(H1[i] / 180.0 * math.pi);
y1 = r * V1[i] * S1[i] * math.sin(H1[i] / 180.0 * math.pi);
z1 = h * (1 - V1[i]);

具體程式碼實現

import math
import cv2  
import numpy as np  
from matplotlib import pyplot as plt
import matplotlib.mlab as mlab  

img1 = cv2.imread('/home/*/result/target1.jpg',cv2.IMREAD_COLOR)

HSV1 = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV)
aH1, aS1, aV1 = cv2.split(HSV1)
H1 = np.array(aH1).flatten()
S1 = np.array(aS1).flatten()
V1 = np.array(aV1).flatten()

# img2 = cv2.imread('/home/*/allAreaColor/result1.jpg',cv2.IMREAD_COLOR)
img2 = cv2.imread('/home/*/localColor/result1.jpg',cv2.IMREAD_COLOR)

HSV2 = cv2.cvtColor(img2, cv2.COLOR_BGR2HSV)
aH2, aS2, aV2 = cv2.split(HSV2)
H2 = np.array(aH2).flatten()
S2 = np.array(aS2).flatten()
V2 = np.array(aV2).flatten()

R = 100.0;
angle = 30.0;
h = R * math.cos(angle / 180 * math.pi);
r = R * math.sin(angle / 180 * math.pi);

sum = 0.0
for i in range(0, len(H1)):
    x1 = r * V1[i] * S1[i] * math.cos(H1[i] / 180.0 * math.pi);
    y1 = r * V1[i] * S1[i] * math.sin(H1[i] / 180.0 * math.pi);
    z1 = h * (1 - V1[i]);

    x2 = r * V2[i] * S2[i] * math.cos(H2[i] / 180.0 * math.pi);
    y2 = r * V2[i] * S2[i] * math.sin(H2[i] / 180.0 * math.pi);
    z2 = h * (1 - V2[i]);

    dx = x1 - x2;
    dy = y1 - y2;
    dz = z1 - z2;

    sum = sum + dx * dx + dy * dy + dz * dz

eucli_dean = math.sqrt(sum)
print eucli_dean

相關文章