OpenCV轻松入门_面向python(第四章色彩空间类型转换)
4.1色彩空间基础
色彩空间类型转换是指,将图像从一个色彩空间转换到另外一个色彩空间。
色彩空间也称为颜色空间、彩色空间、颜色模型、彩色系统、彩色模型、色彩模型等。
例如,在使用OpenCV 处理图像时,可能会在 RGB 色彩空间和 HSV 色彩空间之间进行转换。在进行图像的特征提取、距离计算时,往往先将图像从 RGB 色彩空间处理为灰度色彩空间。
GRAY色彩空间
GRAY(灰度图像)通常指 8 位灰度图,其具有 256 个灰度级,像素值的范围是[0,255]。
当图像由 RGB 色彩空间转换为 GRAY 色彩空间时,
标准的转换方式:
Gray=0.299⋅𝑅+0.587⋅𝐺+0.114⋅BGray = 0.299 · 𝑅 + 0.587 · 𝐺 + 0.114 · BGray=0.299⋅R+0.587⋅G+0.114⋅B
简化形式:
Gray=R+G+B3
\text{Gray} = \frac{R + G + B}{3}
Gray=3R+G+B
XYZ色彩空间
XYZ 色彩空间是由 CIE(International Commission on Illumination 定义的,是一种更便于计算的色彩空间,它可以与 RGB 色彩空间相互转换。
将 RGB 色彩空间转换为 XYZ 色彩空间,其转换形式为:
[XYZ]=[0.4124530.3575800.1804230.2126710.7151600.0721690.0193340.1191930.950227]⋅[RGB] \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} = \begin{bmatrix} 0.412453 & 0.357580 & 0.180423 \\ 0.212671 & 0.715160 & 0.072169 \\ 0.019334 & 0.119193 & 0.950227 \end{bmatrix} \cdot \begin{bmatrix} R \\ G \\ B \end{bmatrix} XYZ=0.4124530.2126710.0193340.3575800.7151600.1191930.1804230.0721690.950227⋅RGB
将 XYZ 色彩空间转换为 RGB 色彩空间,其转换形式为:
[RGB]=[3.240479−1.53715−0.498535−0.9692561.8759910.0415560.055648−0.2040431.057311]⋅[XYZ]
\begin{bmatrix}
R \\
G \\
B
\end{bmatrix} =
\begin{bmatrix}
3.240479 & -1.53715 & -0.498535 \\
-0.969256 & 1.875991 & 0.041556 \\
0.055648 & -0.204043 & 1.057311
\end{bmatrix}
\cdot
\begin{bmatrix}
X \\
Y \\
Z
\end{bmatrix}
RGB=3.240479−0.9692560.055648−1.537151.875991−0.204043−0.4985350.0415561.057311⋅XYZ
为什么有负值?:因为RGB色彩空间(如sRGB)的色域(Gamut)无法覆盖所有可见颜色。有些在XYZ空间中存在的颜色,在RGB空间中无法用正值的R、G、B来表示。这些负值在计算过程中是必要的,但在最终显示时,所有RGB分量会被钳制(Clamp) 在0到1(或0到255)的范围内
YCrCb色彩空间
在 YCrCb 色彩空间中,Y 代表光源的亮度,色度信息保存在 Cr 和 Cb 中,其中,Cr 表示红色分量信息,Cb 表示蓝色分量信息。
亮度给出了颜色亮或暗的程度信息,该信息可以通过照明中强度成分的加权和来计算。在RGB 光源中,绿色分量的影响最大,蓝色分量的影响最小。
亮度分量 (Y):
Y=0.299⋅R+0.587⋅G+0.114⋅B
Y = 0.299 \cdot R + 0.587 \cdot G + 0.114 \cdot B
Y=0.299⋅R+0.587⋅G+0.114⋅B
色度分量 (Cr 和 Cb):
Cr=(R−Y)×0.713+deltaCb=(B−Y)×0.564+delta
\begin{aligned}
C_r &= (R - Y) \times 0.713 + {delta} \\
C_b &= (B - Y) \times 0.564 + {delta}
\end{aligned}
CrCb=(R−Y)×0.713+delta=(B−Y)×0.564+delta
式中 delta 的值为:
delta={128,8 位图像32768,16 位图像0.5,单精度图像 \text{delta} = \begin{cases} 128, & 8 \, \text{位图像} \\ 32768, & 16 \, \text{位图像} \\ 0.5, & \text{单精度图像} \end{cases} delta=⎩⎨⎧128,32768,0.5,8位图像16位图像单精度图像
从 YCrCb 色彩空间到 RGB 色彩空间的转换公式为:
R=Y+1.403⋅(Cr−delta)G=Y−0.714⋅(Cr−delta)−0.344⋅(Cb−delta)B=Y+1.773⋅(Cb−delta) \begin{aligned} R &= Y + 1.403 \cdot (Cr - \text{delta}) \\ G &= Y - 0.714 \cdot (Cr - \text{delta}) - 0.344 \cdot (Cb - \text{delta}) \\ B &= Y + 1.773 \cdot (Cb - \text{delta}) \end{aligned} RGB=Y+1.403⋅(Cr−delta)=Y−0.714⋅(Cr−delta)−0.344⋅(Cb−delta)=Y+1.773⋅(Cb−delta)
注意: 式中 delta 的值与上面公式中的 delta 值相同。
HSV色彩空间
RGB 是从硬件的角度提出的颜色模型,在与人眼匹配的过程中可能存在一定的差异,HSV色彩空间是一种面向视觉感知的颜色模型。HSV 色彩空间从心理学和视觉的角度出发,指出人眼的色彩知觉主要包含三要素:色调(Hue,也称为色相)、饱和度 (Saturation)、亮度 (Value),色调指光的颜色,饱和度是指色彩的深浅程度,亮度指人眼感受到的光的明暗程度。
- 色调H:色调与混合光谱中的主要光波长相关,例如“赤橙黄绿青蓝紫”分别表示不同的色调。如果从波长的角度考虑,不同波长的光表现为不同的颜色,实际上它们体现的是色调的差异。
- 饱和度S:指相对纯净度,或一种颜色混合白光的数量。纯谱色是全饱和的,像深红色(红加白)和淡紫色(紫加白)这样的彩色是欠饱和的,饱和度与所加白光的数量成反比。
- 亮度V:反映的是人眼感受到的光的明暗程度,该指标与物体的反射度有关。对于色彩来讲,如果在其中掺入的白色越多,则其亮度越高;如果在其中掺入的黑色越多,则其亮度越低。
将 RGB 色彩空间转换为 HSV 色彩空间的公式:
值 (Value):
V=max(R,G,B)
V = \max(R, G, B)
V=max(R,G,B)
饱和度 (Saturation):
S={V−min(R,G,B)V,V≠00,其他情况
S =
\begin{cases}
\frac{V - \min(R, G, B)}{V}, & V \neq 0 \\
0, & \text{其他情况}
\end{cases}
S={VV−min(R,G,B),0,V=0其他情况
色相 (Hue):
H={60(G−B)V−min(R,G,B),V=R120+60(B−R)V−min(R,G,B),V=G240+60(R−G)V−min(R,G,B),V=B
H =
\begin{cases}
\frac{60(G - B)}{V - \min(R, G, B)}, & V = R \\
120 + \frac{60(B - R)}{V - \min(R, G, B)}, & V = G \\
240 + \frac{60(R - G)}{V - \min(R, G, B)}, & V = B
\end{cases}
H=⎩⎨⎧V−min(R,G,B)60(G−B),120+V−min(R,G,B)60(B−R),240+V−min(R,G,B)60(R−G),V=RV=GV=B
色相修正(处理 H<0H < 0H<0 的情况):
H={H+360,H<0H,其他情况
H =
\begin{cases}
H + 360, & H <0 \\
H, & \text{其他情况}
\end{cases}
H={H+360,H,H<0其他情况
HSV 色彩空间各分量的取值范围:
S∈[0,1]V∈[0,1]H∈[0,360] \begin{aligned} S &\in [0, 1] \\ V &\in [0, 1] \\ H &\in [0, 360] \end{aligned} SVH∈[0,1]∈[0,1]∈[0,360]
HLS色彩空间
HLS 色彩空间包含的三要素是色调 H(Hue)、光亮度/明度 L(Lightness)、饱和(Saturation)。
与 HSV 色彩空间类似,只是 HLS 色彩空间用“光亮度/明度 L(lightness)”替换了“亮度 (Value)”。
- 色调:表示人眼所能感知的颜色,在 HLS 模型中,所有的颜色分布在一个平面的色调环上,整个色调环为 360 度的圆心角,不同的角度代表不同的颜色。
- 光亮度/明度:用来控制色彩的明暗变化,它的取值范围也是[0, 1]。我们通过光亮度/明度的大小来衡量有多少光线从物体表面反射出来。光亮度/明度对于眼睛感知颜色很重要,因为当一个具有色彩的物体处于光线太强或者光线太暗的地方时,眼睛是无法准确感知物体颜色的。
- 饱和度:使用[0, 1]的值描述相同色调、相同光亮度/明度下的色彩纯度变化。饱和度的值越大,表示颜色的纯度越高,颜色越鲜艳;反之,饱和度的值越小,色彩的纯度越低,颜色越暗沉。通常用该属性表示颜色的深浅,比如深绿色、浅绿色。
CIEL*a*b*色彩空间
CIEL*a*b*色彩空间是均匀色彩空间模型,它是面向视觉感知的颜色模型。从视觉感知均匀的角度来讲,人所感知到的两种颜色的区别程度,应该与这两种颜色在色彩空间中的距离成正比。在某个色彩空间中,如果人所观察到的两种颜色的区别程度,与这两种颜色在该色彩空间中对应的点之间的欧式距离成正比,则称该色彩空间为均匀色彩空间。
CIEL*a*b* 色彩空间中的 L分量用于表示像素的亮度,取值范围是[0,100],表示从纯黑到纯白;a*分量表示从红色到绿色的范围,取值范围是[-127,127];b*分量表示从黄色到蓝色的范围,取值范围是[-127,127]。
RGB 转 CIEL*a*b* 色彩空间
由于 CIEL*a*b* 色彩空间是在 CIE 的 XYZ 色彩空间的基础上发展起来的,在具体处理时,需要先将 RGB 转换为 XYZ 色彩空间,再将其转换到 CIEL*a*b* 色彩空间。
RGB → XYZ 转换:
X=XXn,Xn=0.950456
X = \frac{X}{X_n}, \quad X_n = 0.950456
X=XnX,Xn=0.950456
Z=ZZn,Zn=1.088754
Z = \frac{Z}{Z_n}, \quad Z_n = 1.088754
Z=ZnZ,Zn=1.088754
XYZ → CIEL*a*b* 转换
计算 L*
L={116⋅Y13−16,Y>0.008856903.3⋅Y,其他情况 L = \begin{cases} 116 \cdot Y^{\frac{1}{3}} - 16, & Y > 0.008856 \\ 903.3 \cdot Y, & \text{其他情况} \end{cases} L={116⋅Y31−16,903.3⋅Y,Y>0.008856其他情况
计算 a* 和 b*
a=500⋅(f(X)−f(Y))+δ
a = 500 \cdot ( f(X) - f(Y) ) + \delta
a=500⋅(f(X)−f(Y))+δ
b=200⋅(f(Y)−f(Z))+δ
b = 200 \cdot ( f(Y) - f(Z) ) + \delta
b=200⋅(f(Y)−f(Z))+δ
其中:
f(t)={t13,t>0.0088567.787t+16116,其他情况 f(t) = \begin{cases} t^{\frac{1}{3}}, & t > 0.008856 \\ 7.787t + \frac{16}{116}, & \text{其他情况} \end{cases} f(t)={t31,7.787t+11616,t>0.008856其他情况
δ={128,8 位图像0,单精度图像
\delta =
\begin{cases}
128, & \text{8 位图像} \\
0, & \text{单精度图像}
\end{cases}
δ={128,0,8 位图像单精度图像
数值范围
L∈[0,100]
L \in [0,100]
L∈[0,100]
a∈[−127,127]
a \in [-127,127]
a∈[−127,127]
b∈[−127,127]
b \in [-127,127]
b∈[−127,127]
CIEL*u*v*色彩空间
CIEL*u*v*色彩空间同 CIEL*a*b*色彩空间一样,都是均匀的颜色模型。CIEL*u*v*色彩空间与设备无关,适用于显示器显示和根据加色原理进行组合的场合,该模型中比较强调对红色的表示,即对红色的变化比较敏感,但对蓝色的变化不太敏感。
从 RGB 色彩空间到 XYZ 色彩空间的转换:
[XYZ]=[0.4124530.3575800.1804230.2126710.7151600.0721690.0193340.1191930.950227]⋅[RGB]
\begin{bmatrix}
X \\
Y \\
Z
\end{bmatrix} =
\begin{bmatrix}
0.412453 & 0.357580 & 0.180423 \\
0.212671 & 0.715160 & 0.072169 \\
0.019334 & 0.119193 & 0.950227
\end{bmatrix}
\cdot
\begin{bmatrix}
R \\
G \\
B
\end{bmatrix}
XYZ=0.4124530.2126710.0193340.3575800.7151600.1191930.1804230.0721690.950227⋅RGB
从 XYZ 色彩空间到 CIEL*u*v* 色彩空间的转换:
L={116⋅Y13−16,Y>0.008856903.3⋅Y,其他情况 L = \begin{cases} 116 \cdot Y^{\frac{1}{3}} - 16, & Y > 0.008856 \\ 903.3 \cdot Y, & \text{其他情况} \end{cases} L={116⋅Y31−16,903.3⋅Y,Y>0.008856其他情况
u′=4XX+15Y+3Z u' = \frac{4X}{X + 15Y + 3Z} u′=X+15Y+3Z4X
v′=9YX+15Y+3Z v' = \frac{9Y}{X + 15Y + 3Z} v′=X+15Y+3Z9Y
u=13⋅L⋅(u′−un),un=0.19793943 u = 13 \cdot L \cdot (u' - u_n), \quad u_n = 0.19793943 u=13⋅L⋅(u′−un),un=0.19793943
v=13⋅L⋅(v′−vn),vn=0.46831096
v = 13 \cdot L \cdot (v' - v_n), \quad v_n = 0.46831096
v=13⋅L⋅(v′−vn),vn=0.46831096
所得结果中各个值的取值范围分别为:
- L∈[0,100]L \in [0,100]L∈[0,100]
- u∈[−134,220]u \in [-134,220]u∈[−134,220]
- v∈[−140,122]v \in [-140,122]v∈[−140,122]
Bayer色彩空间
Bayer 色彩空间(Bayer 模型)被广泛地应用在 CCD 和 CMOS 相机中。它能够从单平面 R、G、B 交错表内获取彩色图像。
输出的 RGB 图像的像素点值,是根据当前点的 1 个、2 个或 4 个邻域像素点的相同颜色的像素值获得的。上述模式能够通过移动一个左边的像素或者上方的像素来完成修改。
色彩空间 | 特点 | 典型应用场景(具体) |
---|---|---|
GRAY 灰度 | 单通道,仅含亮度信息,无颜色 | - 人脸检测(Haar、LBP 特征基于灰度) - OCR(字符识别前先转灰度) - 医学影像(X 光片、CT 图像) - 边缘检测(Sobel、Canny 算子常用灰度图) |
CIE XYZ | CIE 标准表色系统,线性空间,与设备无关 | - 作为 Lab/Luv 等感知均匀色彩空间的中间空间 - 打印机、扫描仪、显示器的 ICC 颜色管理 - 科学测量与颜色匹配(光源光谱分析) |
YCrCb | 分离亮度与色度,源自视频编码 | - 数字电视信号传输(PAL、NTSC、HDTV) - 视频压缩(JPEG 图像压缩、H.264 视频编码) - 基于肤色的人脸检测(Cr-Cb 色度空间分割) |
HSV | 基于人眼感知:色相(H)、饱和度(S)、明度(V) | - 工业中基于颜色的物体检测(如流水线产品分拣) - 图像分割(检测红灯、绿植、目标衣物颜色) - Photoshop/美图软件的颜色选择器 |
HLS | 与 HSV 类似,用亮度(Lightness)代替明度(Value) | - UI 设计和网页前端配色(HLS 更利于生成色彩渐变) - 亮度增强、图像美化(调整 Lightness 提升清晰度) - 游戏渲染中用于控制光照与颜色效果 |
CIEL*a*b* | 感知均匀色彩空间,设备无关 | - ΔE 颜色差异计算(油漆厂、纺织品、印刷行业对比标准色卡) - 照片修图中的色彩校正(如 Lightroom) - 食品工业检测(检测水果成熟度、咖啡烘焙程度) |
CIEL*u*v* | 与 CIEL*a*b* 类似,更适合显示器色彩计算 | - 显示器/投影仪色彩校准(Display Calibration) - 光源一致性检测(确保 LED 灯、汽车车灯颜色一致) - 航空航天、军工中对夜视显示设备的色彩测试 |
Bayer | 原始图像传感器格式,每像素仅记录 R/G/B 一种颜色 | - 数码相机/单反相机 RAW 图像存储 - 手机摄像头传感器数据获取 - 工业相机(零件检测、自动化视觉) - 天文摄影(天文望远镜拍摄 RAW,后期 Demosaicing 处理) |
4.2类型转换函数
在 OpenCV 内,我们使用 cv2.cvtColor()函数实现色彩空间的变换。该函数能够实现多个色彩空间之间的转换。其语法格式为:
dst = cv2.cvtColor( src, code [, dstCn] )
- dst 表示输出图像,与原始输入图像具有同样的数据类型和深度。
- src 表示原始输入图像。可以是 8 位无符号图像、16 位无符号图像,或者单精度浮点数等。
- code 是色彩空间转换码。
- dstCn 是目标图像的通道数。如果参数为默认的 0,则通道数自动通过原始输入图像和code 得到。
4.3类型转换实例
通过数组观察转换效果
通过函数 cv2.cvtColor()对图像 img 进行色彩空间的转换,并使用公式计算的方式对其中的像素点进行计算。
import cv2
import numpy as np
img = np.random.randint(0,256,size=[2,4,3],dtype=np.uint8)
rst = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print("img = \n",img)
print("rst = \n",rst)
print("像素点(1,0)直接计算得到的值=",
img[1,0,0]*0.114+img[1,0,1]*0.587+img[1,0,2]*0.299)
print("像素点(1,0)使用公式 cv2.cvtColor()转换值=",rst[1,0])
将灰度图像转换为 BGR 图像。
import cv2
import numpy as np
img = np.random.randint(0,256,size=[2,4],dtype=np.uint8)
rst = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
print("img=\n",img)
print("rst=\n",rst)
将图像在 BGR 和 RGB 模式之间相互转换。
import cv2
import numpy as np
img = np.random.randint(0,256,size = [2,4,3],dtype=np.uint8)
rgb=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
bgr=cv2.cvtColor(rgb,cv2.COLOR_RGB2BGR)
print("img=\n",img)
print("rgb=\n",rgb)
print("bgr=\n",bgr)
图像处理实例
将图像在 BGR 模式和灰度图像之间相互转换。
import cv2
lena=cv2.imread("lena.jpg")
gray=cv2.cvtColor(lena,cv2.COLOR_BGR2GRAY)
rgb=cv2.cvtColor(gray,cv2.COLOR_GRAY2BGR)
#==========打印 shape============print("lena.shape=",lena.shape)
print("gray.shape=",gray.shape)
print("rgb.shape=",rgb.shape)
#==========显示效果============
cv2.imshow("lena",lena)
cv2.imshow("gray",gray)
cv2.imshow("rgb",rgb)
cv2.waitKey()
cv2.destroyAllWindows()
将图像从 BGR 模式转换为 RGB 模式。
import cv2
lena = cv2.imread("D:\openCV\lena.jpg")
rgb = cv2.cvtColor(lena,cv2.COLOR_BGR2RGB)
cv2.imshow("lena",lena)
cv2.imshow("rgb",rgb)
cv2.waitKey()
cv2.destroyAllWindows()
4.4 alpha通道
在 RGB 色彩空间三个通道的基础上,还可以加上一个 A 通道,也叫 alpha通道,表示透明度。<这种 4 个通道的色彩空间被称为 RGBA 色彩空间,PNG 图像是一种典型的 4 通道图像。>alpha 通道的赋值范围是[0,1][0, 1][0,1],或者[0,255][0, 255][0,255],表示从透明到不透明。
分析alpha通道的值
import cv2
import numpy as np
img = np.random.randint(0,256,size = [2,3,3],dtype = np.uint8)
bgra = cv2.cvtColor(img,cv2.COLOR_BGR2BGRA)
print("img= \n",img)
print("bgra= \n",bgra)
b,g,r,a=cv2.split(bgra)
print("a=\n",a)
a[:,:]=125
bgra=cv2.merge([b,g,r,a])
print("bgra=\n",bgra)
处理图像的alpha通道
import cv2
img = cv2.imread("lena.jpg")
bgra = cv2.cvtColor(img,cv2.COLOR_BGR2BGRA)
b,g,r,a = cv2.split(bgra)
a[:,:]=125
bgra125=cv2.merge([b,g,r,a])
a[:,:]=0
bgra0=cv2.merge([b,g,r,a])
cv2.imshow("img",img)
cv2.imshow("bgra",bgra)
cv2.imshow("bgra125",bgra125)
cv2.imshow("bgra0",bgra0)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite("bgra.png",bgra)
cv2.imwrite("bgra125.png",bgra125)
cv2.imwrite("bgra0.png",bgra0)
- 图(a)是原始图像 lena。
- 图(b)是由原始图像 lena 通过色彩空间转换得到的图像 bgra,该图像内 alpha 通道的值是默认值 255。
- 图©是将图像 bgra 中 alpha 通道值设置为 0 得到的。
- 图(d)是将图像 bgra 中 alpha 通道值设置为 125 得到的。
- 图(a)是保存的图像 bgra,该图像由原始图像 lena 通过色彩空间转换得到,该图像内 alpha通道的值是默认值 255。
- 图(b)是保存的图像 bgra125,该图像是将图像 bgra 中 alpha 通道值设置为 125 得到的。
- 图©是保存的图像 bgra0,该图像是将图像 bgra 中 alpha 通道值设置为 0 得到的。需要注意,在图像 bgra0 处于预览模式时,看起来可能是一幅黑色的图像,将其打开后就会看到它实际上是纯色透明的。