1.1. 为什么需要对比度增强?
对比度是图像中明暗区域之间的差异程度。高对比度的图像具有更鲜明的明暗区域,视觉效果更清晰,细节更突出。对比度增强的主要目的包括:
- 提高可视性:增强图像的对比度可以使图像更易于识别和理解。
- 改善图像质量:在光照不足或图像质量较差的情况下,对比度增强可以提升图像的细节和层次感。
- 辅助计算机视觉任务:对比度增强可以帮助提取图像特征,例如边缘和纹理,从而提升目标检测和分析的效果。
1.2. 对比度增强的原理是什么?
对比度增强的原理是通过调整图像中像素的亮度值,使图像的明暗差异更加明显。常见的方法包括:
- 线性变换:通过线性函数调整像素值,将图像的灰度范围拉伸到更宽的区间。
- 直方图均衡化:通过重新分布图像的灰度值,使直方图更加均匀,从而增强对比度。
- 自适应直方图均衡化(AHE):将图像划分为多个小区域,分别对每个区域进行直方图均衡化,以增强局部对比度。
- 限制对比度自适应直方图均衡化(CLAHE):在AHE的基础上限制对比度增强幅度,避免噪声放大。
1.3. 在 OpenCV 中如何实现对比度增强?注意事项是什么?
1.3.1. 实现方法
- 线性对比度拉伸 使用
cv2.convertScaleAbs()
函数,通过调整对比度系数(alpha
)和亮度偏移量(beta
)来增强对比度。
- alpha:对比度系数,控制图像的对比度。
-
- 默认值为 1.0。
- 增大
alpha
:对比度增强,图像的明暗差异更明显。 - 减小
alpha
:对比度减弱,图像的明暗差异变小。
- beta:亮度偏移量,控制图像的整体亮度。
-
- 默认值为 0。
- 增大
beta
:图像整体变亮。 - 减小
beta
:图像整体变暗。
python
import cv2
img = cv2.imread('image.jpg')
enhanced_img = cv2.convertScaleAbs(img, alpha=1.5, beta=0)
cv2.imshow('Enhanced Image', enhanced_img)
cv2.waitKey(0)
测试一下各参数对结果的影响:在网上照一张医学影像来测试一下
python
def showImgs(imgs_and_titles):
"""
显示图片对比函数。
参数:
imgs_and_titles: 一个包含二元组的列表,每个二元组包含 (图片, 标题)。
"""
# 每行最多显示 4 张图片
num_cols = 4
num_rows = (len(imgs_and_titles) + num_cols - 1) // num_cols # 计算需要的行数
# 创建一个足够大的画布
fig, axes = plt.subplots(num_rows, num_cols, figsize=(15, 5 * num_rows))
# 如果只有一行,axes 不是二维数组,需要处理这种情况
if num_rows == 1:
axes = [axes] # 将 axes 转换为二维数组
# 遍历所有图片和标题
for idx, (img, title) in enumerate(imgs_and_titles):
row = idx // num_cols
col = idx % num_cols
ax = axes[row][col]
# 显示图片
ax.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 转换为 RGB 格式
ax.set_title(title) # 设置标题
ax.axis("off") # 关闭坐标轴
# 隐藏剩余的空白子图
for idx in range(len(imgs_and_titles), num_rows * num_cols):
row = idx // num_cols
col = idx % num_cols
axes[row][col].axis("off")
plt.tight_layout() # 自动调整子图间距
plt.show()
def TestEnhanced():
img = cv2.imread("heart.png", 0)
imgs = [(img, "Original Image")]
alpha_betas = [ # 低对比度组
(0.1, 0.1), # 极低对比度,
(0.3, 0.1), # 低对比度,
(0.5, 0.1), # 较低对比度,
# 高对比度组
(1.2, 0.1), # 中等对比度,
(1.6, 0.1), # 较高对比度,
(2.0, 0.1), # 高对比度,
# 亮度调整组
(1.0, -50), # 原始对比度,较暗
(1.0, -20), # 原始对比度,稍暗
(1.0, 0), # 原始对比度,无亮度调整
(1.0, 20), # 原始对比度,稍亮
(1.0, 50), # 原始对比度,较亮
]
for alpha, beta in alpha_betas:
curEnhanced_img = cv2.convertScaleAbs(img, alpha=alpha, beta=beta)
imgs.append((curEnhanced_img, f"curEnhanced_img alpa={alpha} beta={beta}"))
cvTest.showImgs(imgs)

可以看到增强对比度确实可以提高图像细节,位置(2,3)增强对比度的结果与(3,4)增加亮度的结果,还是对比度增强效果要好一些,大家也可以试试其他参数。
- 直方图均衡化 使用
cv2.equalizeHist()
函数对灰度图像进行直方图均衡化。
- 输入图像必须是灰度图像:
-
cv2.equalizeHist()
函数仅适用于单通道的灰度图像。如果输入的是彩色图像,需要先将其转换为灰度图像。
- 特别适用于图像的灰度值集中在某个较窄的范围内时。
- 可能的缺陷
-
- 细节丢失:直方图均衡化是全局操作,可能会导致某些局部细节丢失,尤其是在图像的亮部和暗部。
- 过度增强:在某些情况下,直方图均衡化可能会使图像的某些部分过度增强,导致视觉效果不佳。
- 替代方法:如果需要更好地保留局部细节,可以使用自适应直方图均衡化(CLAHE),CLAHE 将图像划分为多个小块,分别对每个块进行直方图均衡化,从而避免全局均衡化的缺陷。
python
def TestContrast():
image = cv2.imread("heart.png", 0) # 读取灰度图
# enhanced_img = cv2.convertScaleAbs(image, alpha=1.5, beta=0.1) # 线性对比度拉升
equalized_img = cv2.equalizeHist(image) # 直方图均衡化
# clahe = cv2.createCLAHE(clipLimit=20.0, tileGridSize=(4, 4))
# clahe_img = clahe.apply(image) # 自适应直方图均衡化
images = [
(image, "Original Image"),
# (enhanced_img, "enhanced_img"),
(equalized_img, "equalized_img"),
# (clahe_img, "clahe_img"),
]
cvTest.showImgs(images)

