1 伽马相关概念

1.1 人眼对亮度变化的感知

​ 人眼对亮度变化的感知不是线性的,如下图,人眼对亮区的亮度变化不太敏感,对暗区的亮度变化较敏感。另外,我们可以想象一下,在一个黑暗的房间里,由 1 根蜡烛到 2 根蜡烛的变化,我们很容易感知到,但是由 100 根蜡烛到 101 根蜡烛的变化,我们就不容易感知到。因此,对于固定的存储空间,我们应该给暗区分配更多的存储空间,而给亮区少分配些空间,这样能让更多的细节在暗区呈现,而亮区不必呈现太多细节(因为人眼感知不到亮区的细微变化,呈现太多细节只会浪费空间)。

1.2 伽马编码和伽马解码

1)伽马函数

​ 伽马函数公式如下,因其指数部分 γ 读音为伽马(gamma)而来。

​ 当 0 < γ < 1 时,伽马函数的图像从左往右逐渐平缓,通常作为伽马编码处理;当 γ > 1 时,伽马函数的图像从左往右逐渐陡峭,通常作为伽马解码处理。如下是 γ 值为 0.45 和 2.2 的函数图像。

2)伽马函数在图像捕捉****和显示中的应用

​ 一般情况下,一个像素使用 8 位存储,可以表示 256 种颜色。为了尽可能线性化人眼感知的亮度变化(人眼对暗区的亮度变化更敏感,需要使用更多的存储空间,对亮区的亮度变化不太敏感,可以少分配些空间),对相机采集到的图像进行伽马编码处理后,再存入 jpeg 等格式图片文件中,在读取图片文件时,通过伽马解码处理后再显示,如下图所示。

​ 在早期,CRT(Cathode Ray Tube,阴极射线管)几乎是唯一的显示设备,它有一个特性,输入电压和显示亮度不是线性关系,而是伽马函数关系,并且其 γ 值刚好是伽马编码函数的 γ 值的倒数,这正好补偿了图像捕捉设备的伽马编码造成的亮度非线性问题。因此,显示设备只需要输入线性变化的电压,就可以还原线性变化的亮度,而不需要进行伽马解码处理。现在 CRT 设备很少见了,并且后来的显示设备有着不同的伽马曲线(γ 值不同),但人们仍在硬件上做了调整来提供兼容性。

​ 注意:透明通道不参与伽马编码和伽马解码。

3)sRGB 颜色标准

​ 微软联合爱普生、惠普制定了 sRGB 颜色空间标准,推荐相机的伽马编码函数的 γ 值为 0.45,显示器的伽马解码函数的 γ 值为 2.2(因为 2.2 × 0.45 ≈ 1)。绝大多数的摄像机、PC 和打印机都使用了 sRGB 标准。

1.3 颜色空间

​ Unity 中材质渲染的颜色空间分为伽马空间(默认)和线性空间,如下。

​ 伽马空间中,Unity 不会对 Shader 的输入和输出进行任何处理,因此,输入的像素可能是非线性的,输出的像素经过显示器的伽马解码处理后可能会得到非预期的亮度,通常表现为场景整体变暗。

​ 线性空间中,Unity 会把输入纹理设置为 sRGB 模式,在该模式下,硬件在对纹理进行采样时会自动进行伽马解码,在 Shader 写入颜色缓冲前自动进行伽马编码(HDR 除外)。

​ 用户可以在【Edit→Project Settings→Player→Other Settings→Rendering→Color Space】中设置颜色空间,如下。

2 伽马对亮度和混合的影响

​ 当颜色空间使用默认在伽马空间时,如果不进行伽马矫正,可能会出现场景整体偏暗、混合异常等问题。本节实验完整资源见→Unity3D伽马校正对比实验

2.1 伽马对亮度的影响

​ 新建一个场景,调整相机位置和旋转角度分别为 (0, 0, -1.5)、(0, 0, 0),调整直射光旋转角度为 (45, -90, 0),使得直射光从右上角 45° 射向左下角;新建一个 Sphere,调整其位置为 (0, 0, 0),新建一个材质,重命名为 DiffuseMat,设置其 Shader 为【Legacy Shaders / Diffuse】,将该材质拖拽给 Sphere;设置环境光为全黑(在【Window→Rendering→Lighting→Environment→Ambient Color】中设置),使得渲染只受漫反射影响。伽马空间和线性空间中 Sphere 渲染如下。

