图像处理-图像色彩空间转变及范围

最近在做一些颜色域的深度学习实验,转换关乎到精度损失以及归一化等数据处理操作,在这里做一个浅浅的整理与总结

原始图像是自己的低对比度图片,所以亮度分量偏高。

'''
b : min-max 34 255
g : min-max 28 255
r : min-max 20 255
'''

HSV

参考链接:
https://zhuanlan.zhihu.com/p/67930839

HSV颜色空间通过颜色、深浅及亮暗三个维度来描述颜色。 在标准HSV空间中:
H通道的取值范围为0—360(角度),S通道的取值范围为0—1(0%—100%),V通道的取值范围为0—1(0%—100%)。

使用opencv转变的话
float32转变,h:0-360,s:0-1,v:0-1
uint8转变,h:0-180,s:0-255, v:0-255
uint8+full转变,h:0-255, s:0-255, v:0-255

看了一篇博文表示,三种转变中采用float32的精度损失最小,其次是uint8+full,损失最多的是转变后h在0-180范围的。

还有一点,官方文档说是0-180,实际试了几张图,最大也只能达到179。
在这里插入图片描述

import os
import cv2
import numpy as np

image_path_1 = './test.jpg'
save_path = './hsv/'
os.makedirs(save_path, exist_ok=True)


image = cv2.imread(image_path_1)
image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
h = image_hsv[:,:,0]
s = image_hsv[:,:,1]
v = image_hsv[:,:,2]
print('hsv h : min-max {} {}'.format(image_hsv[:,:,0].min(), image_hsv[:,:,0].max()))
print('hsv s : min-max {} {}'.format(image_hsv[:,:,1].min(), image_hsv[:,:,1].max()))
print('hsv v : min-max {} {}'.format(image_hsv[:,:,2].min(), image_hsv[:,:,2].max()))
cv2.imwrite(save_path + 'h.jpg', h)
cv2.imwrite(save_path + 's.jpg', s)
cv2.imwrite(save_path + 'v.jpg', v)

image = cv2.imread(image_path_1)
image_hsv_full = cv2.cvtColor(image, cv2.COLOR_BGR2HSV_FULL)
h_full = image_hsv_full[:,:,0]
s_full = image_hsv_full[:,:,1]
v_full = image_hsv_full[:,:,2]
print('hsv_full h : min-max {} {}'.format(image_hsv_full[:,:,0].min(), image_hsv_full[:,:,0].max()))
print('hsv_full s : min-max {} {}'.format(image_hsv_full[:,:,1].min(), image_hsv_full[:,:,1].max()))
print('hsv_full v : min-max {} {}'.format(image_hsv_full[:,:,2].min(), image_hsv_full[:,:,2].max()))
cv2.imwrite(save_path + 'h_full.jpg', h_full)
cv2.imwrite(save_path + 's_full.jpg', s_full)
cv2.imwrite(save_path + 'v_full.jpg', v_full)


image_f32 = (cv2.imread(image_path_1)/255.).astype(np.float32)
image_hsv_f32 = cv2.cvtColor(image_f32, cv2.COLOR_BGR2HSV)
h_f32 = image_hsv_f32[:,:,0]
s_f32 = image_hsv_f32[:,:,1]
v_f32 = image_hsv_f32[:,:,2]
print('hsv_f32 h : min-max {} {}'.format(image_hsv_f32[:,:,0].min(), image_hsv_f32[:,:,0].max()))
print('hsv_f32 s : min-max {} {}'.format(image_hsv_f32[:,:,1].min(), image_hsv_f32[:,:,1].max()))
print('hsv_f32 v : min-max {} {}'.format(image_hsv_f32[:,:,2].min(), image_hsv_f32[:,:,2].max()))
cv2.imwrite(save_path + 'h_f32.jpg', h_f32)
cv2.imwrite(save_path + 's_f32.jpg', s_f32)
cv2.imwrite(save_path + 'v_f32.jpg', v_f32)

'''
hsv h : min-max 0 179
hsv s : min-max 0 188
hsv v : min-max 35 255
hsv_full h : min-max 0 255
hsv_full s : min-max 0 188
hsv_full v : min-max 35 255
hsv_f32 h : min-max 0.0 359.3023376464844
hsv_f32 s : min-max 0.0 0.7368419766426086
hsv_f32 v : min-max 0.13725490868091583 1.0
'''

