伽马矫正(Gamma Correction)

比较好的伽玛校正文章看这个文章或者是知乎的回答

这里的理解仅供参考

伽玛校正

线性RGB空间sRGB空间(非线性)进行转化的手段

简单的理解可以把gamma ≈ 2.2 (这是近似值,简化后的,实际有些地方会做更精准的计算如:这篇文章

对颜色值做乘方运算,其中gamma值 == 幂次,比如 ( 0.5 , 0 , 0 ) (0.5,0,0) (0.5,0,0)颜色,应用gamma矫正: ( 0.5 , 0 , 0 ) 2.2 = ( 0.217 , 0 , 0 ) (0.5,0,0)^{2.2}=(0.217,0,0) (0.5,0,0)2.2=(0.217,0,0)gamma = 2.2


我们为什么要做伽马矫正?

  • 所有显示器都会自动进行gamma = 2.2的校正,即在你所定义的颜色的基础上 做2.2次幂的乘方运算。
  • 比如我在程序中输出颜色(0.5, 0, 0),在显示器上其实是经过显示器矫正后的颜色(0.217, 0, 0),偏暗!
  • 为了消除这种影响,我们要对我们游戏中定义的颜色做gamma = 1/2.2 矫正。我们想要显示器输出的是(0.5, 0, 0),就必须进行伽玛校正,先对颜色做1/2.2的乘方运算,再把颜色给显示器,它会做2.2乘方运算,结果就还是(0.5, 0, 0)
  • 过程看下图
    在这里插入图片描述

一个容易出错的点:

在这里插入图片描述
对这句话理解: 显示器输出的颜色是经过gamma2.2矫正后的颜色,现在显示器输出的是(0.5,0,0),半红色。艺术家创建纹理的时候,不知道他是0.5R啊,靠感觉为了跟这个颜色一样,他在RGB空间把颜色值调到了(0.729,0,0),诶现在感觉两个颜色看起来一模一样了美滋滋,但是这样的后果就是,艺术家定义的这个纹理颜色0.729是在非线性空间的(sRGB空间)。我们在程序中,拿到这个纹理,按照之前所说的 会先进行gamma1/2.2矫正,会得到得到0.866R,然后显示器默认2.2矫正后,显示的颜色是(0.728,0,0)盖了帽了,颜色偏亮!

解决办法:

  • 让艺术家们调颜色的时候,调到正确的颜色后,应用2.2gamma矫正后,再把纹理给我们
  • 艺术家们不调,我们自己调,对采样到的颜色做2.2矫正,变到线性空间后,再进行后面的操作
    vec3 diffuseColor = pow(texture(diffuse, texCoords).rgb, vec3(gamma));

opengl提供的解决方式

为每个sRGB空间的纹理做这件事非常烦人。幸好,OpenGL给我们提供了另一个方案来解决我们的麻烦,这就是GL_SRGBGL_SRGB_ALPHA内部纹理格式。【这个纹理格式,仅仅是帮我们把传入的纹理图片做一遍2.2gamma矫正而已,没别得东西,因此我们使用这个纹理格式,必须明确知道传入的图片是在sRGB空间定义的,那如果是传入的什么法线纹理、光照高光贴图纹理,诸如此类都是艺术家或我们自己在线性空间定义的,不能使用上述两种格式

如果我们在OpenGL中创建了一个纹理,把它指定为以上两种sRGB纹理格式其中之一,OpenGL将自动把颜色校正到线性空间中,这样我们所使用的所有颜色值都是在线性空间中的了。我们可以这样把一个纹理指定为一个sRGB纹理:

glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
如果你还打算在你的纹理中引入alpha元素,必究必须将纹理的内部格式指定为GL_SRGB_ALPHA。

因为不是所有纹理都是在sRGB空间中的所以当你把纹理指定为sRGB纹理时要格外小心。比如diffuse纹理,这种为物体上色的纹理几乎都是在sRGB空间中的。而为了获取光照参数的纹理,像specular贴图和法线贴图几乎都在线性空间中,所以如果你把它们也配置为sRGB纹理的话,光照就坏掉了。指定sRGB纹理时要当心。

真正的伽马矫正(不是2.2)

线性 RGB 转换到 sRGB

  • 包括 Unreal Engine 和 Unity 等,默认使用 sRGB 颜色空间进行渲染和颜色处理。这是因为 sRGB 颜色空间广泛应用于显示设备和图像处理,确保了颜色的一致性和准确性。

  • 线性 RGB 颜色值 C_linear,sRGB 颜色值 C_sRGB 转换公式是:

    // 该公式需要应用于 RGB 每个分量。
    float linearToSRGB(float c_linear) 
    {
        if (c_linear <= 0.0031308) 
        {
            return 12.92 * c_linear;
        } 
        else 
        {
            return 1.055 * pow(c_linear, 1.0 / 2.4) - 0.055;
        }
    }
    

sRGB 转换到线性 RGB

  • 当需要转回RGB的时候)
    float sRGBToLinear(float c_sRGB) 
    {
        if (c_sRGB <= 0.04045) 
        {
            return c_sRGB / 12.92;
        } 
        else 
        {
            return pow((c_sRGB + 0.055) / 1.055, 2.4);
        }
    }
    
局部自适应伽马矫正(Local Adaptive Gamma Correction)是一种可以根据图像的局部特征进行自适应调整的伽马矫正方法。该方法可以有效地增强图像的对比度并保留细节信息。下面是一个示例代码,演示如何使用OpenCV和NumPy库进行局部自适应伽马矫正: ```python import cv2 import numpy as np def local_adaptive_gamma_correction(image, gamma=1.0, clip_limit=2.0, tile_size=8): # 将图像转换为Lab颜色空间 lab_image = cv2.cvtColor(image, cv2.COLOR_BGR2LAB) l_channel, a_channel, b_channel = cv2.split(lab_image) # 对L通道进行伽马矫正 l_channel = cv2.equalizeHist(l_channel) l_channel = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=(tile_size, tile_size)).apply(l_channel) l_channel = cv2.pow(l_channel/255.0, gamma) * 255.0 # 合并通道并转换回BGR颜色空间 corrected_lab_image = cv2.merge((l_channel, a_channel, b_channel)) corrected_image = cv2.cvtColor(corrected_lab_image, cv2.COLOR_LAB2BGR) return corrected_image # 读取图像 image = cv2.imread('image.jpg') # 进行局部自适应伽马矫正 gamma_corrected_image = local_adaptive_gamma_correction(image, gamma=1.5, clip_limit=2.0, tile_size=8) # 显示原始图像和矫正后的图像 cv2.imshow('Original Image', image) cv2.imshow('Gamma Corrected Image', gamma_corrected_image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 上述代码中的`local_adaptive_gamma_correction()`函数实现了局部自适应伽马矫正。该函数首先将输入图像转换为Lab颜色空间,然后对L通道进行直方图均衡化和CLAHE(对比度限制自适应直方图均衡化)处理。接下来,将L通道的像素值进行伽马矫正,并将L通道与a通道、b通道重新合并。最后,将结果转换回BGR颜色空间。 您可以根据需要调整`gamma`、`clip_limit`和`tile_size`参数以获得所需的效果。请注意,上述代码中的`'image.jpg'`应替换为您要进行矫正的实际图像路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宗浩多捞

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值