OpenCV对比度增强

1.1. 为什么需要对比度增强?

对比度是图像中明暗区域之间的差异程度。高对比度的图像具有更鲜明的明暗区域,视觉效果更清晰,细节更突出。对比度增强的主要目的包括:

  • 提高可视性:增强图像的对比度可以使图像更易于识别和理解。
  • 改善图像质量:在光照不足或图像质量较差的情况下,对比度增强可以提升图像的细节和层次感。
  • 辅助计算机视觉任务:对比度增强可以帮助提取图像特征,例如边缘和纹理,从而提升目标检测和分析的效果。

1.2. 对比度增强的原理是什么?

对比度增强的原理是通过调整图像中像素的亮度值,使图像的明暗差异更加明显。常见的方法包括:

  • 线性变换:通过线性函数调整像素值,将图像的灰度范围拉伸到更宽的区间。
  • 直方图均衡化:通过重新分布图像的灰度值,使直方图更加均匀,从而增强对比度。
  • 自适应直方图均衡化(AHE):将图像划分为多个小区域,分别对每个区域进行直方图均衡化,以增强局部对比度。
  • 限制对比度自适应直方图均衡化(CLAHE):在AHE的基础上限制对比度增强幅度,避免噪声放大。

1.3. 在 OpenCV 中如何实现对比度增强?注意事项是什么?

1.3.1. 实现方法

  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)增加亮度的结果,还是对比度增强效果要好一些,大家也可以试试其他参数。

  1. 直方图均衡化 使用 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)

可以看到:整体的亮度增加了,亮和暗的细节也有部分丢失

  1. 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)

我们来验证一下同样的tileGridSizeclipLimit 逐渐增强的效果

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可能会放大图像噪声,特别是在均匀区域,需要谨慎使用。
相关推荐
东木月2 分钟前
windows安装pytorch
人工智能·pytorch·windows
小白教程3 分钟前
Python连接MySQL数据库图文教程,Python连接数据库MySQL入门教程
数据库·python·mysql·python链接数据库·python链接mysql
weixin_307779133 分钟前
PySpark实现GROUP BY WITH CUBE和WITH ROLLUP的分类汇总功能
大数据·开发语言·python·spark
wheelmouse77888 分钟前
AI IDE 使用体验及 AI 感受
ide·人工智能
周博洋K24 分钟前
SSI用量子计算来玩AI
人工智能·量子计算
不太会写33 分钟前
基于Python+django+mysql旅游数据爬虫采集可视化分析推荐系统
python·推荐算法
IT猿手42 分钟前
2025高维多目标优化:基于导航变量的多目标粒子群优化算法(NMOPSO)的无人机三维路径规划,MATLAB代码
开发语言·人工智能·算法·机器学习·matlab·无人机·cocos2d
呱牛do it1 小时前
Python Matplotlib图形美化指南
开发语言·python·matplotlib
pianmian11 小时前
python制图之小提琴图
开发语言·python·信息可视化
橙子小哥的代码世界1 小时前
【机器学习】【KMeans聚类分析实战】用户分群聚类详解——SSE、CH 指数、SC全解析,实战电信客户分群案例
人工智能·python·机器学习·kmeans·数据科学·聚类算法·肘部法