​ 由于球体的渲染只受漫反射影响,并且直射光从右上角 45° 射向左下角,因此右边的渲染才更符合要求。另外,左侧图像相比右侧图像,整体偏暗一些。

2.2 伽马对混合的影响

​ 新建一个场景,创建 3 个 Quad 和 3 个材质,将这些材质分别拖拽到 3 个 Quad 中,将以下 Shader 绑定到这些材质中,将边缘渐变的圆形图片拖拽到 3 个材质中,调整 3 个材质的颜色分别为红、绿、蓝。

​ SimpleBlend.shader

Shader "MyShader/SimpleBlend" {
Properties {
_MainTex ("Main Tex", 2D) = "white" {}
_Color ("Color Tint", Color) = (1, 1, 1, 1)
} SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} Pass {
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #include "UnityCG.cginc" #pragma vertex vert_img
#pragma fragment frag sampler2D _MainTex;
fixed4 _Color; fixed4 frag(v2f_img i) : SV_Target {
return fixed4(_Color.rgb, tex2D(_MainTex, i.uv).a);
} ENDCG
}
} FallBack "Transparent/VertexLit"
}

​ 伽马空间和线性空间中 3 个 Quad 的渲染如下。

​ 左侧图片边缘较硬,右侧图片边缘较柔和,更符合实际情况。

3 伽马校正策略

​ 在线性空间下,系统自动进行了伽马校正;在伽马空间下,需要用户手动校正。另外,Unity 的线性空间并不是所有平台都支持,如:移动平台就无法使用线性空间。

​ 对非线性的输入纹理,进行伽马解码校正如下:

float3 tex = pow(tex2D(_Tex, i.uv).rgb, 2.2);

​ 在片元着色器输出前,进行伽马编码校正如下:

fragColor.rgb = pow(fragColor.rgb, 0.45);
return fragColor;

​ 注意:当场景中存在半透明物体时,上述校正会导致混合在非线性空间中进行,影响混合效果,一种有效的解决方法是:将伽马编码校正放在屏幕后处理中进行。

​ 声明:本文转自【Unity3D】伽马校正

【Unity3D】伽马校正的更多相关文章

  1. 【图形学】我理解的伽马校正(Gamma Correction)

    http://blog.csdn.net/candycat1992/article/details/46228771/ 写在前面 我相信几乎所有做图像处理方面的人都听过伽马校正(Gamma Corre ...

  2. 【视频开发】伽马校正(gamma correction)学习笔记

    我相信几乎所有做图像处理方面的人都听过伽马校正(Gamma Correction)这一个名词,但真正明白它是什么.为什么要有它.以及怎么用它的人其实不多.我也不例外.  最初我查过一些资料,但很多文章 ...

  3. 图像处理gamma修正(伽马γ校正)的原理和实现算法

    ☞ ░ 前往老猿Python博文目录 ░ 本文转自博客园:淇淇宝贝的文章<图像处理之gamma校正>,原文链接:https://www.cnblogs.com/qiqibaby/p/532 ...

  4. 伽马变换(一些基本的灰度变换函数)基本原理及Python实现

    1. 基本原理 变换形式 $$s=cr^{\gamma}$$ c与$\gamma$均为常数 可通过调整$\gamma$来调整该变换,最常用于伽马校正与对比度增强 2. 测试结果 图源自skimage ...

  5. 图像增强算法(直方图均衡化、拉普拉斯、Log、伽马变换)

    一.图像增强算法原理 图像增强算法常见于对图像的亮度.对比度.饱和度.色调等进行调节,增加其清晰度,减少噪点等.图像增强往往经过多个算法的组合,完成上述功能,比如图像去燥等同于低通滤波器,增加清晰度则 ...

  6. 基础图像处理之混合空间增强——(Java:拉普拉斯锐化、Sobel边缘检测、均值滤波、伽马变换)

    相信看过冈萨雷斯第三版数字图像处理的童鞋都知道,里面涉及到了很多的基础图像处理的算法,今天,就专门借用其中一个混合空间增强的案例,来将常见的几种图像处理算法集合起来,看能发生什么样的化学反应 首先,通 ...

  7. C++数字图像处理(1)-伽马变换

    https://blog.csdn.net/huqiang_823/article/details/80767019 1.算法原理    伽马变换(幂律变换)是常用的灰度变换,是一种简单的图像增强算法 ...

  8. 对比度增强(二):直方图正规划与伽马变换 cv.normal()函数使用及原理

    直方图正规化: 图像为I,宽为W,高为H,I(r,c)代表I的第r行第c列的灰度值:输出图像记为O,为使得输出图像的灰度值在[Omin,Omax]范围里,可用如下公式:                 ...

  9. OpenCV计算机视觉学习(3)——图像灰度线性变换与非线性变换(对数变换,伽马变换)

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 下面 ...

  10. Gamma correction 伽马校准及 matlab 实现

    matlab 内置实现:imadjust Gamma Correction gamma correction formula : .^(gamma) or .^(1/gamma)? 用以调整图像光照强 ...