HLS

HLS 和 HSV 比较类似,这里一起介绍。HLS 也有三个分量,hue(色相)、saturation(饱和度)、lightness(亮度)。

HLS 和 HSV 的区别就是最后一个分量不同,HLS 的是 light(亮度),HSV 的是 value(明度)。可以到这个 网页 尝试一下。

HLS 中的 L 分量为亮度,亮度为100,表示白色,亮度为0,表示黑色;HSV 中的 V 分量为明度,明度为100,表示光谱色,明度为0,表示黑色。

H = [0,180]
L = [0,255]
S = [0,255]
在这里插入图片描述

在这里插入图片描述

import os
import cv2
import numpy as np

image_path_1 = './test.jpg'
save_path = './hls/'
os.makedirs(save_path, exist_ok=True)

image = cv2.imread(image_path_1)
image_hls = cv2.cvtColor(image, cv2.COLOR_BGR2HLS)
h = image_hls[:,:,0]
l = image_hls[:,:,1]
s = image_hls[:,:,2]
print('hls h : min-max {} {}'.format(image_hls[:,:,0].min(), image_hls[:,:,0].max()))
print('hls l : min-max {} {}'.format(image_hls[:,:,1].min(), image_hls[:,:,1].max()))
print('hls s : min-max {} {}'.format(image_hls[:,:,2].min(), image_hls[:,:,2].max()))
cv2.imwrite(save_path + 'h.jpg', h)
cv2.imwrite(save_path + 'l.jpg', l)
cv2.imwrite(save_path + 's.jpg', s)


image_f32 = (cv2.imread(image_path_1)/255.).astype(np.float32)
image_hls_f32 = cv2.cvtColor(image_f32, cv2.COLOR_BGR2HLS)
h_f32 = image_hls_f32[:,:,0]
l_f32 = image_hls_f32[:,:,1]
s_f32 = image_hls_f32[:,:,2]
print('hls_f32 h : min-max {} {}'.format(image_hls_f32[:,:,0].min(), image_hls_f32[:,:,0].max()))
print('hls_f32 l : min-max {} {}'.format(image_hls_f32[:,:,1].min(), image_hls_f32[:,:,1].max()))
print('hls_f32 s : min-max {} {}'.format(image_hls_f32[:,:,2].min(), image_hls_f32[:,:,2].max()))
cv2.imwrite(save_path + 'h_f32.jpg', h_f32)
cv2.imwrite(save_path + 'l_f32.jpg', l_f32)
cv2.imwrite(save_path + 's_f32.jpg', s_f32)

'''
hls h : min-max 0 180
hls l : min-max 31 254
hls s : min-max 0 255
hls_f32 h : min-max 0.0 359.3023376464844
hls_f32 l : min-max 0.1196078509092331 0.9960784316062927
hls_f32 s : min-max 0.0 1.0000030994415283
'''

YCRCB

参考链接:
https://blog.csdn.net/woxincd/article/details/7791956
https://zhuanlan.zhihu.com/p/410688035

这里与yuv一同说明。

YUV模型是根据一个亮度(Y分量)和两个色度(UV分量)来定义颜色空间,在 YUV空间中,每一个颜色有一个亮度信号 Y,和两个色度信号 U 和V。亮度信号是强度的感觉,它和色度信号断开,这样的话强度就可以在不影响颜色的情况下改变。

YCbCr是YUV模型的具体实现,Y表示亮度,色调与饱和度,分别用Cr和Cb来表示。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异,而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之间的差异。

转变后范围,uint8为0-255,float32为0-1。

import os
import cv2
import numpy as np

image_path_1 = './test.jpg'
save_path = './ycrcb/'
os.makedirs(save_path, exist_ok=True)

image = cv2.imread(image_path_1)
image_ycrcb = cv2.cvtColor(image, cv2.COLOR_BGR2YCR_CB)
y = image_ycrcb[:,:,0]
cr = image_ycrcb[:,:,1]
cb = image_ycrcb[:,:,2]
print('ycrcb y : min-max {} {}'.format(image_ycrcb[:,:,0].min(), image_ycrcb[:,:,0].max()))
print('ycrcb cr : min-max {} {}'.format(image_ycrcb[:,:,1].min(), image_ycrcb[:,:,1].max()))
print('ycrcb cb : min-max {} {}'.format(image_ycrcb[:,:,2].min(), image_ycrcb[:,:,2].max()))
cv2.imwrite(save_path + 'y.jpg', y)
cv2.imwrite(save_path + 'cr.jpg', cr)
cv2.imwrite(save_path + 'cb.jpg', cb)


image_f32 = (cv2.imread(image_path_1)/255.).astype(np.float32)
image_ycrcb_f32 = cv2.cvtColor(image_f32, cv2.COLOR_BGR2YCR_CB)
y_f32 = image_ycrcb_f32[:,:,0]
cr_f32 = image_ycrcb_f32[:,:,1]
cb_f32 = image_ycrcb_f32[:,:,2]
print('ycrcb_f32 y : min-max {} {}'.format(image_ycrcb_f32[:,:,0].min(), image_ycrcb_f32[:,:,0].max()))
print('ycrcb_f32 cr : min-max {} {}'.format(image_ycrcb_f32[:,:,1].min(), image_ycrcb_f32[:,:,1].max()))
print('ycrcb_f32 cb : min-max {} {}'.format(image_ycrcb_f32[:,:,2].min(), image_ycrcb_f32[:,:,2].max()))
cv2.imwrite(save_path + 'y_f32.jpg', y_f32)
cv2.imwrite(save_path + 'cr_f32.jpg', cr_f32)
cv2.imwrite(save_path + 'cb_f32.jpg', cb_f32)

'''
ycrcb y : min-max 30 254
ycrcb cr : min-max 93 195
ycrcb cb : min-max 64 176
ycrcb_f32 y : min-max 0.11730196326971054 0.9968039989471436
ycrcb_f32 cr : min-max 0.36231547594070435 0.7620428800582886
ycrcb_f32 cb : min-max 0.2490222454071045 0.6887608766555786
'''

LUV

import os
import cv2
import numpy as np

image_path_1 = './test.jpg'
save_path = './luv/'
os.makedirs(save_path, exist_ok=True)

image = cv2.imread(image_path_1)
image_luv = cv2.cvtColor(image, cv2.COLOR_BGR2LUV)
l = image_luv[:,:,0]
u = image_luv[:,:,1]
v = image_luv[:,:,2]
print('luv l : min-max {} {}'.format(image_luv[:,:,0].min(), image_luv[:,:,0].max()))
print('luv u : min-max {} {}'.format(image_luv[:,:,1].min(), image_luv[:,:,1].max()))
print('luv v : min-max {} {}'.format(image_luv[:,:,2].min(), image_luv[:,:,2].max()))
cv2.imwrite(save_path + 'l.jpg', l)
cv2.imwrite(save_path + 'u.jpg', u)
cv2.imwrite(save_path + 'v.jpg', v)


image_f32 = (cv2.imread(image_path_1)/255.).astype(np.float32)
image_luv_f32 = cv2.cvtColor(image_f32, cv2.COLOR_BGR2LUV)
l_f32 = image_luv_f32[:,:,0]
u_f32 = image_luv_f32[:,:,1]
v_f32 = image_luv_f32[:,:,2]
print('luv_f32 l : min-max {} {}'.format(image_luv_f32[:,:,0].min(), image_luv_f32[:,:,0].max()))
print('luv_f32 u : min-max {} {}'.format(image_luv_f32[:,:,1].min(), image_luv_f32[:,:,1].max()))
print('luv_f32 v : min-max {} {}'.format(image_luv_f32[:,:,2].min(), image_luv_f32[:,:,2].max()))
cv2.imwrite(save_path + 'l_f32.jpg', l_f32)
cv2.imwrite(save_path + 'u_f32.jpg', u_f32)
cv2.imwrite(save_path + 'v_f32.jpg', v_f32)

'''
luv l : min-max 28 254
luv u : min-max 73 168
luv v : min-max 61 212
luv_f32 l : min-max 11.08864974975586 99.70365142822266
luv_f32 u : min-max -32.94413375854492 99.3896713256836
luv_f32 v : min-max -77.67085266113281 77.56366729736328
'''

YUV

import os
import cv2
import numpy as np

image_path_1 = './test.jpg'
save_path = './yuv/'
os.makedirs(save_path, exist_ok=True)

