Python数字图像处理:直方图均衡化

直方图均衡化(Histogram Equalization)是一种通过调整图像灰度分布来增强图像对比度的经典方法,尤其在处理低对比度或光照不均匀的图像时效果显著。本文深入解析其数学原理,并提供手动实现OpenCV优化方案的完整代码,结合实际应用场景展示其核心价值。

1. 直方图均衡化原理

(1) 核心目标
  • 问题:图像灰度集中在狭窄范围 → 细节模糊。
  • 解决方案 :将原始直方图变换为均匀分布,扩展动态范围。
(2) 数学推导
  1. 概率密度函数(PDF)
    统计各灰度级频数:
  1. 累积分布函数(CDF)

映射到新的灰度级,使新直方图接近均匀分布。

2. 手动实现直方图均衡化

(2.1) 灰度图像处理
复制代码
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置字体为黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

def manual_hist_equalize(image):
    if len(image.shape) == 3:
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    hist = cv2.calcHist([image], [0], None, [256], [0, 256])
    hist_norm = hist.ravel() / hist.sum()  # 归一化得到PDF
    cdf = hist_norm.cumsum()               # 计算CDF
    cdf_normalized = (cdf * 255).astype(np.uint8)  # 线性映射到0-255
    return cdf_normalized[image]  # 应用映射

# 使用示例
img = cv2.imread('5.bmp', cv2.IMREAD_GRAYSCALE)

if img is None:
    print("错误:无法加载图像,请检查文件路径。")
else:
    equalized_manual = manual_hist_equalize(img)

    # 显示原始图像和直方图均衡化后的图像
    plt.figure(figsize=(10, 5))

    plt.subplot(1, 2, 1)
    plt.title('原始图像')  # 中文标题
    plt.imshow(img, cmap='gray')

    plt.subplot(1, 2, 2)
    plt.title('手动直方图均衡化图像')  # 中文标题
    plt.imshow(equalized_manual, cmap='gray')

    plt.show()
(2.2) 关键步骤解析
步骤 功能 代码实现
统计直方图 计算各灰度级像素数量 cv2.calcHist
归一化PDF 转换为概率分布 hist_norm = hist / total
计算CDF 累加概率密度,生成映射函数 cdf = np.cumsum(hist_norm)
应用映射 将原图灰度替换为CDF对应值 equalized = cdf[original]

3. OpenCV高效实现

复制代码
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置字体为黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 灰度图直方图均衡化
def gray_hist_equalize(image):
    if len(image.shape) == 3:
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    equalized = cv2.equalizeHist(image)
    return equalized

# 彩色图直方图均衡化
def color_hist_equalize(image):
    # 将图像转换为 YCrCb 色彩空间
    ycrcb = cv2.cvtColor(image, cv2.COLOR_BGR2YCrCb)
    # 对 Y 通道进行直方图均衡化
    ycrcb[:, :, 0] = cv2.equalizeHist(ycrcb[:, :, 0])
    # 转换回 BGR 色彩空间
    equalized = cv2.cvtColor(ycrcb, cv2.COLOR_YCrCb2BGR)
    return equalized

# 加载图像
img = cv2.imread('5.bmp')

if img is None:
    print("错误:无法加载图像,请检查文件路径。")
else:
    # 灰度图处理
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    gray_equalized = gray_hist_equalize(img)

    # 彩色图处理
    color_equalized = color_hist_equalize(img)

    # 将 BGR 图像转换为 RGB 图像(matplotlib 使用 RGB 格式)
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    color_equalized_rgb = cv2.cvtColor(color_equalized, cv2.COLOR_BGR2RGB)

    # 使用 matplotlib 显示图像
    plt.figure(figsize=(15, 10))

    # 显示原始图像
    plt.subplot(2, 2, 1)
    plt.imshow(img_rgb)
    plt.title('原始彩色图像')
    plt.axis('off')

    # 显示原始灰度图像
    plt.subplot(2, 2, 2)
    plt.imshow(gray_img, cmap='gray')
    plt.title('原始灰度图像')
    plt.axis('off')

    # 显示灰度直方图均衡化图像
    plt.subplot(2, 2, 4)
    plt.imshow(gray_equalized, cmap='gray')
    plt.title('灰度直方图均衡化图像')
    plt.axis('off')

    # 显示彩色直方图均衡化图像
    plt.subplot(2, 2, 3)
    plt.imshow(color_equalized_rgb)
    plt.title('彩色直方图均衡化图像')
    plt.axis('off')

    # 显示图像
    plt.tight_layout()
    plt.show()
相关推荐
又是忙碌的一天19 小时前
java字符串
java·开发语言
Hi2024021719 小时前
Qt+Qml客户端和Python服务端的网络通信原型
开发语言·python·qt·ui·网络通信·qml
chxii19 小时前
ISO 8601日期时间标准及其在JavaScript、SQLite与MySQL中的应用解析
开发语言·javascript·数据库
Teable任意门互动19 小时前
主流多维表格产品深度解析:飞书、Teable、简道云、明道云、WPS
开发语言·网络·开源·钉钉·飞书·开源软件·wps
王哈哈^_^19 小时前
【数据集】【YOLO】【目标检测】农作物病害数据集 11498 张,病害检测,YOLOv8农作物病虫害识别系统实战训推教程。
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·1024程序员节
xier_ran19 小时前
邻接矩阵的 k 次幂意味着什么?从图论到路径计数的直观解释
算法·图论
程序员大雄学编程20 小时前
「用Python来学微积分」16. 导数问题举例
开发语言·python·数学·微积分
B站_计算机毕业设计之家20 小时前
预测算法:股票数据分析预测系统 股票预测 股价预测 Arima预测算法(时间序列预测算法) Flask 框架 大数据(源码)✅
python·算法·机器学习·数据分析·flask·股票·预测
Dreams_l20 小时前
redis中的数据类型
java·开发语言
梵得儿SHI20 小时前
Java IO 流详解:字符流(Reader/Writer)与字符编码那些事
java·开发语言·字符编码·工作原理·字符流·处理文本