栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

数据增强:随机HSV增强

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据增强:随机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 ° ] [0degree, 360degree] [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={VV−min(R,G,B)​0​if   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(G−B)/(V−min(R,G,B))120+60(B−R)/(V−min(R,G,B))240+60(R−B)/(V−min(R,G,B))0​if   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} ​0≤V≤10≤S≤10≤H≤360​

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

2.2 例子

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

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​={VV−min(R,G,B)​0​if   V​=0otherwise​=0.72940.7294−min(0.7294,0.7020,0.5922)​=0.72940.7294−0.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(G−B)/(V−min(R,G,B))120+60(B−R)/(V−min(R,G,B))240+60(R−B)/(V−min(R,G,B))0​if   V=Rif   V=Gif   V=Bif   R=G=B​=60(G−B)/(V−min(R,G,B))=60(0.7020−0.5922)/(0.7294−0.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.7294,S=0.1881,H=48.0175。

如果 H ≤ 0 Hle0 H≤0,那么 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' = 255times 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' = 255times V rightarrow 185.9970 end{aligned} ​H′=2H​→24.0088S′=255×S→47.9655V′=255×V→185.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 [0degree, 360degree] rightarrow [0degree, 180degree] 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.uniform对h, 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
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/923942.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号