数据增强:随机HSV增强

1. HSV色彩空间介绍

HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。在HSV模型中,颜色是由色度(Hue),饱和度(Saturation),明度(Value)共同组成。

在这里插入图片描述

HSV 模型显示为圆柱形或圆锥形物体。当它表示为圆锥形物体时,色调由圆锥形的圆形部分表示。圆锥体通常以三维形式表示。饱和度是使用圆锥的半径计算的,值是圆​​锥的高度。六角锥也可以用来表示 HSV 模型。圆锥模型的优点是它能够在单个对象中表示 HSV 颜色空间。由于计算机接口的二维特性,HSV 的圆锥模型最适合为计算机图形选择颜色

HSV色彩空间的圆柱模型的应用与圆锥模型类似。计算以类似的方式完成。从理论上讲,圆柱模型是 HSV 颜色空间计算的最准确形式。在实际使用中,降低值时无法区分饱和度和色调。圆柱模型因此失去了相关性,圆锥形状比它更受欢迎

1.1 色度(Hue)

色度(Hue)即表示颜色,使用角度 ° \degree °度量的,范围为 [ 0 ° , 360 ° ] [0\degree, 360\degree] [0°,360°](逆时针旋转),色度范围如下图所示。

在这里插入图片描述

其中:

角度( ° \degree °)对应颜色表示
0-60红色
60-120黄色
120-180绿色
180-240青色
240-300蓝色
300-360品红

1.2 饱和度(Saturation)

饱和度(Saturation)表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。其范围是 [ 0 , 1 ] [0, 1] [0,1]越大色彩越饱和)。

在这里插入图片描述

1.3 明度(Value)

明度(Value)表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关。其范围是 [ 0 , 1 ] [0, 1] [0,1]越大色彩越亮)。

在这里插入图片描述

1.4 HSV的应用

HSV 颜色空间被广泛用于生成高质量的计算机图形。简单来说,就是用来选择特定图片所需的各种不同颜色。用户可以从色轮中选择图片所需的特定颜色。它根据人类的感知给出颜色。

1.5 HSV的优势

HSV 颜色空间与人类感知颜色的方式非常相似。除 HSL 外,其他模型定义与原色相关的颜色。 HSV 中使用的颜色可以通过人类感知清楚地定义,而 RGB 或 CMYK 并非总是如此

2. RGB色彩空间转为HSV色彩空间

2.1 OpenCV官方提供的公式

参考OpenCV官方文档
在这里插入图片描述

首先将 R , G , B R, G, B R,G,B分量数值缩放到范围0到1之间(除以255)。 接下来按如下公式进行转换即可(RGB转HSV需要先计算V再计算S最后计算H😂)。

