Image processing(非线性对比度增强算法)
题目:
查阅资料,完成1-2种图像灰度变换或图像增强的算法,完成一份实验PPT 。
PPT主要内容包括:
(1)理论方法介绍;
(2)实验代码(截图+源码,其中源码可以放在截图页的备注框)
(3)实验结果;
(4)其他你想说明的内容。
- 限制对比度自适应直方图均衡化
- 指数变换增强
- 对数变换增强
- 伽马变换增强
CLAHE(限制对比度自适应直方图均衡化)
CLAHE是基于自适应直方图均衡化(AHE)算法的改进版本。AHE的工作原理是将图像分成小块,对每个小块进行直方图均衡化,从而增强局部对比度。但AHE存在一个问题,就是可能会过度增强噪声,导致噪声像素值过大,产生不自然的效果。
CLAHE通过限制对比度的增强程度来解决这一问题。它将每个小块的直方图进行剪裁,剪裁的阈值由clipLimit
参数控制。超过阈值的像素将被剪裁掉,剩余像素再进行直方图均衡化。这样就限制了对比度增强的程度,避免过度增强噪声。
简单来说: CLAHE的核心思想是将图像分成小块进行直方图均衡化,从而增强局部对比度,同时限制对比度过度增强以避免噪声放大。
举个例子: 当我们使用CLAHE处理一张图像时,首先将图像划分成许多小块(例如16x16像素的块),然后对每个小块进行直方图均衡化,以增强局部对比度。接着,我们需要进行对比度限制,以避免过度增强。这通常通过对每个小块中的直方图进行调整来实现。
假设我们有一张灰度图像,其中一部分区域的亮度较低,而另一部分区域的亮度较高。我们将使用CLAHE来增强这张图像的对比度。
原始图像:
[ 30 30 30 30 30 30 ]
[ 30 30 30 30 30 30 ]
[ 30 30 150 150 150 150 ]
[ 30 30 150 150 150 150 ]
[ 30 30 150 150 150 150 ]
[ 30 30 150 150 150 150 ]
现在,我们将图像划分成3x3的小块,然后对每个小块进行直方图均衡化。接下来,我们将对每个小块中的直方图进行对比度限制。这意味着,如果某个小块的直方图中某个灰度级别的像素数量超过了一个预先定义的阈值,那么这个灰度级别中的像素将被截断并分配给其他灰度级别,以限制对比度增强。
处理后的图像可能如下所示:
[ 30 30 30 30 30 30 ]
[ 30 30 35 35 35 35 ]
[ 30 30 150 150 150 150 ]
[ 30 30 150 150 150 150 ]
[ 30 30 150 150 150 150 ]
[ 30 30 150 150 150 150 ]
在这个处理后的图像中,对比度得到了增强,但是对比度增强是在每个小块内部进行的,并且受到对比度限制的控制,因此图像的整体外观并没有发生过度变化。这样,我们就通过CLAHE成功地增强了图像的对比度,同时保留了图像的细节。
在3x3的小块中进行直方图均衡化的过程中,通常会使用CDF(Cumulative Distribution Function,累积分布函数)来映射像素值。其基本步骤如下:
计算直方图:对于3x3的小块,统计每个灰度级别出现的频率,得到原始直方图。
计算累积分布函数(CDF):对于每个灰度级别,计算其累积分布函数的值。这可以通过将每个灰度级别的频率与前面的频率相加来实现。
归一化:将CDF进行归一化,以确保最小值为0,最大值为255。
映射:将原始图像中每个像素的灰度级别替换为其对应的CDF值,以完成直方图均衡化。
注
在CLAHE中,常用的非线性变换包括使用S形函数(例如sigmoid函数)、分段线性函数或其他适合于特定图像特征的函数。这些非线性变换可以根据图像的局部特征来调整对比度增强的强度,并且可以防止图像过度增强或产生不自然的效果。
函数参数:
cv2.createCLAHE(clipLimit = 2.0, tileGridSize=(8,8))
clipLimit: 设置对比度限制的阈值。较大的值会增加对比度,但也可能过度增强噪声。建议值在2-5之间。
tileGridSize: 设置网格的大小,决定了要分成多少个小块进行直方图均衡化。较大的值会增加对比度,但也可能导致过度增强边界噪声。通常设置为(8,8)。
代码:
import cv2
img = cv2.imread('test1.png',0)
# 限制对比度自适应直方图均衡化
clache = cv2.createCLAHE(clipLimit=5.0,tileGridSize=(8,8))
cl1 = clache.apply(img)
cv2.imshow('origin image',img)
cv2.imshow('CLAHE Image',cl1)
cv2.waitKey(0)
结果图:
指数变换增强
感觉除了变亮,没什么区别...
指数变换的公式如下:
其中,f(x, y)
表示输入图像在坐标(x, y)
处的像素值,g(x, y)
表示输出图像在相应坐标处的像素值,c
是尺度常数(通常取1),gamma
是指数变换的参数。
当gamma
小于1时,较暗的像素值被拉伸,较亮的像素值被压缩,从而增强图像的整体亮度和暗部细节。
当gamma
大于1时,较亮的像素值被拉伸,较暗的像素值被压缩,从而增强图像的整体对比度和亮部细节。
举个例子
例如有一个4x4的灰度图像,像素值如下:
10 20 30 40
50 60 70 80
90 100 110 120
130 140 150 160
现在,我们对这个图像应用指数变换增强,设置gamma
为0.5。我们对每个像素值进行变换。以像素值为10的点为例:
g(0, 0) = 1 * (10/255)^0.5 * 255
= 1 * 0.1980 * 255
= 50.49
对其他像素值进行同样的变换,得到变换后的图像:
50 89 122 152
177 200 222 243
255 255 255 255
255 255 255 255
可以看到,原始图像中较暗的像素值(如10、20、30等)被拉伸,变得更亮;而较亮的像素值(如130、140、150等)被压缩,变得略暗。这是因为我们设置的gamma
值小于1,使得较暗的像素值被拉伸,较亮的像素值被压缩。
如果我们设置gamma
为2,则变换后的图像如下:
1 4 9 16
25 36 49 64
81 100 121 144
169 196 225 255
在这种情况下,原始图像中较亮的像素值被拉伸,变得更亮;而较暗的像素值被压缩,变得更暗。这是因为我们设置的gamma
值大于1,使得较亮的像素值被拉伸,较暗的像素值被压缩。
通过这个简单的例子,我们可以看到指数变换增强如何通过调整gamma
参数来控制图像的亮度和对比度。gamma
小于1时,图像整体变亮,暗部细节被增强;gamma
大于1时,图像整体变暗,亮部细节被增强。
代码:
# 指数变换的参数,可以根据需要调整
gamma = 0.9
enhanced_img = np.power(img/255.0,gamma)*255.0
enhanced_img = enhanced_img.astype(np.uint8)
cv2.imshow('origin image',img)
cv2.imshow('Enhanced Image',enhanced_img)
cv2.waitKey(0)
结果图:
对数变换增强
感觉效果也没有很好...
对数变换是一种非线性的图像增强方法,它通过对图像的灰度值应用对数函数来扩展图像的低灰度部分,压缩高灰度部分,从而改善图像的对比度和暗部细节。对数变换的公式如下:
其中,f(x, y)
表示输入图像在坐标(x, y)
处的像素值,g(x, y)
表示输出图像在相应坐标处的像素值,c
是尺度常数,用于控制增强的程度。
对数函数的特点是,当输入值较小时,输出值增长较快;当输入值较大时,输出值增长较慢。这种特性恰好与人眼的感知特性相符合,因为人眼对暗部细节的变化更加敏感。
在对数变换增强中,我们通过对像素值加1,然后计算自然对数,再乘以尺度常数c
,来实现对图像的增强。之所以要给像素值加1,是为了避免出现log(0)
的情况,因为log(0)
是未定义的。
对数变换后的图像可能超出了0-255的范围,因此我们需要对其进行归一化处理。归一化的过程是将对数变换后的图像除以其最大值,再乘以255,使其映射回0-255的范围内。
对数变换增强的效果取决于尺度常数c
的选择。较大的c
值会使增强效果更明显,暗部细节更加突出,但可能会导致亮部细节的丢失;较小的c
值会使增强效果更温和,保留更多的亮部细节,但暗部细节的增强程度会降低。
在实际应用中,我们可以根据图像的特点和增强的目的,选择合适的c
值来获得所需的增强效果。通常情况下,c
的取值范围在0.5到2之间。
代码:
# 对数变换增强
c = 2.0
log_img = c * np.log(1.0 + img)
# 归一化到0-255范围
log_img = np.uint8(log_img / np.max(log_img) * 255)
# 显示原图和增强后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Enhanced Image', log_img)
cv2.waitKey(0)
效果图:
伽马变换增强
伽马变换是一种非线性的图像增强方法,它通过对图像的灰度值应用幂律变换来调整图像的对比度。伽马变换的公式如下:
其中,f(x, y)
表示输入图像在坐标(x, y)
处的像素值,g(x, y)
表示输出图像在相应坐标处的像素值,c
是尺度常数(通常取1),gamma
是伽马变换的参数。
当gamma
小于1时,较暗的像素值被拉伸,较亮的像素值被压缩,从而增强图像的整体亮度和暗部细节。
当gamma
大于1时,较亮的像素值被拉伸,较暗的像素值被压缩,从而增强图像的整体对比度和亮部细节。
代码:
# 伽马变换增强
gamma = 1.2
gamma_img = np.power(img / 255.0, gamma) * 255.0
gamma_img = gamma_img.astype(np.uint8)
# 显示原图和增强后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Enhanced Image', gamma_img)
cv2.waitKey(0)
效果图: