我有一些问题无法完全了解 Gamma 校正的必要性。我希望你们能帮助我。

假设我们要显示256个相邻像素。这些像素应该是从黑色到白色的平滑渐变。为了表示它们的颜色,我们使用了0..255.中的线性灰度值。由于人眼的非线性,监视器不能仅将这些值转换为线性亮度值。如果相邻像素的亮度值为(1/256)*I_max, (2/256)*I_max, et cetera,我们将在较暗的区域中感知到两个像素之间的亮度差异过大(渐变将不平滑)。

幸运的是,监视器具有与人眼相对的非线性。这意味着,如果我们将线性灰度值0..255放入帧缓冲区,则监视器会将它们转换为非线性亮度值x ^ gamma。但是,由于我们的眼睛是非线性的,因此我们可以感觉到平滑的线性渐变。监视器的非线性和我们的一只眼睛相互抵消。

那么,为什么我们需要 Gamma 校正?我读过一些书,我们一直希望监视器产生线性亮度值。根据它们,监视器的非线性必须在将灰度值写入帧缓冲器之前得到补偿。这是通过 Gamma 校正完成的。但是,我的问题是,据我所知,当监视器产生线性亮度值时,我们不会感知线性亮度值(即,我们不会感知到平滑,稳定的梯度)。

据我所知,如果将线性灰度值放入帧缓冲区,那将是完美的。监视器将这些值转换为非线性亮度值,并且我们的眼睛再次感知到线性亮度值,因为眼睛是互为非线性的。无需 Gamma 校正帧缓冲区中的灰度值,也无需强制监视器产生线性亮度值。

我看这些东西的方式有什么问题?
谢谢

最佳答案

请允许我“复活”这个问题,因为我现在正在努力解决类似的问题,并且我认为我已经找到了答案-它可能对其他人有用。否则我可能错了,有人可以告诉我:)

我认为您的思维方式没有错。事实是,如果您知道自己在做什么,就不需要一直进行 Gamma 校正。这取决于您要实现的目标。我们来看两种不同的情况。

A)灯光模拟(又称渲染)。您有一个漫反射的表面,灯光指向它。然后,光的强度加倍。

出色地。让我们看看在这种情况下在现实世界中会发生什么。假设表面是纯漫射面,则反射光的强度将是表面的反照率乘以入射光强度以及入射光角度和法线的余弦。任何。问题是,当入射光强度加倍时,反射光强度也将加倍。这就是为什么光传输被认为是线性过程的原因。有趣的是,您不会感知到表面亮度是它的两倍,因为我们的感知是非线性的(这是由所谓的史蒂文幂定律建模的)。再说一遍:在现实世界中,反射光增加了一倍,但您不会感觉到两倍的亮度。

现在,我们将如何模拟呢?好吧,如果我们有一个具有表面反照率的sRGB纹理,则需要对其进行线性化(通过对其进行校正,这意味着应用2.2 Gamma )。现在它是线性的,并且具有光强度,我们可以使用我之前说的公式来计算反射光强度。由于我们处在线性空间中,因此通过将强度加倍,我们将使输出翻倍,就像在现实世界中一样。现在,我们对结果进行 Gamma 校正。因此,当屏幕显示渲染的图像时,它将应用 Gamma 值,因此它将具有线性响应,这意味着当我们模拟两倍于屏幕时,屏幕发出的光的强度将是屏幕的两倍。柔和的光线比我们模拟第一个光线时强。因此,从屏幕到达您的眼睛的光的强度将增加一倍。就像您在真实的表面上看到有真实的光线影响它的情况一样。您当然不会感觉到第二个渲染的亮度是原来的两倍,但是正如我们之前所说,这恰恰是真实情况下的效果。在现实世界和模拟中,行为相同意味着模拟(渲染)是正确的:)

B)另一种情况恰好是您想要一个“线性化”(“被感知”为“线性”)渐变。

由于您希望屏幕的非线性响应抵消我们的非线性视觉感知,因此可以完全跳过 Gamma 校正(如您建议)。或者,更准确地说,请继续在线性空间中进行操作并进行 Gamma 校正,但要创建渐变时,不要使用会被非线性感知的像素(1,2,3 ... 255)的连续值(因为史蒂文的),而要使用连续值由我们的感知亮度响应的倒数转换(即,对标准化值应用1/0.5 = 2的指数。这是对亮度使用史蒂文指数的倒数)。

实际上,如果您看到经过ammat校正的线性渐变(例如http://scanline.ca/gradients/中的渐变),则根本不会认为它是线性的:与预期的相比,较低强度的变化远大于较高强度的变化。

好吧,至少这是我目前对该主题的理解。我希望它能对任何人有帮助。再一次,请,请,如果是错的,如果有人能指出我的话,我将不胜感激。

关于image-processing - Gamma 校正到底需要什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12975688/

10-16 03:36