V = max ⁡ ( R , G , B ) V = \max(R,G,B) V=max(R,G,B)
S = { V − min ⁡ ( R , G , B ) V if    V ≠ 0 0 otherwise S = \begin{cases} \frac{V - \min(R, G, B)}{V} & \text{if} \ \ \ V \ne 0 \\ 0 & \text{otherwise} \end{cases} S={VVmin(R,G,B)0if   V=0otherwise
H = { 60 ( G − B ) / ( V − min ⁡ ( R , G , B ) ) if    V = R 120 + 60 ( B − R ) / ( V − min ⁡ ( R , G , B ) ) if    V = G 240 + 60 ( R − B ) / ( V − min ⁡ ( R , G , B ) ) if    V = B 0 if    R = G = B H = \begin{cases} 60(G - B) / (V - \min(R, G, B)) & \text{if} \ \ \ V = R \\ 120 + 60(B - R) / (V - \min(R, G, B)) & \text{if} \ \ \ V = G \\ 240 + 60(R- B) / (V - \min(R, G, B)) & \text{if} \ \ \ V = B \\ 0 & \text{if} \ \ \ R= G = B \end{cases} H=60(GB)/(Vmin(R,G,B))120+60(BR)/(Vmin(R,G,B))240+60(RB)/(Vmin(R,G,B))0if   V=Rif   V=Gif   V=Bif   R=G=B

如果计算的结果<0,那么就加上360。其中:
0 ≤ V ≤ 1 0 ≤ S ≤ 1 0 ≤ H ≤ 360 \begin{aligned} & 0 \le V \le 1 \\ & 0 \le S \le 1 \\ & 0 \le H \le 360 \\ \end{aligned} 0V10S10H360

值得注意的是,上面的公式是针对某个像素点计算的

2.2 例子

在这里插入图片描述

假设一个像素点对应的RGB分量为(186, 179, 151),其在HSV色彩空间中对应的数值为:

归一化
V
S
H

R , G , B = ( 186 , 179 , 151 ) / 255 = ( 0.7294 , 0.7020 , 0.5922 ) \begin{aligned} R,G,B & = (186, 179, 151) / 255 \\ & = (0.7294, 0.7020, 0.5922) \end{aligned} R,G,B=(186,179,151)/255=(0.7294,0.7020,0.5922)
V = max ⁡ ( 0.7294 , 0.7020 , 0.5922 ) = 0.7294 \begin{aligned} V & = \max(0.7294, 0.7020, 0.5922)\\ & = 0.7294 \end{aligned} V=max(0.7294,0.7020,0.5922)=0.7294
S = { V − min ⁡ ( R , G , B ) V if    V ≠ 0 0 otherwise = 0.7294 − min ⁡ ( 0.7294 , 0.7020 , 0.5922 ) 0.7294 = 0.7294 − 0.5922 0.7294 = 0.1881 \begin{aligned} S & = \begin{cases} \frac{V - \min(R, G, B)}{V} & \text{if} \ \ \ V \ne 0 \\ 0 & \text{otherwise} \end{cases}\\ & =\frac{0.7294 - \min(0.7294, 0.7020, 0.5922)}{0.7294}\\ & =\frac{0.7294 - 0.5922}{0.7294}\\ & = 0.1881 \end{aligned} S={VVmin(R,G,B)0if   V=0otherwise=0.72940.7294min(0.7294,0.7020,0.5922)=0.72940.72940.5922=0.1881
H = { 60 ( G − B ) / ( V − min ⁡ ( R , G , B ) ) if    V = R 120 + 60 ( B − R ) / ( V − min ⁡ ( R , G , B ) ) if    V = G 240 + 60 ( R − B ) / ( V − min ⁡ ( R , G , B ) ) if    V = B 0 if    R = G = B = 60 ( G − B ) / ( V − min ⁡ ( R , G , B ) ) = 60 ( 0.7020 − 0.5922 ) / ( 0.7294 − 0.5922 ) = 48.0175 \begin{aligned} H & = \begin{cases} 60(G - B) / (V - \min(R, G, B)) & \text{if} \ \ \ V = R \\ 120 + 60(B - R) / (V - \min(R, G, B)) & \text{if} \ \ \ V = G \\ 240 + 60(R- B) / (V - \min(R, G, B)) & \text{if} \ \ \ V = B \\ 0 & \text{if} \ \ \ R= G = B \end{cases}\\ & = 60(G - B) / (V - \min(R, G, B)) \\ & = 60(0.7020 - 0.5922) / (0.7294 - 0.5922) \\ & = 48.0175 \end{aligned} H=60(GB)/(Vmin(R,G,B))120+60(BR)/(Vmin(R,G,B))240+60(RB)/(Vmin(R,G,B))0if   V=Rif   V=Gif   V=Bif   R=G=B=60(GB)/(Vmin(R,G,B))=60(0.70200.5922)/(0.72940.5922)=48.0175

那么该RGB像素点转换为HSV色彩空间后的 V = 0.7294 , S = 0.1881 , H = 48.0175 V=0.7294,S=0.1881, H=48.0175 V=0.7294S=0.1881,H=48.0175

如果 H ≤ 0 H\le0 H0,那么 H = H + 360 H = H + 360 H=H+360

3. OpenCV实现RGB转HSV

3.1 函数调用及其注意事项

使用OpenCV将RGB模型图像转成HSV模型图像非常简单,直接使用cv2.cvtColor函数,在ColorConversionCodes参数中传入cv2.COLOR_RGB2HSV参数即可。

cv2.cvtColor官方文档
ColorConversionCodes官方文档

需要注意的是,通过OpenCV转HSV后会根据传入的数据类型缩放到不同范围,如果输入的是Uint8类型的数据(一般读入的图片数据类型都是Uint8),默认缩放到0到255之间 。 那么对于饱和度和明度(默认0到1之间)而言直接乘以255然后取整即可。对于色度(默认是在0到360之间)由于超出了Uint8数据类型的范围,所以官方储存时是直接除以2即缩放到0到180之间

  • 8-bit图片 -> Uint8 V ′ = 255 × V , S ′ = 255 × S , H ′ = H 2 V' = 255\times V, S' = 255 \times S, H' = \frac{H}{2} V=255×V,S=255×S,H=2H
  • 16-bit图片:当前并不支持😂
  • 32-bit图片 -> float32:直接原值存储即可

那么对于刚刚讲的示例将(186, 179, 151)RGB模型空间转到HSV模型空间得到是(48.0175, 0.1881, 0.7294),按照刚刚讲的在OpenCV转换后应该是:

H ′ = H 2 → 24.0088 S ′ = 255 × S → 47.9655 V ′ = 255 × V → 185.9970 \begin{aligned} & H' = \frac{H}{2} \rightarrow 24.0088\\ & S' = 255 \times S \rightarrow 47.9655\\ & V' = 255\times V \rightarrow 185.9970 \end{aligned} H=2H24.0088S=255×S47.9655V=255×V185.9970

3.2 例子

https://blog.csdn.net/qq_37541097/article/details/119478023

import cv2
import numpy as np

rgb_point = np.array([186, 179, 151], dtype=np.uint8).reshape((1, 1, 3))
hsv_point = cv2.cvtColor(rgb_point, cv2.COLOR_RGB2HSV)
print(hsv_point)  # [[[ 24  48 186]]]

和我们计算的是一样的。

3.3 HSV控制变量

接下来在使用OpenCV来固定色度(Hue),饱和度(Saturation),明度(Value)其中两个变量,渐变剩下一个变量来看看效果。

3.3.1 变量 —— Hue

需要注意的是,在HSV色彩空间中,因为保存方式的原因,所以 H ∈ [ 0 ° , 360 ° ] → [ 0 ° , 180 ° ] H \in [0\degree, 360\degree] \rightarrow [0\degree, 180\degree] H[0°,360°][0°,180°]

"""
    Hue
"""
import cv2
import numpy as np

# np.tile(a,(x,y,z))表示将数组a在行上重复x次,在列上重复y次,在第三维度重复z次(假设数组a是一维的)
hue = np.tile(np.arange(0, 180, dtype=np.uint8).reshape((1, 180, 1)), (50, 1, 1))

saturation = np.ones((50, 180, 1), dtype=np.uint8) * 255
value = np.ones((50, 180, 1), dtype=np.uint8) * 255

img_hsv = cv2.merge((hue, saturation, value))
img = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)
img = cv2.resize(img, (720, 100))
cv2.imwrite("./Hue.jpg", img)
cv2.imshow("Hue", img)
cv2.waitKey(0)

在这里插入图片描述

3.3.2 变量 —— Saturation

"""
    Saturation
"""
import cv2
import numpy as np


hue = np.zeros((100, 256, 1), dtype=np.uint8)
sat = np.tile(np.arange(0, 256, dtype=np.uint8).reshape((1, 256, 1)), (100, 1, 1))
val = np.ones((100, 256, 1), dtype=np.uint8) * 255
img_hsv = cv2.merge((hue, sat, val))
img = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)
img = cv2.resize(img, (720, 100))
cv2.imwrite("./Saturation.jpg", img)
cv2.imshow("img", img)
cv2.waitKey(0)

在这里插入图片描述

3.3.3 变量 —— Value

"""
    Value
"""
import cv2
import numpy as np


hue = np.zeros((100, 256, 1), dtype=np.uint8)
sat = np.ones((100, 256, 1), dtype=np.uint8) * 255
val = np.tile(np.arange(0, 256, dtype=np.uint8).reshape((1, 256, 1)), (100, 1, 1))
img_hsv = cv2.merge((hue, sat, val))
img = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)
img = cv2.resize(img, (720, 100))
cv2.imwrite("./Value.jpg", img)
cv2.imshow("img", img)
cv2.waitKey(0)

在这里插入图片描述

4. HSV在数据增强中的应用

https://blog.csdn.net/qq_37541097/article/details/119478023

import cv2
import numpy as np


def augment_hsv(img, h_gain=0.5, s_gain=0.5, v_gain=0.5):
    r = np.random.uniform(-1, 1, 3) * [h_gain, s_gain, v_gain] + 1  # random gains
    hue, sat, val = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))
    dtype = img.dtype  # uint8

    x = np.arange(0, 256, dtype=np.int16)
    lut_hue = ((x * r[0]) % 180).astype(dtype)
    lut_sat = np.clip(x * r[1], 0, 255).astype(dtype)
    lut_val = np.clip(x * r[2], 0, 255).astype(dtype)

    img_hsv = cv2.merge((cv2.LUT(hue, lut_hue), cv2.LUT(sat, lut_sat), cv2.LUT(val, lut_val))).astype(dtype)
    aug_img = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)
    return aug_img
  1. 首先传入图像img以及三个超参数h_gain, s_gain, v_gain
  2. 使用np.random.uniformh, s, v分别随机生成了一个 [ − 1 , 1 ] [-1, 1] [1,1]之间的随机数,然后分别乘上三个超参数h_gain, s_gain, v_gain,最后加上1
    假设h_gain=0.5那么会在[0.5, 1.5]之间随机生成一个倍率因子,后面会将所有Hue数值乘上这个倍率。s_gain, v_gain同理。
  3. 使用cv2.cvtColor函数将传入的图片由BGR格式(OpenCV读取图片的默认格式是BGR)转成HSV,在使用cv2.split函数将HSV分量分开分别赋值给hue, sat, val
  4. 分别针对hue, sat, val生成对应的Look-Up Table(LUT)查找表(记录变换前后数值的对应表)。
    就是将0-255范围内所有的数值都乘以刚刚生成的随机倍率因子构建LUT,后面针对每个元素直接查表无需再计算。
    注意,hue范围是在0到180之间的,所以有个取余的操作(%180),sat和val范围是0到255之间,所以使用np.clip防止越界。
  5. 使用cv2.LUT方法利用刚刚针对hue, sat, val生成的Look-Up Table进行变换。变换后使用cv2.merge方法再将hue, sat, val分量合并为HSV图像。
  6. 最后使用cv2.cvtColor再将HSV图像转换回BGR图像。

