一种基于分段线性插值的Gamma校正硬件实现
以下gamma校正内容摘自《视频信号预处理IP的硬件实现和软件验证》电子科技大学 徐琦
GAMMA 曲线校正(Gamma Correction)是数字图像处理领域最常见,最重要, 同时也是大多数人不太了解的技术之一,无论是在图像的输入端,还是在图像的输出端,甚至在图像处理的过程中它都是一个不能绕开的流程。因此,本章首先会介绍一下之所以需要进行GAMMA 曲线校正的原因,以及进行GAMMA 曲线校正所能解决的问题。
2.1 什么是GAMMA 曲线
GAMMA 曲线的概念来源于CRT(显示器/电视机)的响应曲线[14],由于CRT 显示器是通过电子束撞击荧光屏产生亮光来实现图像的显示,但是由于电子束的能量与产生的亮度的大小实际上并不成正比,而需要通过Gamma 校正来使两者对应起来。但是实际上并不是只有CRT(显示器/电视机)才存在GAMMA 响应曲线, 在实际应用中,用于做光电、电光转换的设备,他们的光电、电光转换的特性都不会是完全符合线性要求的,比如CRT 显示器,数字摄像头,甚至人眼对光线的响应曲线也都是非线性的。经过前人很多的实验总结出来一个结论,这些做光电、电光转换的设备,无论他们的输入是光,输出是电,还是输入是电,输出是光, 他们的输入和输出都符合一个幂函数关系,这个幂函数关系可以由公式(2-1)表示:
式(2-1)中的Vout 是经过光电或者电光转换之后输出的亮度值,Vin 是输入的亮度值,式中的gamma 是幂函数的指数,它是被用来衡量非线性部件(显示器/摄像头) 的转换特性,这种特性称为幂-律(power-law)转换特性。
实际上,现在在图像质量调整中Gamma 校正被赋予了更多的意义。它能起到的作用很多,它几乎可以影响到图像质量调整的各个方面。在图像质量调整中, Gamma 校正的一个重要作用是体现细节,增强对比度。由于人眼对于高亮度的差别感觉不明显,而对低亮度的细小差别感觉较为明显,因此,Gamma 校正通过将低亮度部分的差距拉大,而造成低亮度部分的细节能够被人眼明显的感觉出来, 而图像的细节部分基本上都是存在于低亮度部分的。
2.2 GAMMA曲线的幂指数
不同非线性部件gamma曲线的幂指数也不是完全相同的,通常对于Windows的输出显示系统,gamma曲线的幂指数为2.2,而对于苹果的输出显示系统和打印系统来说,gamma曲线的幂指数为1.8。人眼和数字摄像头GAMMA曲线,如图2-1所示
2.3 GAMMA曲线校正的硬件实现
从上面的介绍中可以了解到,GAMMA曲线校正对最终显示的图像质量起着非常关键的作用,因此,对于本文的视频信号预处理IP来说,它也是一个不可或缺的关键环节,下面要看一下,怎样在视频信号预处理IP中来实现GAMMA曲线校正的功能。
其实对于GAMMA曲线校正来说,算法方面没有什么太多值得研究的地方,就只是一个指数运算,只是指数有可能会不同。但是对于数字芯片设计来说,指数运算却是一个很大的难题,基本上不可能直接去实现一个指数运算。不过对于数字芯片设计来说,有一个很大的优势,那就是只需要计算有限的离散的整数的值,而不需要去关心无限的连续的小数的值,因此,查表法就成了数字芯片设计对付复杂运算的一件利器。
查表法,顾名思义,就是事先把所有输入值用复杂运算计算得到的结果制成一张表,然后把这张表存在一个地方,对于数字芯片设计来说,通常会把这张表放在一块SRAM中,这样的话,在真正需要用的时候,就可以根据输入的值直 接去查一下表,就可以知道相应的结果是什么,这样就可以省掉复杂的运算逻辑。不过相信大家也都看出来了,这种做法的优点很明显,就是可以省略那些复杂的运算的过程,直接可以得到运算结果,不过缺点也同样很明显,那就是会需要很大的一块SRAM。
按照现在市场上的需求,本文中芯片设计支持输入像素点的分辨率最高可以达到12 bits,而对于本文现在设计中GAMMA 曲线校正的指数运算,要求查表得到结果的位数为8 bits,这就意味着需要一个4096 字节的SRAM 用来存放查找表, 这已经是一块很大的SRAM 了。
SRAM 是芯片设计当中最常用到的一种模块,基本上一颗芯片如果剖开来看, 会发现其中三分之一,甚至一半以上都是SRAM,大量使用SRAM 会使得芯片的面积暴增,对于芯片成本和功耗的控制,都会带来不利的影响。
那能不能把所使用的 SRAM 的大小变小一点呢?说到这个就要提起数字芯片设计中另外一个利器,那就是逼近法,找到一个近似的,比较容易实现的公式代替原来的公式,因为很多时候无法完全实现那些很复杂的运算,那么如果可以得到一个误差足够小的结果,也是可以接受的。本文采用的是分段折线法,分段折线的具体计算方法见式(2-2)。
因为按照本文制定的规格,输入的像素点的输入数据为12bit,综合考虑尽量减小所使用的SRAM的大小,同事也要保证求出来的值由足够的精度,因此取b的值等于a+16,也就是每隔16个点画一条直线,如图2-2所示,就是本文的所采用的分段折线法。
在引入了分段折线法之后,SRAM的大小缩小了16倍,也就是所,现在只需要256个字节的SRAM就够了。但是因为引入公式2-2,现在想办法实现公式2-2,将b=a+16带入公式,可以得到下面公式2-3.
公式(2-3)中,a 为分段折线的起始点,x 为当前需要计算的点,y 为经过GAMMA 校正之后像素点的色彩值。
如果用直接计算的方式来计算公式(2-3),先来看看需要多少计算单元,单从公式来看,因为除以4 的操作可以用向右移2 位来实现,所以需要1 个乘法器,2 个加法器(一般在设计过程中,减法也会选择用加法器实现),其实这样的硬件消耗,已经可以接受了,但是这其中有一个很大的问题,那就是只有一块SRAM, 是没有办法在同一个时钟周期内把y(a)和y(a+16)的值都读出来的,那样就需要2 个周期才能算出一个点,在实时系统中,这是绝对不被允许的。
那要怎样解决这个问题呢?最直接简单的方法,就是使用2 个256 字节的SRAM,这样就可以在同一个时钟周期内把y(a)和y(a+16)的值都读出来,这样的话就需要512 字节的SRAM,相对于最开始的4096 字节的SRAM,是原来的八分之一,但是还有没有更好的方案来实现呢?仔细思考可以发现,其实只要可以同时取到相邻的两个地址的值就可以了,因此,本文把1个256字节的SRAM拆成2个128字节的SRAM,分别标记成A和B,在A中放入原来奇数地址的值,在B中存放原来偶数地址的值,这样在任何时刻都可以同时得到任意原来相邻两个地址的值。如图2-3所示,就是本文做GAMMA曲线校正的硬件架构。