2. 图像对比度增强

任务说明

本案例针对低对比度图像(如雾天、背光、医学影像等场景),通过对比度增强使图像特征更明显。核心目标是:给定一张输入图像,输出对比度增强后的图像,并验证增强前后像素灰度分布的变化。

实现方案

采用两种互补的对比度增强方法,并允许用户选择:

  • 线性拉伸(Min-Max Stretch):将灰度范围线性映射到[0,255],简单高效,适合整体偏灰的图像。
  • 直方图均衡化(Histogram Equalization):通过累积分布函数重映射灰度,自动增强全局对比度,对低对比度图像效果显著。

使用OpenCV实现,代码可直接运行,无需额外数据集——使用内置的cv2.imread读取任意本地图像即可。

环境依赖

pip install opencv-python numpy matplotlib

完整代码

import cv2
import numpy as np
import matplotlib.pyplot as plt

def linear_stretch(img_gray):
    """线性拉伸:将灰度范围映射到[0,255]"""
    min_val = np.min(img_gray)
    max_val = np.max(img_gray)
    if max_val == min_val:
        return img_gray.copy()
    stretched = (img_gray.astype(np.float32) - min_val) * 255.0 / (max_val - min_val)
    return stretched.astype(np.uint8)

def histogram_equalization(img_gray):
    """直方图均衡化"""
    return cv2.equalizeHist(img_gray)

def process_image(image_path, method='equalize'):
    """
    主处理函数
    method: 'stretch' 或 'equalize'
    """
    # 读取图像(灰度)
    img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    if img is None:
        raise FileNotFoundError(f"无法读取图像: {image_path}")

    # 执行增强
    if method == 'stretch':
        enhanced = linear_stretch(img)
    elif method == 'equalize':
        enhanced = histogram_equalization(img)
    else:
        raise ValueError("method 参数必须为 'stretch' 或 'equalize'")

    # 保存结果
    out_path = f"enhanced_{method}.jpg"
    cv2.imwrite(out_path, enhanced)

    # 可视化对比(原图、增强图、直方图)
    fig, axes = plt.subplots(2, 2, figsize=(10, 8))
    axes[0, 0].imshow(img, cmap='gray')
    axes[0, 0].set_title('Original')
    axes[0, 0].axis('off')

    axes[0, 1].imshow(enhanced, cmap='gray')
    axes[0, 1].set_title(f'Enhanced ({method})')
    axes[0, 1].axis('off')

    axes[1, 0].hist(img.ravel(), bins=256, range=(0, 255), color='blue', alpha=0.7)
    axes[1, 0].set_title('Original Histogram')

    axes[1, 1].hist(enhanced.ravel(), bins=256, range=(0, 255), color='red', alpha=0.7)
    axes[1, 1].set_title('Enhanced Histogram')

    plt.tight_layout()
    plt.savefig(f"comparison_{method}.png", dpi=150)
    plt.show()

    # 输出灰度范围统计
    print(f"原图灰度范围: [{np.min(img)}, {np.max(img)}]")
    print(f"增强后灰度范围: [{np.min(enhanced)}, {np.max(enhanced)}]")
    print(f"原图标准差: {np.std(img):.2f}")
    print(f"增强后标准差: {np.std(enhanced):.2f}")
    print(f"结果已保存: {out_path}")

if __name__ == "__main__":
    # 使用示例:替换为你的低对比度图像路径
    process_image("low_contrast.jpg", method="equalize")
    # process_image("low_contrast.jpg", method="stretch")  # 可选线性拉伸

运行与验证

  1. 准备一张低对比度图像(如雾天风景、背光照片),命名为low_contrast.jpg,放在与脚本相同的目录下。
  2. 运行脚本:python contrast_enhance.py
  3. 观察弹出的对比图窗口,检查:
  • 增强后图像视觉上是否更清晰、细节更明显;
  • 直方图是否从集中在狭窄区间变为覆盖更宽的灰度范围;
  • 控制台输出的标准差是否显著增大(标准差越大,对比度越高)。

通过条件:增强后图像灰度范围接近[0,255],标准差相比原图明显提升,且直方图分布更均匀,即视为增强成功。

预期输出示例

原图灰度范围: [52, 178]
增强后灰度范围: [0, 255]
原图标准差: 28.34
增强后标准差: 74.12
结果已保存: enhanced_equalize.jpg

以上数值仅为逻辑一致的示例——实际结果取决于输入图像,但灰度范围扩展和标准差增大是必然趋势。

对比度增强效果示意 原图(低对比度) 灰度范围窄(如52~178) 增强后(高对比度) 灰度范围扩展(0~255) 灰度直方图对比 原图 增强后 原图分布 增强后分布

常见问题

  • 增强后出现噪点:直方图均衡化可能放大噪声。若图像噪声明显,可先做轻微高斯模糊(cv2.GaussianBlur)再增强。
  • 线性拉伸效果不明显:说明原图灰度范围已接近[0,255],此时应改用直方图均衡化。
  • 彩色图像处理:本案例针对灰度图。若需处理彩色图,可先转换到HSV色彩空间,仅对V通道增强后合并。