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)是
xyz=r∗V∗S∗cosH=r∗V∗S∗sinH=h∗(1−V)
x
=
r
∗
V
∗
S
∗
c
o
s
H
y
=
r
∗
V
∗
S
∗
s
i
n
H
z
=
h
∗
(
1
−
V
)
具体代码实现:
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