色彩空间,伽马和图像增强

问题描述 投票:13回答:3

色彩空间。好吧,每个人都知道RGB:在[0.0,1.0]范围内归一化的三个值,它们具有红绿蓝色的强度的含义;这个强度是线性的,不是吗?

伽玛。据我所知,gamma是一种将RGB颜色分量映射到另一个值的函数。谷歌搜索,我已经看到线性函数和非线性函数...线性函数似乎缩放RGB组件,所以它似乎调整图像亮度;非线性函数似乎“解压缩”更暗/更亮的组件。

现在,我开始实现一个图像查看器,它将显示不同的图像格式作为纹理。我想修改这些图像的伽玛,所以我应该建立一个片段着色器并在纹理四边形上运行。很好,但我如何确定正确的伽马校正?

OpenGL使用线性RGB颜色空间,使用浮点组件。实际上,我可以从这些值(具有特殊浮点精度)开始计算伽马校正值,因此在钳制伽马校正值后显示它们。

首先,我将确定伽玛斜坡。我怎么能确定它? (分析或使用查找表)

然后,我开始调查OpenGL扩展EXT_framebuffer_sRGB,这似乎与扩展EXT_texture_sRGB非常相关。

EXT_texture_sRGB引入了一种新的纹理格式,用于将textel值线性化为RGB线性空间。 (脚注1)通过这种方式,我知道sRGB色彩空间并将其用作线性RGB色彩空间。

相反,EXT_framebuffer_sRGB扩展允许我将线性RGB值编码到sRGB帧缓冲区,而不用担心它。

...

等等,所有这些信息是为了什么?如果我可以使用sRGB帧缓冲并加载sRGB纹理,处理纹理而不进行sRGB转换...为什么我应该更正伽玛?

即使在sRGB缓冲区上,也许我可以校正所有相同的伽玛?或者我最好不要?亮度和对比度:它们应在伽玛校正之前还是之后应用?

这是很多信息,我现在感到困惑。希望你们中的某个人能够向我解释所有这些概念!谢谢。

...

还有一个问题。在设备伽玛与“标准”2.2不同的情况下,如何“累积”不同的伽马校正?我不知道是否清楚:如果图像的RGB值已经针对伽玛值为2.2的显示器进行了校正,但显示器的伽马值为2.8,如何校正伽玛?


(1)这里有一些摘要突出我的意思:

sRGB色彩空间基于光线昏暗的办公室中预期的典型(非线性)监视器特性。它已由国际电工委员会(IEC)标准化为IEC 61966-2-1。 sRGB色彩空间大致对应于2.2伽马校正。

此扩展是否提供任何类型的sRGB帧缓冲格式或保证使用sRGB纹理渲染的图像在输出到支持sRGB色彩空间的设备时“看起来不错”?

   RESOLVED:  No.

  Whether the displayed framebuffer is displayed to a monitor that
    faithfully reproduces the sRGB color space is beyond the scope
    of this extension.  This involves the gamma correction and color
    calibration of the physical display device.

    With this extension, artists can author content in an sRGB color
    space and provide that sRGB content for use as texture imagery
    that can be properly converted to linear RGB and filtered as part
    of texturing in a way that preserves the sRGB distribution of
    precision, but that does NOT mean sRGB pixels are output
    to the framebuffer.  Indeed, this extension provides texture
    formats that convert sRGB to linear RGB as part of filtering.

    With programmable shading, an application could perform a
    linear RGB to sRGB conversion just prior to emitting color
    values from the shader.  Even so, OpenGL blending (other than
    simple modulation) will perform linear math operations on values
    stored in a non-linear space which is technically incorrect for
    sRGB-encoded colors.

    One way to think about these sRGB texture formats is that they
    simply provide color components with a distribution of values
    distributed to favor precision towards 0 rather than evenly
    distributing the precision with conventional non-sRGB formats
    such as GL_RGB8.
opengl rgb gamma srgb gamma-distribution
3个回答
8
投票

不幸的是,OpenGL本身并没有定义颜色空间。它只是定义了传递给OpenGL的RGB值形成一个线性向量空间。然后,渲染帧缓冲器的值按原样发送到显示设备。 OpenGL只是传递了值。

Gamma服务有两个目的:

  • 感官知觉是非线性的
  • 在过去,显示设备具有非线性响应

伽马校正用于补偿两者。

该变换只是“线性值V到某个功率Gamma”,即y(v)= v ^ gamma

色彩空间变换涉及从输入值到发送到显示器的完整链,因此这包括伽马校正。这也意味着你不应该自己操纵伽玛匝道。

很长一段时间,典型的Gamma值曾经是2.2。然而,这导致了一些不期望的低值量化,因此Adobe引入了一个新的色彩空间,称为sRGB,其具有用于低值的线性部分和用于较高值的指数为~2.3的幂函数。目前大多数显示设备都使用sRGB。目前大多数图像文件都在sRGB中。

因此,如果您有一个sRGB图像,并在sRGB显示设备上按原样显示,并且设备上配置了线性伽马斜坡(即视频驱动程序gamma = 1),那么只需使用sRGB纹理和帧缓冲即可还要别的吗。

编辑由于评论

总结一下:

如果您的系统不支持sRGB帧缓冲区:


6
投票

等等,所有这些信息是为了什么?如果我可以使用sRGB帧缓冲并加载sRGB纹理,处理纹理而不进行sRGB转换...为什么我应该更正伽玛?

