ISP:Gamma

假设图像中有一个像素 X ,值是 100 ,那么对这个X像素进行校正,步骤如下:

1. 归一化 :将像素值转换为  0 ~ 1  之间的实数。 算法如下 : ( x + 0. 5)/256  这里包含 1 个除法和 1 个加法操作。对于像素  X  而言  , 其对应的归一化值为  0. 392528 。

2. 预补偿 :根据公式 , 求出像素归一化后的 数据以  1 /gamma  为指数的对应值。这一步包含一个 求指数运算。若  gamma  值为  2. 2 ,  则  1 /gamma  为  0. 454545 , 对归一化后的 X   值进行预补偿的结果就 是  0. 392528 ^0. 454545 = 0. 653764 。

3. 反归一化 :将经过预补偿的实数值反变换为  0  ~  255  之间的整数值。具体算法为 : f * 256 - 0. 5  此步骤包含一个乘法和一个减法运算。续前 例  , 将 X   的预补偿结果               0. 653764 代入上式  , 得到 X  预补偿后对应的像素值为  167, 这个  167 就是最后送 入显示器的数据。

上诉运算效率比较低,针对这种情况,提出了一种快速查找表 (LUT:Look Up Table)算法。前提是转换前后,X的值在0~255之间。

本算法不适用于高Bit为转低Bit位 不适合,原理一样,估计公式不同?待研究

#include <math.h>

typedef unsigned char UNIT8; // 0~255
UNIT8 g_GammaLUT[256];

// fPrecompensation = 1 / gamma
void BuildLUTTable(float fPrecompensation )
{
  int i;
  float f;
  for( i=0;i<256;i++)
  {
    f=(i+0.5F)/256;//归一化
    f=(float)pow(f,fPrecompensation); //预补偿
    g_GammaLUT[i]=(UNIT8)(f*256-0.5F);//反归一化 & 结果存入 g_GammaLUT
  }
}

void GammaCorrectiom(UNIT8 src[],int iWidth,int iHeight,float fGamma,UNIT8 Dst[])
{
  int iCols,iRows;
  BuildLUTTable(1/fGamma);//gamma校正查找表初始化
 
  //查找表矫正
  for(iRows=0;iRows<iHeight;iRows++)
  {
    for(iCols=0;iCols<iWidth;iCols++)
    {
      Dst[iRows*iWidth+iCols]=g_GammaLUT[src[iRows*iWidth+iCols]];
    }
  }
}

typedef unsigned char UNIT8; // 0~255
UNIT8 g_GammaLUT[256];

// fPrecompensation = 1 / gamma
void BuildLUTTable(float fPrecompensation )
{
  int i;
  float f;
  for( i=0;i<256;i++)
  {
    f=(i+0.5F)/256;//归一化
    f=(float)pow(f,fPrecompensation); //预补偿
    g_GammaLUT[i]=(UNIT8)(f*256-0.5F);//反归一化 & 结果存入 g_GammaLUT
  }
}

void GammaCorrectiom(UNIT8 src[],int iWidth,int iHeight,float fGamma,UNIT8 Dst[])
{
  int iCols,iRows;
  BuildLUTTable(1/fGamma);//gamma校正查找表初始化
 
  //查找表矫正
  for(iRows=0;iRows<iHeight;iRows++)
  {
    for(iCols=0;iCols<iWidth;iCols++)
    {
      Dst[iRows*iWidth+iCols]=g_GammaLUT[src[iRows*iWidth+iCols]];
    }
  }
}
发布了15 篇原创文章 · 获赞 8 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/YXFLINUX/article/details/51260666
今日推荐