image = cv2.imread(image_path_1)
image_yuv = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)
y = image_yuv[:,:,0]
u = image_yuv[:,:,1]
v = image_yuv[:,:,2]
print('yuv y : min-max {} {}'.format(image_yuv[:,:,0].min(), image_yuv[:,:,0].max()))
print('yuv u : min-max {} {}'.format(image_yuv[:,:,1].min(), image_yuv[:,:,1].max()))
print('yuv v : min-max {} {}'.format(image_yuv[:,:,2].min(), image_yuv[:,:,2].max()))
cv2.imwrite(save_path + 'y.jpg', y)
cv2.imwrite(save_path + 'u.jpg', u)
cv2.imwrite(save_path + 'v.jpg', v)


image_f32 = (cv2.imread(image_path_1)/255.).astype(np.float32)
image_yuv_f32 = cv2.cvtColor(image_f32, cv2.COLOR_BGR2YUV)
y_f32 = image_yuv_f32[:,:,0]
u_f32 = image_yuv_f32[:,:,1]
v_f32 = image_yuv_f32[:,:,2]
print('yuv_f32 y : min-max {} {}'.format(image_yuv_f32[:,:,0].min(), image_yuv_f32[:,:,0].max()))
print('yuv_f32 u : min-max {} {}'.format(image_yuv_f32[:,:,1].min(), image_yuv_f32[:,:,1].max()))
print('yuv_f32 v : min-max {} {}'.format(image_yuv_f32[:,:,2].min(), image_yuv_f32[:,:,2].max()))
cv2.imwrite(save_path + 'y_f32.jpg', y_f32)
cv2.imwrite(save_path + 'u_f32.jpg', u_f32)
cv2.imwrite(save_path + 'v_f32.jpg', v_f32)

'''
yuv y : min-max 30 254
yuv u : min-max 72 170
yuv v : min-max 85 210
yuv_f32 y : min-max 0.11730196326971054 0.9968039989471436
yuv_f32 u : min-max 0.28106194734573364 0.6646637320518494
yuv_f32 v : min-max 0.3306461274623871 0.8223164081573486
'''

LAB

参考链接:
https://blog.51cto.com/u_6263569/5708152
https://baijiahao.baidu.com/s?id=1772014392331617006&wfr=spider&for=pc

Lab是由一个亮度通道(channel)和两个颜色通道组成的。在Lab颜色空间中,每个颜色用L、a、b三个数字表示,各个分量的含义是这样的:

  • L*代表亮度

  • a*代表从绿色到红色的分量

  • b*代表从蓝色到黄色的分量

理论上说,L*、a*、b*都是实数,不过实际一般限定在一个整数范围内:

  • L越大,亮度越高。L为0时代表黑色,为100时代表白色。

  • a和b为0时都代表灰色。

  • a*从负数变到正数,对应颜色从绿色变到红色。

  • b*从负数变到正数,对应颜色从蓝色变到黄色。

Lab相较于RGB更符合人类视觉,也更容易调整:想要调节亮度就调节L通道,想要调节只色彩平衡就分别调a和b。同时a与b的绝对值可以控制饱和度,a、b值混合控制色相(在某个博文中看到,忘了记录是哪个了)。
opencv官方文档
由文档可以看出,转变后L在[0,100]之间,a、b在[-127,127],不过在最后输出为了在[0,255]进行了变换,所以使用cv2输出最大最小值是在0到255之间。

import os
import cv2
import numpy as np

image_path_1 = './test.jpg'
save_path = './lab/'
os.makedirs(save_path, exist_ok=True)


image = cv2.imread(image_path_1)
image_lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
l = image_lab[:,:,0]
a = image_lab[:,:,1]
b = image_lab[:,:,2]
print('lab l : min-max {} {}'.format(image_lab[:,:,0].min(), image_lab[:,:,0].max()))
print('lab a : min-max {} {}'.format(image_lab[:,:,1].min(), image_lab[:,:,1].max()))
print('lab b : min-max {} {}'.format(image_lab[:,:,2].min(), image_lab[:,:,2].max()))
cv2.imwrite(save_path + 'l.jpg', l)
cv2.imwrite(save_path + 'a.jpg', a)
cv2.imwrite(save_path + 'b.jpg', b)