import cv2
import numpy as np


def augment_hsv(img, h_gain=0.5, s_gain=0.5, v_gain=0.5):
    r = np.random.uniform(-1, 1, 3) * [h_gain, s_gain, v_gain] + 1  # 倍率因子
    hue, sat, val = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))  # 获取原图的hue, saturation, value
    dtype = img.dtype  # 一般为uint8
	
	# 针对hue, saturation, value生成对应的LUT表(记录变换前后数值的对应表)
    x = np.arange(0, 256, dtype=np.int16)  # [0, 255]
    lut_hue = ((x * r[0]) % 180).astype(dtype)
    lut_sat = np.clip(x * r[1], 0, 255).astype(dtype)
    lut_val = np.clip(x * r[2], 0, 255).astype(dtype)
	
	# 将hue, saturation, value分量合并为hsv图像
    img_hsv = cv2.merge((cv2.LUT(hue, lut_hue), cv2.LUT(sat, lut_sat), cv2.LUT(val, lut_val))).astype(dtype)
	# 将HSV图像转换回BGR图像
    aug_img = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)
    return aug_img


img = cv2.imread("./img_exp.jpg")

# 对该图片进行随机HSV数据增强
aug_img = augment_hsv(img=img, h_gain=0.5, s_gain=0.8, v_gain=0.9)

cv2.imshow("origin image", img)
cv2.imshow("Random HSV augmentation", aug_img)
cv2.waitKey(0)

在这里插入图片描述

参考

  1. https://blog.csdn.net/qq_37541097/article/details/119478023
  2. https://www.tech-faq.com/hsv.html
  3. https://docs.opencv.org/master/de/d25/imgproc_color_conversions.html#color_convert_rgb_hsv
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值