现象
从上往下看左侧黑色块黑得越来越严重,对比度也在逐渐加深。此时灰阶的高亮区获得的数据位变少,暗区获得的数据位变多,暗区细节会更多。但是需要注意的是这幅图是一个反伽马曲线的特性,和ISP中的gamma表示是反的。
Gamma产生的原因
CRT属性导致
在液晶屏幕诞生前,CRT显示器是唯一的一种显示器。老式电视。
这种显示器的工作方式如下图所示:
屏幕后面是一个阴极射线管,工作原理大致就是后面的电子前发射电子,经加速电场和偏移电场的作用打到屏幕上指定的位置,然后屏幕的特殊材质会发光产生画面。然后屏幕显示的亮度就和电子的数量有关,而这个又和电子枪的电压有关,所以屏幕亮度就和电子枪有一个函数关系:
I s r e e n = f ( V ) I sreen =f(V) Isreen=f(V)
但是需要注意的是这个函数关系不是线性的,也就是说当电子枪的电压升高为原来的两倍,但是屏幕亮度并不能变为原来的两倍,后面经过实验总结发现CRT的这种非线性关系满足对数关系:
正式因为显示时会把亮度压低,所以为了还原原来的线性特征,需要在显示之前进行一个矫正,使其恢复为线性,于是就有的gamma矫正,这也是最早对gamma的理解。到现在液晶显示可不满足这种特性,但是为了兼容以前的视频格式,也会认为在显示的时候添加这个一个反伽马矫正。通过 Gamma 编码的数据(encoding gamma)与 CRT 显示器的 Gamma 特征(display gamma),这两组编码恰好乘积(system gamma)为 1。
参考以下链接:
gamma矫正原理
其中:此人眼对亮度的变化的感知能力一开始我理解为是对亮度的响应但看了up主的HVS篇讲解,此应该是对亮度的灵敏度(会在hvs篇解释)
人眼的亮度特性
对于gamma还有一种说法就是,人眼的亮度响应曲线不是线性的而是如下图的关系:
视觉感受的中灰色是白色反射率的20%左右。(注:白色为低动态颜色1.0)
再换成更不精确但更好用的话就是:自然界的0.2,在心目中的地位是0.5。
所以为了更好符合人眼的特性,就需要对暗区进行加强以提高画面的动态范围和暗区细节,更好的响应人眼对暗部更敏感的特性。(目的是为了更好地匹配人眼对光线强度的非线性响应特性!!)
该回答写的很清楚,其中维基百科的解释更简单易理解:引入gamma压缩是为了更好地利用比特位,因为人眼对暗比高亮更敏感,所以用gamma<1的指数函数变换使得敏感部分获得更多的数据位。 而显示器的gamma值完全是为了解压缩,只要能够使得整个系统的输入输出呈线性就好了。 人眼特性+充分利用存储空间的考虑->gamma编码 ; gamma编码+全系统输入为1的考虑->显示器的gamma值取什么
更直白的话就是:因为硬盘太贵,网线太细,所以地球人目前主流使用8位每通道的sRGB色彩描述体系,它灰阶有限,中灰的地位必须在所有灰阶的中间,记录值为128,而不能是其物理值0.218,把物理量0.218换算成0.5灰阶的过程,就是编码端的Gamma校正,Gamma值为1/2.2=0.454。屏幕读取到128显示成21.8%的亮度的过程,就是解码端的Gamma校正,Gamma值为2.2。整个系统Gamma为1。
gamma校正
以下皆转载up主博客。
LUT法
如上图的论文中提到一种LUT法的实现方式。就是提前把每个像素值经过gamma矫正后对应的值求出来,然后把这些数值直接存储在一个数组中,到矫正的时候就根据输入的值就能直接通过数组下标就能找到对应的矫正后的值,这种方式最大的优点就是快,几乎不消耗硬件资源,因为几乎不用做任何计算的处理,但是这种方式的弊端在于需要大量的内存来存储这个表,但随着技术的发展内存对于硬件也不是什么限制了,一个手机动辄就8G的内存了,可以通过加DDR来提高内存,所以现在很多方案在用这种查表得方式做gamma矫正。
就是在一个头文件中定义这么一个数组,完全对应每一个输入值。
clc;clear; close all;
data = csvread('data/Gamma_Data_DEC_20210804103309.csv');
plot(data);
xlim([0, 1024]);
ylim([0, 4098]);
hold on;
plot([0, 1024], [0, 4098], 'r');
线性插值法
线性插值法也很好理解,就是在gamma曲线上提取一些采样点,然后把采样点的输入输出作为xy存储起来,然后矫正的时候如果在采样点上就接直接输入矫正值,如果不在,那么肯定在某两个采样点之间,那么就可以就可以通过这两个采样点的线性方程求解出该点的校正值。但是这种方式会有一定的误差,因为线性方程并不能完全拟合gamma曲线。
如上,通过17个采样点来拟合曲线。
clc;clear;close all;
data = textread('data\gamma.txt', '%s');
xStr = char(data(1));
yStr = char(data(2));
xC = strsplit(xStr, ',');
yC = strsplit(yStr, ',');
x = hex0x2Dec(xC);
y = hex0x2Dec(yC);
plot(x, y);
hold on;
plot([0 255], [0 1023], 'r')
xlim([0, 256]);
ylim([0, 1024]);
这调曲线就是拟合出来的效果。
模拟gamma法
还有一种方式就是通过模拟的方式来做gamma矫正,但是这种方式不输入ISP PIPELINE中的算法,所以只是简单提一下。
这种方法的大概思路就是AD转换的时候经过一定的处理使其呈现非线性的特性。如上图定义Vramp和Vsig,当电压达到Vramp时产生一个斜坡信号,同时时钟信号开始工作并计数,然后当电压到达Vsig时latch信号发生一个跳变使得时钟信号停止记数,然后这个电压值就会和这种始终信号有一个非线性特性,后根据这个特性进行gamma矫正。然后这种方式不涉及ISP算法,所以up主并未作重点讲解。
转载来源:https://blog.csdn.net/wtzhu_13/article/details/119533870?spm=1001.2014.3001.5502
https://www.bilibili.com/video/BV1VU4y1n7UC/?spm_id_from=333.1387.homepage.video_card.click&vd_source=917b39787b71f9af867492b65b1fdec3