可以看到:整体的亮度增加了,亮和暗的细节也有部分丢失
- CLAHE(限制对比度自适应直方图均衡化) 使用
cv2.createCLAHE()
创建CLAHE对象,并应用到图像上,关键参数如下:
clipLimit
参数
-
- 作用 :
clipLimit
是对比度限制阈值,用于控制局部对比度增强的程度。 - 影响:
- 作用 :
-
-
- 较小值(如 1.0-2.0):限制对比度增强的幅度,避免噪声放大。适用于需要保留细节的图像,但可能会导致对比度增强不够明显。
- 较大值(如 40.0):允许更强的对比度增强,但可能会放大噪声,导致图像细节丢失。
-
-
- 选择方法:通常建议从较小值(如 2.0)开始尝试,逐步增加以观察对比度增强的效果,同时注意避免噪声放大。
tileGridSize
参数
-
- 作用 :
tileGridSize
定义了图像被划分为小块的大小(以网格形式表示),决定了局部均衡化的粒度。 - 影响:
- 作用 :
-
-
- 较小值(如 (4, 4)****):图像被划分为更多小块,局部对比度增强更精细,细节更明显,但可能会出现边界伪影。
- 较大值(如 (16, 16)****):图像被划分为较少的大块,局部对比度增强更平滑,但细节保留较少。
-
-
- 选择方法 :通常建议从
(8, 8)
开始尝试,根据图像的大小和细节需求进行调整。
- 选择方法 :通常建议从
- 如何选择这两个参数?
根据图像类型选择参数:
-
-
- 医学图像或卫星图像 :需要保留细节 ,建议使用较小的
clipLimit
(如 2.0)和适中的tileGridSize
(如(8, 8)
)。 - 低对比度图像 :可以尝试较大的
clipLimit
和较小的tileGridSize
,以增强对比度。
- 医学图像或卫星图像 :需要保留细节 ,建议使用较小的
-
实验调整:
-
-
- 通过多次实验,观察不同参数组合对图像的影响,找到最适合当前图像的设置。
-
避免噪声放大:
- 在增强对比度的同时,注意观察图像中是否有噪声放大现象,适当调整
clipLimit
。
python
import cv2
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
clahe_img = clahe.apply(img)
cv2.imshow('CLAHE Image', clahe_img)
cv2.waitKey(0)
我们来验证一下同样的tileGridSize
下clipLimit
逐渐增强的效果
python
def TestCLAHE():
image_path = "heart.png"
img = cv2.imread(image_path, 0)
if img is None:
raise FileNotFoundError(f"图像文件未找到:{image_path}")
imgs = [(img, "Original Image")]
clahe_params_clipLimitUp = [
{"clipLimit": 1.0, "tileGridSize": (4, 4), "title": "CLAHE (1.0, 4x4)"},
{"clipLimit": 2.0, "tileGridSize": (4, 4), "title": "CLAHE (2.0, 4x4)"},
{"clipLimit": 40, "tileGridSize": (4, 4), "title": "CLAHE (40, 4x4)"},
]
for param in clahe_params_clipLimitUp:
clahe = cv2.createCLAHE(
clipLimit=param["clipLimit"], tileGridSize=param["tileGridSize"]
)
clahe_img = clahe.apply(img) # 自适应直方图均衡化
imgs.append((clahe_img, param["title"]))
cvTest.showImgs(imgs)

可以看到,越来越亮,但是噪声也同样放大了,特别是到40的时候噪声更明显
我们再对比一下同样的clipLimit
下,tileGridSize
增强的结果:
python
def TestCLAHE():
image_path = "heart.png"
img = cv2.imread(image_path, 0)
if img is None:
raise FileNotFoundError(f"图像文件未找到:{image_path}")
imgs = [(img, "Original Image")]
clahe_params_tileGridSizeUp = [
{"clipLimit": 2.0, "tileGridSize": (4, 4), "title": "CLAHE (1.0, 4x4)"},
{"clipLimit": 2.0, "tileGridSize": (8, 8), "title": "CLAHE (1.0, 8x8)"},
{"clipLimit": 2.0, "tileGridSize": (16, 16), "title": "CLAHE (1.0, 16x16)"},
]
for param in clahe_params_tileGridSizeUp:
clahe = cv2.createCLAHE(
clipLimit=param["clipLimit"], tileGridSize=param["tileGridSize"]
)
clahe_img = clahe.apply(img) # 自适应直方图均衡化
imgs.append((clahe_img, param["title"]))
cvTest.showImgs(imgs)

可以看到划分块的尺寸越小,细节效果越好,尺寸越大的,肉眼可见感觉噪声较大
这种医学图像需要保留较多的细节建议使用较小的 clipLimit
(如 2.0)和适中的 tileGridSize
(如 (8, 8)
)。
1.4. 注意事项
- 参数选择 :对比度增强系数(如
alpha
)和直方图均衡化的参数(如clipLimit
)需要根据具体图像调整,避免过度增强或欠增强。 - 图像类型:直方图均衡化适用于灰度图像,对于彩色图像需要分别对每个通道进行处理。
- 噪声问题:AHE和CLAHE可能会放大图像噪声,特别是在均匀区域,需要谨慎使用。