0%

我们必须知道的光与色彩

这篇文章我们来聊聊光与色彩。

我们之所以能够看到这缤纷的世界,能够看到各式各样的物体,能够看到美丽的图画都要归功于

照射到物体后,物体会将一部分光反射到我们的眼睛里,而我们的眼睛会从中提取必要的信息传给大脑,这样在我们的大脑中就会“构造”出一幅图像,而这幅图像就是我们看到的景像了。这就是我们通过人眼能看到物体的真正原因。

实际上,无论是声音、紫外线还是光,它们都是一种电磁波。对于光而言,光传播的频率决定了光的颜色,频率越高颜色越靠近紫色,而光传播时的振幅决定了光的亮度,振幅越大亮度越高。

其实,我们人眼可见光的频谱是非常窄的,如下图所示。

在$10^6$到$10^{19}$这么大范围内的电磁波中,只有$10^{14}$到$10^{15}$范围内的一小部分才是人眼可见的。因此,俗话中所说的“眼见为实”并不靠谱!

1966年,牛顿通过三棱镜发现白光是由多种颜色光混合而成的。根据这个原理,人们进一步发现只需要RGB(红色、绿色、蓝色)三种颜色就可以组合出人眼可以看到的各种颜色的光。并且在RGB三色光中,人眼对绿色最为敏感,其次是红色,最后是蓝色。

后来人们根据用途不同构建了好几种色彩空间,如用于显示设备的RGB色彩空间;用于打印设备的CMYK色彩空间;用于电视和视频压缩的YUV色彩空间;绘画使用的HSV色彩空间以及描述人眼的HSL色彩空间。这些色彩空间有大有小,而且由于用途不同,还会有一些色差。

对于视频渲染来说,用的最多的是RGB和YUV。由于经常需要进行两种色彩空间的转换,所以我们必须熟悉这两格色彩空间的区别和数据格式。

RGB与YUV

如我们上面所述,屏幕使用的是RGB方式显示图像,即通过三元色(红、绿、蓝)组合成各种颜色。屏幕上的每个像素点都是由R、G、B三个发光二极管构成的。当R、G、B全部点亮时为白色,全灭时为黑色。这样当我们在屏幕上显示信息时,只要控制每个像素点中R、G、B发光二极管的明暗程度就可以显示出我们想要的效果了。

而YUV是彩色电视使用的。其中Y分量用于控制明暗程度,UV分量用于控制颜色。之所以电视使用YUV方式显示图像,是因为在彩色电视之前大家使用的是黑白电视。而黑白电视只需要Y分量,当彩色电视出现之后,为了兼容黑白电视,因此才会出现YUV格式,这样无论是彩色电视下是黑白电视我们给它传输YUV数据时,它们都可以正常工作。

对于YUV来说,有三个重要的标准,分别是BT.601、BT.709和BT.2020。这三个标准分别代表三种不同的YUV色彩空间,其中BT.601是标清色彩空间,BT.709是高清色彩空间,而BT.2020是超高清色彩空间。针对于不同的色彩空间,RGB与YUV互转时使用的公式也是不同的。

BT.601与RGB互转公式如下:

$$
\begin{bmatrix}
Y \
U \
V
\end{bmatrix}
=\begin{bmatrix}
0.299 & 0.587 & 0.114 \
-0.14713 & -0.28886 & 0.436 \
0.615 & -0.51499 & -0.10001
\end{bmatrix}
\begin{bmatrix}
R \
G \
B
\end{bmatrix}
$$

$$
\begin{bmatrix}
R \
G \
B
\end{bmatrix}
=\begin{bmatrix}
1.0 & 0.0 & 1.13983 \
1.0 & -0.39465 & -0.58060 \
1.0 & 2.03211 & 0.0
\end{bmatrix}
\begin{bmatrix}
Y \
U \
V
\end{bmatrix}
$$

BT.709与RGB互转公式如下:
$$
\begin{bmatrix}
Y \
U \
V
\end{bmatrix}
=\begin{bmatrix}
0.2126 & 0.7152 & 0.0722 \
-0.09991 & -0.33609 & 0.436 \
0.615 & -0.55861 & -0.05639
\end{bmatrix}
\begin{bmatrix}
R \
G \
B
\end{bmatrix}
$$

$$
\begin{bmatrix}
R \
G \
B
\end{bmatrix}
=\begin{bmatrix}
1.0 & 0.0 & 1.28033 \
1.0 & -0.21482 & -0.38059 \
1.0 & 2.12798 & 0.0
\end{bmatrix}
\begin{bmatrix}
Y \
U \
V
\end{bmatrix}
$$

BT.2020与RGB互转公式如下:
$$
\begin{bmatrix}
Y \
U \
V
\end{bmatrix}
=\begin{bmatrix}
0.2627 & 0.6780 & 0.0593 \
-0.1396 & -0.3604 & 0.5 \
0.5 & -0.4598 & -0.0402
\end{bmatrix}
\begin{bmatrix}
R \
G \
B
\end{bmatrix}
$$

$$
\begin{bmatrix}
R \
G \
B
\end{bmatrix}
=\begin{bmatrix}
1.0000 & 0.0000 & 1.47460 \
1.0000 & -0.16455 & -0.57135 \
1.0000 & 1.88140 & 0.00000
\end{bmatrix}
\begin{bmatrix}
Y \
U \
V
\end{bmatrix}
$$

小结

通过这篇文章我们应该知道光也是一种电磁波,而且可见光在整个电磁波范围内占比非常小。我们可以使用三元色的不同组合构造出各种颜色,这就是RGB。RGB通常应用于屏幕,因此我们在进行渲染时,就需要先将图像转成RGB,然后才能将其渲染到屏幕上。

另外,视频图像使用的是YUV格式而不是RGB。如果我们想将YUV格式的数据渲染到屏幕上,那么首先需要将其转成RGB,然后才能渲染到屏幕上。当然对于OpenGL来说,其内部已经提供了YUV转RGB的方法,因此在进行YUV到RGB转换时,不需要我们自己实现,调用OpenGL提供的方法即可。

另一方面,有时我们也需要将屏幕上渲染的图像保存成MP4、JPEG等格式,此时需要将RGB转成YUV,才能交给编码器。同样我们也不需要知道YUV与RGB之间具体该如何互换,唯一需要清楚的是,编码器要的是YUV而不是RGB。

参考资料

系统玩转OpenGL+AI,实现各种酷炫视频特效

欢迎关注我的其它发布渠道