图像处理のHSV变换原理及实现

考虑到研究生可能会研究CV领域,先学点opencv打点基础,今日成果——HSV变换算法及python实现

HSV变换

参考blog:

本题来源于github opencv100题第5题:HSV变换

原理

将RGB表示的图像转换为HSV表示,其中,H表示色相(Hue),S表示饱和度(Saturation),V表示明度(Value),这边贴一张上方某blog内可视化表示HSV含义的图,清晰明了

20180520172120828

$\text{RGB}$的取值范围为$[0, 1]$,令:

色相:

饱和度:

明度:

从$\text{HSV}$色彩表示转换到$\text{RGB}$色彩表示通过以下方式计算:

题意

请将色相反转(色相值加$180$),然后再用$\text{RGB}$色彩空间表示图片。

代码

PS:算法中可能出现除以0的浮点问题,我在分母上加了0.001防了一波,否则一块黑色的nan很难看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import cv2
import numpy as np

def rgb2hsv(img):
hsv = np.zeros_like(img, dtype=np.float32)
img = img/255.0
R = img[...,2]
G = img[...,1]
B = img[...,0]
Max = np.max(img, axis=2)
Min = np.min(img, axis=2)
min_arg = np.argmin(img, axis=2)

hsv[...,0][np.where(Max==Min)] = 0

ind = np.where(min_arg==0) # Min==B
hsv[...,0][ind] = 60*(G[ind]-R[ind])/(Max[ind]-Min[ind]+0.001)+60

ind = np.where(min_arg==2) # Min==R
hsv[...,0][ind] = 60*(B[ind]-G[ind])/(Max[ind]-Min[ind]+0.001)+180

ind = np.where(min_arg==1) # Min==G
hsv[...,0][ind] = 60*(R[ind]-B[ind])/(Max[ind]-Min[ind]+0.001)+300


hsv[...,1] = Max-Min # S
hsv[...,2] = Max # V
return hsv

def hsv2rgb(hsv):
H = hsv[...,0]
S = hsv[...,1]
V = hsv[...,2]
C = S
H_ = H/60
X = C*(1-np.abs(H_%2-1))
Z = np.zeros_like(C)
rgb = np.zeros_like(hsv)
table = [[Z,X,C],[Z,C,X],[X,C,Z],[C,X,Z],[C,Z,X],[X,Z,C]]
for i in range(6):
ind = np.where((H_>=i)&(H_<(i+1)))
rgb[...,0][ind] = (V-C)[ind]+table[i][0][ind]
rgb[...,1][ind] = (V-C)[ind]+table[i][1][ind]
rgb[...,2][ind] = (V-C)[ind]+table[i][2][ind]

rgb = np.clip(rgb,0,1)
rgb = (rgb*255).astype(np.uint8)
return rgb


img = cv2.imread("test.jpg")
hsv_img = rgb2hsv(img)
hsv_img[...,0] = (hsv_img[...,0]+180)%360
rgb_img = hsv2rgb(hsv_img)
cv2.imshow("img2", rgb_img)
cv2.imshow("img1", img)
cv2.waitKey(0)

效果

image-20200803183934553

知识点

np.zeros_like()

np.zeros_like(mat, dtype=np.float32)

生成一个规模mat相同,类型为np.float32全零ndarray

np.max()/np.min()

np.max(mat, axis=2)

用于计算以axis=2轴为比较对象的最大值,即:取每axis=2这一维度的最大值,将其压成一维,其他维度不变,比如一个4*3*2的数组经过上述变换就变成了4*3的矩数组

np.argmax()/np.argmin()

np.argmin(mat, axis=2)

获得一个效果同np.max()规模的矩阵,元素值为mataxis轴上最小值的索引

np.where()

np.where(mat1==mat2)

返回一个bool型矩阵,大小同mat1/mat2,比较两矩阵对应位置元素值是否相等,当满足条件时返回True,否则返回False


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!