image_f32 = (cv2.imread(image_path_1)/255.).astype(np.float32)
image_lab_f32 = cv2.cvtColor(image_f32, cv2.COLOR_BGR2LAB)
l_f32 = image_lab_f32[:,:,0]
a_f32 = image_lab_f32[:,:,1]
b_f32 = image_lab_f32[:,:,2]
print('lab_f32 l : min-max {} {}'.format(image_lab_f32[:,:,0].min(), image_lab_f32[:,:,0].max()))
print('lab_f32 a : min-max {} {}'.format(image_lab_f32[:,:,1].min(), image_lab_f32[:,:,1].max()))
print('lab_f32 b : min-max {} {}'.format(image_lab_f32[:,:,2].min(), image_lab_f32[:,:,2].max()))
cv2.imwrite(save_path + 'l_f32.jpg', l_f32)
cv2.imwrite(save_path + 'a_f32.jpg', a_f32)
cv2.imwrite(save_path + 'b_f32.jpg', b_f32)
'''
lab l : min-max 28 254
lab a : min-max 96 174
lab b : min-max 76 188
lab_f32 l : min-max 11.077880859375 99.69482421875
lab_f32 a : min-max -32.421875 46.171875
lab_f32 b : min-max -51.59375 60.40625
'''

XYZ

参考链接:
https://zhuanlan.zhihu.com/p/345596900

这个没有仔细研究,看深度学习中基本没用过这个颜色域。

CIE发布此颜色模型为了确定人眼感知颜色的平均状况,在1931年,他们使用三种原色定义了一个数学模型(或者三种刺激值(X(红色),Y(绿色)和Z(蓝色)),从这个模型中可以看到所有的颜色都可以被一个“标准”观察者看到,此数学模型被称为“CIE XYZ模型”。CIE XYZ模型中测量了标准光源下的每一种颜色,以及严格定义了标准观察者所看到的观察条件。
在这里插入图片描述

import os
import cv2
import numpy as np

image_path_1 = './test.jpg'
save_path = './xyz/'
os.makedirs(save_path, exist_ok=True)

image = cv2.imread(image_path_1)
image_xyz = cv2.cvtColor(image, cv2.COLOR_BGR2XYZ)
x = image_xyz[:,:,0]
y = image_xyz[:,:,1]
z = image_xyz[:,:,2]
print('xyz x : min-max {} {}'.format(image_xyz[:,:,0].min(), image_xyz[:,:,0].max()))
print('xyz y : min-max {} {}'.format(image_xyz[:,:,1].min(), image_xyz[:,:,1].max()))
print('xyz z : min-max {} {}'.format(image_xyz[:,:,2].min(), image_xyz[:,:,2].max()))
cv2.imwrite(save_path + 'x.jpg', x)
cv2.imwrite(save_path + 'y.jpg', y)
cv2.imwrite(save_path + 'z.jpg', z)


image_f32 = (cv2.imread(image_path_1)/255.).astype(np.float32)
image_xyz_f32 = cv2.cvtColor(image_f32, cv2.COLOR_BGR2XYZ)
x_f32 = image_xyz_f32[:,:,0]
y_f32 = image_xyz_f32[:,:,1]
z_f32 = image_xyz_f32[:,:,2]
print('xyz_f32 x : min-max {} {}'.format(image_xyz_f32[:,:,0].min(), image_xyz_f32[:,:,0].max()))
print('xyz_f32 y : min-max {} {}'.format(image_xyz_f32[:,:,1].min(), image_xyz_f32[:,:,1].max()))
print('xyz_f32 z : min-max {} {}'.format(image_xyz_f32[:,:,2].min(), image_xyz_f32[:,:,2].max()))
cv2.imwrite(save_path + 'x_f32.jpg', x_f32)
cv2.imwrite(save_path + 'y_f32.jpg', y_f32)
cv2.imwrite(save_path + 'z_f32.jpg', z_f32)

'''
xyz x : min-max 29 242
xyz y : min-max 30 254
xyz z : min-max 37 255
xyz_f32 x : min-max 0.11375140398740768 0.9476515054702759
xyz_f32 y : min-max 0.11598961800336838 0.9966293573379517
xyz_f32 z : min-max 0.14579877257347107 1.0881474018096924
'''
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值