目录
前言
整体框图
EOTF-NolinearToLinear
sRGB中的EOTF
BT.1886的EOTF
BT.709
色域
sRGB色域
DCI-P3色域
Display P3色域
Adobe RGB (1998) 色域
BT2020色域
RGB2XYZ
计算公式
代码
仿真结果
颜色空间
LAB颜色空间
JzAzBz颜色空间
ICtCp颜色空间
ICaCb颜色空间
ColorSpaceToLCH
RGB2HSV/L
RGB和HSV互转
RGB与HSL互转
RGB2YUV
参考文献
在图像处理中,经常会遇到各种颜色空间,比如RGB,YUV,Lab,HSV等等,同时,也会涉及到各种色域,比如sRGB色域,DCI-P3,Display P3色域,BT2020色域等等。有时,为了处理图像颜色,更加直观的看颜色,会进行颜色空间转换,从一种颜色空间转到另一种颜色空间,或者是从RGB转到LCH,来看亮度饱和度和色度。
用下面这个图来表示从RGB到LCH的变换过程,从中可以看到,大体上分两类,一类是区分色域空间的,一类是不区分色域空间的。区分色域空间的,即使RGB的数值完全相等,只要对应的色域不一样,得到LCH也会不一样,这一类都是先将RGB转到和人眼比较相似的CIE1931 XYZ空间上,然后再选取某种颜色空间来衡量颜色,当然,不同的颜色空间,其得到的LCH也会不一样。总体来说,这一类是比较准确的,符合人眼特性的。而另一类,不区分色域的,哪怕是不同色域,RGB一样,得到的LCH就一样(实际人眼感知是不一样的),所以这一类是不准确的,不过这一类的计算相对要简单很多,经常一步或者两步就可以了。
下面,分不同模块来介绍。
EOTF主要是将非线性域RGB转到线性域RGB,对应的还有个OETF,就是将线性域转到非线性域,而不同标准下,其转换是不同的,主要介绍以下几种:
在sRGB色域中,有对EOTF应的规定,如下所示:
其反变换OETF为:
由IEC 61966-2-1:1999 (International Electrotechnical Commission, 1999) 发布的,其函数是分段的,使用的是gamma2.4,暗处是线性。
BT.1886中,对EOTF进行如下规定:
基本上就是采用了gamma2.4,LB是屏幕最暗,就是0对应的亮度,Lw是屏幕的最亮,就是1对应的亮度,都是用nit为单位。
BT709中,对OETF的定义如下,也是分段函数,一段是线性,另一段是gamma2.2,和BT1886中和sRGB色域中,都有些不同。
当然,除了上面几种,还有些HDR标准的EOTF定义,比如PQ,HLG等,具体可以参照以下资料。
HDR相关标准-HLG/HDR10/HDR10+/DOLBY VISION_图像算法菜鸟的博客-CSDN博客_hlg和hdr10什么区别
PQ和HLG标准及其转换_图像算法菜鸟的博客-CSDN博客_hlg pq
在业界,有很多种色域标准,sRGB色域,DCI-P3,Display P3色域,BT2020色域,他们都是定义在XYZ空间上,规定RGB三个色坐标和白点色坐标即可。色域色坐标都确定了,那么就可以在线性RGB和XYZ空间进行转换了。主要介绍以下色域:
sRGB的色坐标定义如下:
RGB Primaries:
[[ 0.64 0.33]
[ 0.3 0.6 ]
[ 0.15 0.06]]
Whitepoint: [ 0.3127 0.329 ]
DCI-P3的色坐标定义如下:
RGB Primaries:
[[ 0.68 0.32 ]
[ 0.265 0.69 ]
[ 0.15 0.06 ]]
Whitepoint: [ 0.314 0.351]
Display P3的色坐标定义如下:
RGB Primaries:
[[ 0.68 0.32 ]
[ 0.265 0.69 ]
[ 0.15 0.06 ]]
Whitepoint: [ 0.3127 0.329 ]
和DCI-P3对比,二者的差异是白点色坐标不同,Display P3使用的是D65的白点,而DCI-P3不是
Adobe RGB的色坐标定义如下:
RGB Primaries :
[[ 0.64 0.33]
[ 0.21 0.71]
[ 0.15 0.06]]
Whitepoint : [ 0.3127 0.329 ]
BT2020的色坐标定义如下:
RGB Primaries :
[[ 0.708 0.292]
[ 0.17 0.797]
[ 0.131 0.046]]
Whitepoint: [ 0.3127 0.329 ]
可以使用Python提供的colour库[4]进行画图,得到各个色域的信息和画图,参考代码如下:
import colour
import colour.plotting
if __name__ == '__main__':
srgb = colour.RGB_COLOURSPACES['sRGB']
print('srg :', srgb)
dcip3 = colour.RGB_COLOURSPACES['DCI-P3']
print('dci-p3:', dcip3)
bt2020 = colour.RGB_COLOURSPACES['ITU-R BT.2020']
print('ITU-R BT.2020:', bt2020)
adobe1998 = colour.RGB_COLOURSPACES['adobe1998']
print('adobe1998:', adobe1998)
DisplayP3 = colour.RGB_COLOURSPACES['Display P3']
print('DisplayP3:', DisplayP3)
colour.plotting.plot_RGB_colourspaces_in_chromaticity_diagram_CIE1931(['sRGB', 'ITU-R BT.2020', 'adobe1998',
'DCI-P3', 'Display P3'])
结果图如下:
只要色域的RGB三个色坐标和白点色坐标确定了,就可以得到RGB到XYZ空间的转换矩阵,很多时候,我们都是记住这个矩阵,不过有时,会定义一个不是标准的色域,这个时候就没有对应的转换矩阵了。而实际上,这个转换矩阵是可以通过计算得到的[5],
其实现代码和测试代码如下:
import numpy as np
def XYZToxy(XYZ):
XYZ = XYZ.reshape(-1, 3)
num, _ = XYZ.shape
sumXYZ = np.sum(XYZ, axis=0)
xy = np.zeros((num, 2), np.float)
xy[:, 0] = XYZ[:, 0] / sumXYZ
xy[:, 1] = XYZ[:, 1] / sumXYZ
return xy
def xyToXYZ(xy):
xy = xy.reshape(-1, 2)
num, _ = xy.shape
XYZ = np.zeros((num, 3), np.float)
XYZ[:, 0] = xy[:, 0] / xy[:, 1]
XYZ[:, 1] = 1
XYZ[:, 2] = (1 - xy[:, 0] - xy[:, 1]) / xy[:, 1]
return XYZ
def GetRGBXYZMatrices(xy):
XYZ = xyToXYZ(xy)
# print(XYZ)
matXYZrgb = XYZ[0:3, :].T
XYZw = XYZ[3, :]
Srgb = np.linalg.inv(matXYZrgb) @ XYZw.T
# print(Srgb.shape)
matRGB2XYZ = np.zeros((3, 3), np.float)
matRGB2XYZ[0, 0] = Srgb[0] * matXYZrgb[0, 0]
matRGB2XYZ[0, 1] = Srgb[1] * matXYZrgb[0, 1]
matRGB2XYZ[0, 2] = Srgb[2] * matXYZrgb[0, 2]
matRGB2XYZ[1, 0] = Srgb[0] * matXYZrgb[1, 0]
matRGB2XYZ[1, 1] = Srgb[1] * matXYZrgb[1, 1]
matRGB2XYZ[1, 2] = Srgb[2] * matXYZrgb[1, 2]
matRGB2XYZ[2, 0] = Srgb[0] * matXYZrgb[2, 0]
matRGB2XYZ[2, 1] = Srgb[1] * matXYZrgb[2, 1]
matRGB2XYZ[2, 2] = Srgb[2] * matXYZrgb[2, 2]
matXYZ2RGB = np.linalg.inv(matRGB2XYZ)
print('matRGB2XYZ:', matRGB2XYZ)
print('matXYZ2RGB:', matXYZ2RGB)
return matRGB2XYZ, matXYZ2RGB
if __name__ == '__main__':
xysRGB = np.array([
[0.64, 0.33],
[0.30, 0.60],
[0.15, 0.06],
[0.3127, 0.3290]
])
xyDisplayP3 = np.array([
[0.68, 0.32],
[0.265, 0.69],
[0.15, 0.06],
[0.3127, 0.3290]
])
xyBT2020 = np.array([
[0.708, 0.292],
[0.17, 0.797],
[0.131, 0.046],
[0.3127, 0.3290]
])
xySMPTE_C = np.array([
[0.63, 0.34],
[0.31, 0.595],
[0.155, 0.07],
[0.3127, 0.3290]
])
xyNTSC = np.array([
[0.67, 0.33],
[0.21, 0.71],
[0.14, 0.08],
[0.3101, 0.3162]
])
xyAdobe = np.array([
[0.64, 0.33],
[0.21, 0.71],
[0.15, 0.06],
[0.3127, 0.3290]
])
GetRGBXYZMatrices(xysRGB)
GetRGBXYZMatrices(xyDisplayP3)
GetRGBXYZMatrices(xyAdobe)
代码中计算了三种色域的转换矩阵,分别为
sRGB色域
matRGB2XYZ:
[[ 0.4123908 0.35758434 0.18048079]
[ 0.21263901 0.71516868 0.07219232]
[ 0.01933082 0.11919478 0.95053215]]
matXYZ2RGB:
[[ 3.24096994 -1.53738318 -0.49861076]
[-0.96924364 1.8759675 0.04155506]
[ 0.05563008 -0.20397696 1.05697151]]
Display-P3色域
matRGB2XYZ:
[[ 4.86570949e-01 2.65667693e-01 1.98217285e-01]
[ 2.28974564e-01 6.91738522e-01 7.92869141e-02]
[ -3.97207552e-17 4.51133819e-02 1.04394437e+00]]
matXYZ2RGB:
[[ 2.49349691 -0.93138362 -0.40271078]
[-0.82948897 1.76266406 0.02362469]
[ 0.03584583 -0.07617239 0.95688452]]
Adobe RGB色域
matRGB2XYZ:
[[ 0.57666904 0.18555824 0.18822865]
[ 0.29734498 0.62736357 0.07529146]
[ 0.02703136 0.07068885 0.99133754]]
matXYZ2RGB:
[[ 2.0415879 -0.56500697 -0.34473135]
[-0.96924364 1.8759675 0.04155506]
[ 0.01344428 -0.11836239 1.01517499]]
当转到XYZ以后,一般就会将XYZ再转到各种颜色空间来衡量,最常见的就是CIE的Lab空间,后面还有些其他的颜色空间,比如ICtCp, ICaCb, JzAzBz等等,下面主要介绍以下几种。
XYZ转到LAB的公式如下:
XYZ转到JzAzBz的颜色空间公式如下:
XYZ转到ICtCp颜色空间公式如下:
XYZ转到ICaCb颜色空间公式如下:
当然,还有些其他的颜色空间,比如proLab[9],zICaCb[10]颜色空间等等,这些颜色空间基本上都是考虑颜色的更加均匀性和一致性,和人眼的感知接近,或者是和XYZ直接是线性转换,而不是非线性转换。
当转到各种颜色空间,比如LAB,ICtCp, ICaCb, JzAzBz和YUV或者YCbCr之后,其中L,I,Jz和Y等是亮度,其他两个分量是颜色,但也没有转到饱和度和色度上。以Lab为例,按如下方法计算即可:
RGB转HSV的公式如下,这个颜色空间相对来说,色相和饱和度比较好点,当然均匀性和一致性和LAB,JzAzBz等空间没法比,但亮度V和人眼感知的相差很远,并不能代表真实亮度。
HSV转到RGB的公式如下:
RGB2HSL的公式:
HSL2RGB的公式:
HSL颜色空间的色度和HSV是一样的,亮度分量L比HSV中的亮度分量要好些,但也不是很准确,饱和度S分量不好,均匀性很差,只要RGB里有0或者255,算出来的S就为1,很不连续,和人眼感知相差很远。
RGB转YUV有多种公式,不同标准,其系数不一样,不过都是线性变换,格式类似,只是数值不一样,详细可以参考如下资料。
各种标准下的YUV与RGB间的转换公式_图像算法菜鸟的博客-CSDN博客
[1] Multimedia systems and equipment - Colour measurement and management - Part 2-1: Colour management - Default RGB colour space - sRGB。
IEC 61966-2-1:1999 | IEC Webstore
[2] R-REC-BT.1886-0-201103-I!!PDF-E.pdf
[3] R-REC-BT.709-6-201506-I!!PDF-E.pdf
[4] API Reference — Colour 0.4.1 documentation
[5] Welcome to Bruce Lindbloom's Web Site
[6] CIE 1976 uniform colour spaces
[7] Perceptually uniform color space for image signals including high dynamic range and wide gamut
[8] Encoding High Dynamic Range and Wide Color Gamut Imagery
[9] ProLab: perceptually uniform projective colour coordinate system
[10] investigating performance of uniform color spaces for high dynamic range and wide gamut color difference applications