数字图像处理与机器视觉:Visual C++与Matlab实现(第2版)
上QQ阅读APP看书,第一时间看更新

3.4 伽玛变换

伽玛变换又名指数变换或幂次变换,是另一种常用的灰度非线性变换。

3.4.1 理论基础

伽玛变换的一般表达式如下。

其中,x与y的取值范围均为[0,1], esp为补偿系数,γ则为伽玛系数。

与对数变换不同,伽玛变换可以根据γ的不同取值选择性地增强低灰度区域的对比度或是高灰度区域的对比度。

γ是图像灰度校正中非常重要的一个参数,其取值决定了输入图像和输出图像之间的灰度映射方式,即决定了是增强低灰度(阴影区域)还是增强高灰度(高亮区域)。

γ>1时,图像的高灰度区域对比度得到增强。

γ<1时,图像的低灰度区域对比度得到增强。

γ=1时,这一灰度变换是线性的,即不改变原图像。

伽玛变换的映射关系如图3.10所示。在进行变换时,通常需要将0~255的灰度动态范围首先变换到0~1的动态范围,执行伽玛变换后再恢复原动态范围。

图3.10 0~1范围上的伽玛变换示意图

3.4.2 MATLAB编程实现

MATLAB中为使用者提供了实现灰度变换的基本工具imadjust,它有着非常广泛的用途,其调用的一般语法如下。

      J = imadjust(I, [low_in, high_in], [low_out, high_out], gamma);

该函数将输入图像I中从low_in至high_in之间的值映射到输出图像J的low_out和high_out之间的值,low_in以下和high_in以上的值则被裁减掉。

参数说明:

• [low_in, high_in]和[low_out, high_out]确定源灰度范围到目标灰度范围的映射,在给定[low_in, high_in]和[low_out, high_out]时,需要按照double类型给定,即取值范围在0~1之间;

使[low_in, high_in]和[low_out, high_out]为空([ ]),相当于默认值[0 1],若high_out小于low_out,则输出图像J的亮度将会反转;

• 参数gamma指定了变换曲线的形状(类似于图3.10中的形状),其默认值为1,表示线性映射。若gamma<1,则映射被加权至更高的输出值;若gamma>1,则映射被加权至更低的输出值;

提示

当gamma取1时,通过设定合适的[low_in, high_in]和[low_out, high_out]的取值,imadjust函数可以实现3.2节中的灰度线性变换;而当[low_in, high_in]和[low_out, high_out]的取值均为[0, 1]时,以不同的gamma调用imadjust函数则可以实现图3.10中所示的各种伽玛变换。

• I为输入图像,可以是uint8, uint16或者double类型。

返回值:

• J为经过处理的图像,与I具有同样的类型。

将imadjust函数用于Gamma变换的调用语法如下。

      J = imadjust(I, [ ], [ ], gamma)

下面给出了gamma分别取不同值时的伽玛变换的程序实现。

      I = imread(‘pout.tif'); %读入原图像

      % Gamma取0.75
      subplot(1,3,1);
      imshow(imadjust(I, [ ], [ ], 0.75));
      title('Gamma 0.75');

      % Gamma取1
      subplot(1,3,2);
      imshow(imadjust(I, [ ], [ ], 1));
      title('Gamma 1');

      % Gamma取1.5
      subplot(1,3,3);
      imshow(imadjust(I, [ ], [ ], 1.5));
      title('Gamma 1.5');

上述程序的运行结果如图3.11所示,可以看出不同伽玛因子给图像的整体明暗程度带来的变化,以及对图像暗部和亮部细节清晰度的影响。当伽玛因子取1的时候,图像没有任何改变。

图3.11 伽玛变换效果

下面的程序生成了图3.12中3幅图像的灰度直方图。

      % Gamma取0.75
      subplot(1,3,1);
      imhist(imadjust(I, [ ], [ ], 0.75));
      title('Gamma 0.75');

      % Gamma取1
      subplot(1,3,2);
      imhist(imadjust(I, [ ], [ ], 1));
      title('Gamma 1');

      % Gamma取1.5
      subplot(1,3,3);
      imhist(imadjust(I, [ ], [ ], 1.5));
      title('Gamma 1.5');

图3.12 伽玛变换对灰度直方图的影响

注意图3.12中直方图非零区间位置的变化,以及这些变化给图像带来的影响。由于伽玛变换并不是线性变换,所以它不仅可以改变图像的对比度,还能够增强细节,从而带来整体图像效果的增强和改善。

3.4.3 Visual C++实现

利用Visual C++实现伽玛变换的代码如下。

      /**************************************************
      BOOL CImgProcess::GammaTran(CImgProcess* pTo, double gamma, double comp)
      功能:      图像的伽玛变换方法
      参数:      CImgProcess * pTo:输出CImgProcess对象的指针
                  double gamma:伽玛系数
                  double comp:补偿系数,默认为0
      返回值:    BOOL类型,true为成功,false为失败
      ***************************************************/
      BOOL CImgProcess::GammaTran(CImgProcess* pTo, double gamma, double comp)
      {
            // 首先检查图像是否是8位灰度图像
            if (m_pBMIH->biBitCount! =8) return false;

            BYTE gray;        // 临时变量,存储当前光标像素的灰度值
            int target;       // 临时变量,存储当前光标像素的目标值

            for (int i=0; i<m_pBMIH->biHeight; i++)
            {
                  for (int j=0; j<m_pBMIH->biWidth; j++)
                  {
                    gray = GetGray(j, i);
                    target = pow( (gray+comp)/255.0, gamma ) * 255; //伽马变换

                    if (target < 0) target = 0;
                    if (target > 255) target = 255;

                    // 写入目标图像
                    pTo->SetPixel(j, i, RGB(target, target, target));
                  }
            }
            return 0;
      }

利用GammaTran()函数实现伽玛变换的完整示例被封装在DIPDemo工程中的视图类函数void CDIPDemoView::OnPointGamma()中,其中调用GammaTran()函数的代码片断如下所示。

      // 输出的临时对象
      CImgProcess imgOutput = imgInput;

      // 调用GammaTran方法执行伽玛变换
      imgInput.GammaTran(&imgOutput, dlg.m_dGamma, dlg.m_dEsp);
      //其中dlg.m_dGamma和dlg.m_dEsp为伽玛变换所需的参数

      // 将结果返回给文档类
      pDoc->m_Image = imgOutput;

上述程序运行时,会弹出对话框要求用户设置伽玛变换参数。读者可以通过光盘中示例程序DIPDemo中的菜单命令“点运算→伽玛变换”来观察处理效果。