C实现Gama变换
原理:
Gama变换也幂变换,公式如下:
s=cr^γ
输入r与s的变换关系如下图:
上图中,横坐标0附近对应于输入图像中的黑色像素值,纵坐标中0附近对应于输出图像中黑色像素值。由上图可以看出,当γ<1时,Gama变换将输入图像中0值邻域拉伸了,相反,当γ>1时Gama变换将输入图像中0值邻域缩小了。当γ=1时,为恒同变换。上图中,γ=1两边的变换互为逆映射,如0.2和5.0。
为什么要进行Gama校正:
某些显示器,如CRT显示器,它的强度到电压的响应是幂变换,其γ值在1.8到2.5之间,因此,其显示效果偏暗,如果在显示之前,先对图像进行γ变换,使之在0值邻域偏亮,那么输出的图像就是正常的了。可以对其他设备做此相应的分析,它们之间没有什么差别,只不过是γ不同而已。
代码实现:
void RGB32GamaCorrection(uint8_t* src, int width, int height, int factor)
{
int i;
int j;
float maxv;
float minv;
float gama;
int r,g,b;
float nr,nb,ng;
uint32_t color;
uint32_t* img = (uint32_t*)src;
minv = 1.0;
maxv = 5.0;
gama = (maxv - minv) * factor/100.0 + minv;
gama = 1 / gama;
if (factor ==0)
return;
if (factor > 100)
factor = 100;
for(i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
color = *img;
r = color & 0x000000FF;
g = (color >> 8) & 0x000000FF;
b = (color >> 16) & 0x000000FF;
nr = r / 255.0;
ng = g / 255.0;
nb = b / 255.0;
nr = pow(nr, gama);
ng = pow(ng, gama);
nb = pow(nb, gama);
r = nr * 255;
g = ng * 255;
b = nb * 255;
r = r < 0?0:(r > 255? 255:r);
g = g < 0?0:(g > 255? 255:g);
b = b < 0?0:(b > 255? 255:b);
color &= 0xFF000000;
color |= (r + (g << 8) + (b << 16));
*img = color;
img++;
}
}
}
效果如下:
原图:
变换后的图片效果:
问题,变换之后图片引入了噪声,而且参数值越大,噪声越明显,所以,为了进一步改善视觉效果,可以根据需要引入滤波器,对变换结果进行滤波处理。