3.3 灰度对数变换
本节介绍一种灰度的非线性变换——对数变换,并介绍它在傅里叶频谱显示中的应用。
3.3.1 理论基础
对数变换的一般表达式如下。
其中,c为尺度比例常数,s为源灰度值,t为变换后的目标灰度值。
在如图3.8所示的对数曲线上,函数自变量为低值时,曲线的斜率很高;自变量为高值时,曲线斜率变小。
图3.8 对数变换示意图
由对数函数曲线可知,这种变换可以增强一幅图像中较暗部分的细节,从而可用来扩展被压缩的高值图像中的较暗像素,因此对数变换被广泛地应用于频谱图像的显示中。一个典型的应用是傅里叶频谱(参见第6章),其动态范围可能宽达0~106。直接显示频谱时,图像显示设备的动态范围往往不能满足要求,从而丢失了大量的暗部细节。而在使用对数变换之后,图像的动态范围被合理地非线性压缩,从而可以清晰地显示。本节的MATLAB实现中就提供了一个这样的示例。
3.3.2 MATLAB实现
对数变换不需要专门的图像处理函数,可以使用如下数学函数实现对图像I的对数变换。
T = log(I + 1);
注意
log函数会对输入图像矩阵I中的每个元素进行操作,但是却仅能处理double类型的矩阵。从图像文件中得到的图像矩阵则大多数是uint8类型的,因此需要首先使用im2double函数来执行数据类型的转换。
下面的程序比较了对傅里叶频谱图像进行对数变换前后的效果(不必关注代码中生成傅里叶频谱的部分)。结果如图3.9所示。
I=imread('coins.png'); % 读取图像 F = fft2(im2double(I)); % 计算频谱 F = fftshift(F); F = abs(F); T = log(F + 1); % 对数变换 subplot(1,2,1); imshow(F, []); title(’未经变换的频谱’); subplot(1,2,2); imshow(T, []); title(’对数变换后’); % 显示原图和变换结果
图3.9 对数变换效果示意图
在图3.5(a)中未经变换的频谱可见,图像中心绝对高灰度值的存在压缩了低灰度部分的动态范围,从而无法在显示时表现出细节;而经过对数灰度处理的图像,其低灰度区域对比度将会增加,暗部细节被增强。
3.3.3 Visual C++实现
利用Visual C++实现灰度对数变换的代码如下。
/************************************************** BOOL CImgProcess::LogTran(CImgProcess* pTo, double dC) 功能: 图像的灰度对数变换 参数: CImgProcess * pTo:输出CImgProcess对象的指针 double dC:灰度对数变换所需的参数 返回值: BOOL类型,0为成功,其他值为失败 ***************************************************/ BOOL CImgProcess::LogTran(CImgProcess* pTo, double dC) { // 首先检查图像是否是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 = dC * log( (double)(gray + 1) ); if (target < 0) target = 0; if (target > 255) target = 255; // 写入目标图像 pTo->SetPixel(j, i, RGB(target, target, target)); } }; return 0; }
利用LogTran()函数实现对数变换的完整示例被封装在DIPDemo工程中的视图类函数void CDIPDemoView::OnPointLog()中,其中调用LogTran()函数的代码片断如下所示。
// 输出的临时对象 CImgProcess imgOutput = imgInput; // 使用对数变换方法 imgInput.LogTran(&imgOutput, dlg.m_dC); // 其中dlg.m_dC是对数变换的系数 // 将结果返回给文档类 pDoc->m_Image = imgOutput;
上述程序运行时会弹出对话框要求用户设置对数变换参数。读者可以通过光盘中示例程序DIPDemo中的菜单命令“点运算→对数变换”来观察处理效果。