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

问题描述

| 色彩空间。好吧,每个人都知道RGB:在[0.0,1.0]范围内归一化的三个值,它们具有颜色成分的强度Red Green Blue的含义;这个强度是线性的,不是吗? 伽玛据我了解,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转换的情况下处理该纹理...为什么我应该校正gamma? 也许即使在sRGB缓冲区上,我也可以全部校正伽玛吗?还是我最好不要?亮度和对比度:应在伽玛校正之前还是之后应用? 这是很多信息,我现在很困惑。希望你们中的每个人都能向我解释所有这些概念!谢谢。 ... 还有另一个问题。如果设备的灰度系数与“标准” 2.2不同,如何“累积”不同的灰度系数校正?我不知道是否很清楚:如果伽玛值为2.2的显示器的图像RGB值已经被校正,但是显示器的伽玛值为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本身并没有定义色彩空间。刚刚定义传递给OpenGL的RGB值形成线性向量空间。然后,将渲染的帧缓冲区的值按原样发送到显示设备。 OpenGL只是通过该值。 Gamma服务有两个目的: 感觉感知是非线性的 在过去,显示设备具有非线性响应 伽马校正用于补偿这两种情况。 变换只是“线性值V到某个幂Gamma”,即y(v)= v ^ gamma 色彩空间转换涉及从输入值到发送到显示器的内容的完整链,因此包括伽玛校正。这也意味着您不应该自己操纵伽玛斜率。 长期以来,典型的Gamma值曾经是2.2。但是,这导致了一些不希望的低值量化,因此Adobe引入了一种新的色彩空间,称为sRGB,它具有低值的线性部分和幂函数,高值的指数函数约为2.3。如今,大多数显示设备都使用sRGB。同样,这些天大多数图像文件都在sRGB中。 因此,如果您有sRGB图像,并在sRGB显示设备上按原样显示它,并且该设备上配置了线性伽玛斜率(即视频驱动器gamma = 1),则只需使用sRGB纹理和帧缓冲即可,做其他事情。 由于评论而编辑 总结一下: 使用ARB_framebuffer_sRGB帧缓冲区,以便驱动程序http://www.opengl.org/registry/specs/ARB/framebuffer_sRGB.txt对线性OpenGL处理​​的结果进行正确的颜色转换。 将所有颜色输入线性化到OpenGL sRGB颜色空间中的纹理应通过EXT_texture_sRGB http://www.opengl.org/registry/specs/EXT/texture_sRGB.txt传递 不要对输出值进行伽马校正(sRGB格式的帧缓冲区将负责此操作) 如果您的系统不支持sRGB帧缓冲区: 在显示设备上设置线性色带。 Windows http://msdn.microsoft.com/zh-CN/library/ms536529(v=vs.85).aspx 可以通过xgamma http://www.xfree86.org/current/xgamma.1.html完成X11 创建(线性)帧缓冲对象,以在帧缓冲对象中进行线性渲染。为了适当地进行混合,FBO的使用仅在线性色彩空间中有效。 使用应用所需颜色(伽玛及其他)校正的片段着色器将最终的渲染结果从FBO绘制到窗口。     ,           等待,所有这些信息有什么用?如果我可以使用sRGB帧缓冲区并加载sRGB纹理,请在不进行sRGB转换的情况下处理该纹理...为什么我应该校正gamma? 通常,您不需要。 sRGB纹理和帧缓冲区的目的是使您不必手动进行伽玛校正。从sRGB纹理读取的内容将转换为线性色彩空间,而对sRGB帧缓冲区的写入将获取线性RGB值并将其转换为sRGB值。这是完全自动的,并且在性能方面更是如此。 唯一需要进行伽玛校正的时间是,如果显示器的伽玛与sRGB伽玛近似值2.2伽玛不匹配。执行此操作的监视器很少。 您的纹理不必在sRGB色彩空间中。但是,大多数图像创建应用程序会将图像保存为sRGB并可以使用sRGB中的颜色,因此很可能您的大多数纹理都已经在sRGB中,无论您是否希望使用它们。 sRGB纹理功能仅允许您实际获取正确的颜色值,而不是您到目前为止一直在获取的颜色值。   亮度和对比度:应在伽玛校正之前还是之后应用? 我不知道您所说的亮度和对比度。这应该由监视器而不是您的应用程序来设置。但是实际上,您要对图像数据进行的所有数学运算都应该在线性色彩空间中完成。因此,如果为您提供sRGB色彩空间中的图像,则需要对其进行线性处理,然后才能对其进行任何数学运算。 sRGB纹理功能使此功能免费,而不必进行复杂的着色器数学运算。     ,RGB   RGB:在[0.0,1.0]范围内归一化的三个值,其含义是颜色分量的强度Red Green Blue;这个强度是线性的,不是吗? 除非定义了它们与特定空间/编码的相关性,否则RGB值是无意义的数字。它们可以是线性的,伽马编码的或对数编码的,或使用诸如Rec709和sRGB规格的复合传输曲线。 同样,它们相对于色彩空间中定义的原色和白点,因此,例如,sRGB中的#00FF00与DCI-P3中的#00FF00是不同的颜色。 要定义应如何显示RGB像素值,不仅需要RGB三元组,还需要知道其预期的色彩空间,其中需要包括主坐标,白点和传输曲线。 sRGB是Web和通用计算的默认“标准” RGB色彩空间。它与Rec709有关,后者是HDTV的标准色彩空间。 GAMMA aka转移曲线   伽玛据我了解,gamma是将RGB颜色分量映射到另一个值的函数。 图像伽玛利用人类感知的非线性优势,以充分利用每通道图像8位的有限数据大小。人眼对较暗颜色的变化更敏感,因此更多位用于定义伽玛编码图像中的较暗颜色。 在数字化之前,伽玛技术还被用于NTSC广播系统中,该系统可以抑制信号中的视在噪声,其方式类似于图像伽玛技术如何防止每通道8位图像具有“带状”伪像。   首先,我将确定伽玛斜率。我如何确定呢? (从语法上或使用查找表) 伽玛曲线。 sRGB伽玛曲线很容易访问。这是从sRGB到线性的Wikipedia链接。您也可以使用“简化”方法,该方法仅使用2.2指数曲线:
linearVideo = sRGBvideo^2.2
和简化的逆,回到sRGB:
sRGBvideo = linearVideo^0.4545
使用简化版会引入一些较小的伽玛误差,建议对关键操作使用“正确”曲线,或者在多次“往返”的情况下使用图像。   还有另一个问题。如果设备的灰度系数与“标准” 2.2不同,如何“累积”不同的灰度系数校正?我不知道是否很清楚:如果伽玛值为2.2的显示器的图像RGB值已经被校正,但是显示器的伽玛值为2.8,如何校正伽玛值? 2.8 ???那是什么显示器?朋友?这是不寻常的-尽管PAL规范指出2.8并非“实用”。显示器的设置通常在2.3到2.5之间。当您调整黑电平和对比度(白电平)时,本质上是在调整可感知的伽玛值以匹配观看环境(室内照明)。 仅供参考,虽然sRGB \“ signal \”的编码伽玛值为1 / 2.2,但监视器通常会添加约1.1的指数 对于Rec709,编码信号的有效伽玛值约为1 / 1.9 ish,但参考观看环境中的监视器约为2.4 在这两种情况下,都有一个故意的系统伽马增益。 如果要使用伽玛编码的图像以显示2.8,而又不希望使用系统伽玛增益,则指数为1 / 2.8 普遍使用的“最高”伽玛值适用于数字电影(2.6版),对于2.6版的人来说,我建议您阅读有关此主题的Poynton: 强烈推荐阅读 查尔斯·波因顿(Charles Poynton)的“伽玛常见问题解答”(Gamma FAQ)易于阅读,并完整描述了这些问题以及它们在图像处理中的重要性。另请在同一链接上阅读他的颜色常见问题解答。 线性与sRGB上的几个字 在线性工作空间中处理图像通常是理想的选择,因为它不仅可以简化数学运算,而且可以模拟现实世界中的光线。世界上的光以线性方式(累加)工作。但是,如果以线性方式工作,则需要足够的位深度,而8位是不够的。 人类的感知是非线性的。图像伽玛编码利用非线性优势来充分利用8位图像容器。当您转换为线性时,您需要更多位。每个通道12位被认为是最小值,但是对于线性工作空间,最低16位浮点数是“推荐的最佳实践”。 如果在线性渲染环境中使用纹理,则需要将那些纹理转换为线性空间(通常是更深的位深度)。尽管增加的位增加了数据带宽,但简化的数学运算通常可以加快计算速度。 sRGB是“显示参考”空间,用于显示目的,并以紧凑的“显示就绪”状态存储图像。黑色为0,白色为255,传输曲线接近1 / 2.2 sRGB基于Rec709(HDTV),并使用相同的基色和白点。但是传输曲线和数据编码不同。 Rec709旨在在较暗的客厅中的更高伽玛监视器上显示,并以16位黑色和235位白色编码。