一般来说,你没有。 sRGB纹理和帧缓冲区的目的是让您不必手动进行伽马校正。从sRGB纹理读取转换为线性颜色空间,写入sRGB帧缓冲区采用线性RGB值并将其转换为sRGB值。这是全自动的,更多的是免费的,性能方面的。

您需要进行伽马校正的唯一时间是显示器的伽马值与2.2伽玛的sRGB伽马近似值不匹配。罕见的是这样做的监视器。

您的纹理不必位于sRGB色彩空间中。但是,大多数图像创建应用程序将以sRGB保存图像并使用sRGB中的颜色,因此无论您是否想要它们,大多数纹理都已经在sRGB中。 sRGB纹理功能只是让您实际获得正确的颜色值,而不是您到目前为止所获得的颜色值。

亮度和对比度:它们应在伽玛校正之前还是之后应用?

我不知道你的亮度和对比是什么意思。这应该由显示器设置,而不是您的应用程序。但是,几乎所有想要对图像数据进行的数学运算都应该在线性色彩空间中完成。因此,如果在sRGB色彩空间中给出图像,则需要对其进行线性化,然后才能对其进行任何数学运算。 sRGB纹理功能使其免费,而不必进行复杂的着色器数学运算。


0
投票

RGB

RGB:三个值在[0.0,1.0]范围内归一化,具有红绿蓝色强度的含义;这个强度是线性的,不是吗?

否则RGB值是无意义的数字,除非它们与特定空间/编码的相关性被定义。它们可以是线性,伽马编码或对数编码,或使用复合传递曲线,如Rec709和sRGB规格。

此外,它们与颜色空间中定义的原色和白点相关,因此,例如,sRGB中的#00FF00与DCI-P3中的#00FF00颜色不同。

要定义RGB像素值的显示方式,您不仅需要RGB三元组,还需要知道它所针对的色彩空间,这需要包括主坐标,白点和传递曲线。

sRGB是Web和通用计算的默认“标准”RGB色彩空间。它与Rec709有关,Rec709是HDTV的标准色彩空间。

GAMMA aka TRANSFER CURVE

伽玛。据我所知,gamma是一种将RGB颜色分量映射到另一个值的函数。

图像伽玛利用人类感知的非线性来充分利用每通道8位图像的有限数据大小。人眼对较暗颜色的变化更敏感,因此更多位用于定义伽马编码图像中的较暗颜色。

在数字化之前,还在NTSC广播系统中使用伽马,其抑制信号中的表观噪声,其方式类似于图像伽马防止每通道8比特图像具有“条带”伪像的方式。

首先,我将确定伽玛斜坡。我怎么能确定它? (分析或使用查找表)

伽玛曲线。可以轻松访问sRGB伽玛曲线。这是从sRGB到线性的Wikipedia link。您还可以使用简单使用2.2指数曲线的“简化”方法:

linearVideo = sRGBvideo^2.2和简化的逆,回到sRGB:

sRGBvideo = linearVideo^0.4545

使用简化版本会引入一些轻微的伽马误差,建议使用“正确”曲线进行关键​​操作或图像将多次“往返”。

还有一个问题。在设备伽玛与“标准”2.2不同的情况下,如何“累积”不同的伽马校正?我不知道是否清楚:如果图像的RGB值已经针对伽玛值为2.2的显示器进行了校正,但显示器的伽马值为2.8,如何校正伽玛?

2.8 ???那个显示器是什么?朋友?这是不寻常的 - 虽然PAL规范说,2.8不是“实用”。监视器通常在2.3到2.5左右,具体取决于它们的设置方式。当您调整黑电平和对比度(白色电平)时,您实质上是调整感知的伽玛以匹配观看环境(室内照明)。

仅供参考,虽然sRGB“信号”具有1 / 2.2的编码伽玛,但监视器通常会增加约1.1的指数

对于Rec709,编码信号的有效伽玛值约为1 / 1.9 ish,但参考观察环境中的监视器约为2.4

在这两种情况下都存在有意的系统伽马增益。

如果你想用2.8的显示器对一个图像进行编码而你想要没有系统伽玛增益,那么指数是1 / 2.8

常用的“最高”伽马是用于数字电影(以及Rec2020),在2.6对于那些思考PAL和2.8的人,我鼓励你阅读Poynton的主题:

高度推荐的阅读

Charles Poynton's Gamma FAQ易于阅读,完整地描述了这些问题以及它们在图像管道中的重要性。另请阅读同一链接中的Color FAQ。

A FEW WORDS ON LINEAR vs sRGB

在线性工作空间中处理图像通常是理想的,因为它不仅简化了数学运算,还模拟了现实世界中的光。世界上的光以线性方式(添加剂)工作。但是如果以线性方式工作,则需要足够的位深度,而8位是不够的。

人类感知是非线性的。图像伽马编码利用非线性来充分利用8位图像容器。当你转换为线性你需要更多的比特。每个通道12位被认为是最小值,但16位浮点数是线性工作空间的最小“推荐最佳实践”。

如果在线性渲染环境中使用纹理,则需要将这些纹理转换为线性空间(通常是更深的位深度)。虽然增加的位增加了数据带宽,但简化的数学通常允许更快的计算。

sRGB是一个DISPLAY REFERRED空间,用于显示目的,以及以紧凑的“显示就绪”状态存储图像。黑色为0,白色为255,传输曲线接近1 / 2.2

sRGB基于Rec709(HDTV),使用相同的原色和白点。但转移曲线和数据编码是不同的。 Rec709用于在黑暗的客厅中的较高伽马监视器上显示,并且编码黑色16和白色235。

© www.soinside.com 2019 - 2024. All rights reserved.