色彩校正中的 gamma 值是什么?

一直听到这个词就是不知道什么意思,也没找到特别好的介绍。
关注者
1,786
被浏览
1,005,470
登录后你可以
不限量看优质回答私信答主深度交流精彩内容一键收藏

Gamma Correction的概念的确比较抽象,但在计算机图形学中非常重要。一般的解释,比方说已有的答案中,往往忽略两个背景知识:人类的视觉特性和古老的 CRT 显示器。在我看过的所有资料中,都没有人提到过,Gamma 的广泛应用很大程度上是因为一个神奇的巧合。

从字面上看,Gamma指的是指数运算中的指数。比方说 A 的2.2次方,Gamma 指的就是2.2这个数字。计算机图形学中颜色值,特别是 RGBA 值都是用0到1的浮点数表示。颜色的 Gamma 矫正本质上就是一系列介于0到1之间的浮点数进行指数运算,通常来说这个数字是2.2。

为什么要进行矫正?为什么是2.2?

从人类的视觉特性说起。人类的视觉系统进化出了一个特性,黑暗环境下的辨识能力要强于明亮环境,这可能有助于我们及时发现黑暗中隐藏的危险。如果有兴趣,可以在计算机上绘制一条从白到黑的渐变条,你会发现明显黑色部分的色阶要多于白色部分。这并不是你的显示器问题(当然也有可能真的是你的显示器太差……),而是因为我们对于暗色的分辨能力远超过亮色。那么在有限的计算机颜色(民用显示器和操作系统中黑色到白色256个色阶)中,亮色和暗色均匀分布的话,那亮色部分就会精度过剩而暗色部分就会精度不足。如何解决这个问题?进行 Gamma 矫正。

上图中的红色虚线就是图像的 Gamma 矫正曲线,一般都是2.2的倒数,0.454545..。观察矫正以后的曲线,原来0到0.5的区间被扩展到了0到~0.73,相应的大于0.5的区间被压缩到只有原来的一半左右。这样通过一次简单的计算,我们达到了不增加数据量的前提下提高可辨识精度(Perceptual precision)的目的。可能从来没有人告诉过你,存储在你硬盘上的图像,都是矫正过的,如下图,中间那个。

当然有人可能会问,矫正以后岂不是丧失了很多亮部的细节,也不合算呀。这个问题取决于存储的数据格式,一般的格式都有足够多的冗余精度,足有保存矫正前后的所有细节,但是对于某些特定的压缩格式,比方说游戏普遍使用的 DXT 压缩格式,精度只有6Bit,也就是64阶,Gamma矫正后很多细节永久丧失了(当然压缩算法也会丢失很多)。

现在我们知道了对图像进行 Gamma 矫正的本质上的原因——因为我们的眼睛。那么为什么是2.2的倒数?

因为老式的 CRT 显示器。

阴极管显示器有一个物理特性——输入值和输出值呈现指数关系,这个指数是2.2。也就是说,当你输入0.5的亮度,在屏幕上得到的不是0.5,而是0.5的2.2次方,约等于0.218。仍旧是这个图:

下面的曲线就是 CRT 显示器的 Gamma 曲线。

当我们在 CRT 显示器上显示一张 Gamma 矫正过的图像,也就是上面的那根曲线,就会获得所期望的线性图像——中间那跟灰色的直线。你看,对图像进行Gamma 矫正即可以获得我们想要的精度,又能在 CRT 显示器上正确显示,这岂不是一个美好的巧合?

事实上我们之所以选择2.2的倒数进行图像矫正,那是为了迎合 CRT 显示器的特性。如果显示器的 Gamma 值不是2.2,那么图像矫正 Gamma 值也需要相应变更,比方说早年的 Mac 操作系统都是使用1.8的 Gamma 值。现代的 LCD 显示器已经不再具有这个特性,但是生产厂商仍旧会加入模拟 Gamma 曲线的硬件功能,也就是说所有显示器都期待软件输出 Gamma 矫正过的图像。

总结一下,所谓 Gamma 矫正就是对颜色进行指数运算。对图像进行矫正是为了获得符合人眼特性的可辨识精度。矫正使用的Gamma 值取决于显示器,现代系统基本上都统一使用2.2。

Gamma 矫正的确是一个隐藏的比较深的问题,别说普通人,长久以来游戏界也一直没有重视。计算机图形学中的算法普遍需要输入值处于线性空间,而读入的图像却都是矫正过的——处于 Gamma 空间。最终得到的计算结果自然也是不正确的。当然游戏图像往往可以通过美术师的人为修改来得到符合期望的图像,但从数学上来说,这是错误的……而且整个行业错了几十年,直到这几年这个问题才被重视起来,产生了所谓了 Gamma Corrected Pipeline。

左侧是一张真实的照片,右侧上方是线性空间(正确)的运算结果,下方是 Gamma 空间(错误)的结果。这种错误的结果我们用了很久……

3D 图像的渲染本质上是对真实世界进行模拟,近几年(特别是2014年)兴起的 Physically Based Rendering 特别强调贴图材质灯光的统一性和物理真实的渲染效果,自然不能容忍在整个系统的底层存在不正确的 Gamma 矫正这样的大乌龙……

要达到这样的实时渲染效果,Gamma 一定要搞对……

希望我这个回答能让读者彻底搞清楚 Gamma Correction 的来龙去脉。如果仍旧有疑惑,请留言。