随机推荐

  1. C++模板显示指定类型时使用引用遇到的问题

    1.问题 这里我想让模板函数接收int和char类型的参数,并进行相加,显示指定参数类型为int. 第一个调用理论上会自动将char类型强转成int类型,后进行相加: 第二个调用理论上会自动将int类 ...

  2. [转帖]Nginx 使用与异常处理

    http://jartto.wang/2017/04/15/nginx-exception-handling/ 以前总是偷懒使用 Http-Server 来启动一个本地服务,后来花时间学习了一下 Ng ...

  3. 【转帖】【奇淫技巧】Linux | 查找文件,无所遁形

    theme: channing-cyan 本文正在参与 "走过Linux 三十年"话题征文活动 在Linux系统上,最常见的操作莫过于处理文本.常见文件操作陈列.查找.排序.格式转 ...

  4. Beyond Compare 的比较以及导出的简单设置方法

    最近需要对文件进行对比 但是发现对比的工作量比较难搞. 用到了beyond compare 的工具 感觉挺好用的 但是需要注意事项比较多这里记录一下 1.  session setting 里面进行设 ...

  5. 使用rpmbuild打包erlang和rabbitmq进行部署服务的方法

    使用rpmbuild打包erlang和rabbitmq进行部署服务的方法 背景说明 1. rabbitmq 是基于 erlang 开发的消息列队, 本身rabbitmq 自己不区分架构. 2. 但是e ...

  6. 【JS 逆向百例】W店UA,OB反混淆,抓包替换CORS跨域错误分析

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...

  7. 手撕Vuex-实现getters方法

    经上一篇章介绍,完成了实现共享数据的功能,实现方式是在 Store 构造函数中将创建 Store 时将需要共享的数据添加到 Store 上面,这样将来我们就能通过 this.$store 拿到这个 S ...

  8. 报错ValueError: Can't find 'adapter_config.json'

    前言 在做组内2030项目时,我具体做的一个工作是对大模型进行LoRA微调,在整个过程中有许多坑,其中有些值得记录的问题,于是便产生了这篇博客. 问题 我在得到微调好的模型后,需要对模型进行性能测评. ...

  9. 7.3 C/C++ 实现顺序栈

    顺序栈是一种基于数组实现的栈结构,它的数据元素存储在一段连续的内存空间中.在顺序栈中,栈顶元素的下标是固定的,而栈底元素的下标则随着入栈和出栈操作的进行而变化.通常,我们把栈底位置设置在数组空间的起始 ...

  10. C/C++ 实现切片免杀的思路

    今天突然想到了一个好玩的免杀思路,原理就是想办法切断磁盘特征与内存特征,关于沙盒免杀我寻思着,这样可以将不同的的DLL映射到内存,在内存中他们的特征也是被切断的,在注入器上做判断如果是沙盒则不加载,不 ...