3. 直方图归一化处理

直方图归一化处理 学习卡片

任务说明

本案例针对一幅灰度图像,计算其灰度直方图,并将直方图各灰度级的频数除以像素总数,得到归一化的概率分布(即每个灰度级出现的概率),最后验证所有概率之和等于1。归一化直方图是直方图均衡化、规定化等后续处理的基础,它使直方图不再依赖图像尺寸,便于不同图像之间进行概率意义上的比较。

实现方案

使用Python与OpenCV读取灰度图像,通过NumPy计算直方图并完成归一化。核心步骤为:读取图像→统计各灰度级像素个数→除以总像素数得到概率→累加验证。代码不依赖任何未展示的预定义变量,输入图像路径由用户指定,若图像本身为彩色则先转换为灰度图。

输入灰度图 I(x,y), 0~255 统计直方图 h[k] = count(I==k) 归一化 p[k] = h[k] / (M×N) 验证 Σp[k] = 1.0 关键公式 灰度级 k 的概率:p(k) = h(k) / N_total,其中 N_total = 图像宽度 × 图像高度 验证条件:Σ p(k) = 1.0(浮点误差允许在 1e-6 范围内) 注:归一化后的直方图即为灰度概率分布,是后续均衡化/规定化的输入

代码实现


import cv2
import numpy as np

def normalize_histogram(image_path):
    """
    读取灰度图像,计算归一化直方图(概率分布),并验证概率之和为1。
    
    参数:
        image_path: 输入图像路径(支持彩色或灰度图,彩色图自动转灰度)
    
    返回:
        hist_prob: 长度为256的numpy数组,hist_prob[k]为灰度级k出现的概率
        total_prob: 所有概率之和(应等于1.0)
    """
    # 1. 读取图像并转为灰度
    img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    if img is None:
        raise ValueError(f"无法读取图像: {image_path}")
    
    # 2. 获取图像尺寸
    h, w = img.shape
    total_pixels = h * w
    
    # 3. 计算直方图(256个灰度级)
    hist = cv2.calcHist([img], [0], None, [256], [0, 256]).flatten()
    
    # 4. 归一化:频数 / 总像素数
    hist_prob = hist / total_pixels
    
    # 5. 验证概率之和
    total_prob = np.sum(hist_prob)
    
    return hist_prob, total_prob

# 使用示例(请将路径替换为实际图像路径)
if __name__ == "__main__":
    # 生成一张测试图像(8x8灰度图,便于人工验证)
    test_img = np.array([
        [0, 0, 1, 1, 2, 2, 3, 3],
        [0, 0, 1, 1, 2, 2, 3, 3],
        [4, 4, 5, 5, 6, 6, 7, 7],
        [4, 4, 5, 5, 6, 6, 7, 7],
        [8, 8, 9, 9, 10, 10, 11, 11],
        [8, 8, 9, 9, 10, 10, 11, 11],
        [12, 12, 13, 13, 14, 14, 15, 15],
        [12, 12, 13, 13, 14, 14, 15, 15]
    ], dtype=np.uint8)
    cv2.imwrite("test_gray.png", test_img)
    
    prob, total = normalize_histogram("test_gray.png")
    
    # 打印非零概率值(便于观察)
    print("灰度级  概率")
    for k in range(256):
        if prob[k] > 0:
            print(f"{k:3d}    {prob[k]:.4f}")
    print(f"\n概率总和: {total:.6f}")
    print(f"验证结果: {'通过' if abs(total - 1.0) < 1e-6 else '失败'}")

运行与验证

依赖环境:Python 3.6+,安装OpenCV(pip install opencv-python)和NumPy(pip install numpy)。

运行方式:直接执行上述脚本。脚本会生成一张8×8的测试图像(灰度级0~15各出现4次,共64像素),然后调用归一化函数处理该图像。

预期输出:由于测试图像中每个灰度级出现4次,总像素64个,因此每个非零灰度级的概率应为4/64=0.0625。程序将打印16个非零概率值(灰度级0~15),每个均为0.0625,最后输出概率总和为1.000000,并显示“验证结果: 通过”。

判定标准:若打印的概率总和与1.0的误差小于1e-6,且每个灰度级概率等于其像素数除以总像素数,则案例实现正确。对于任意输入图像,归一化直方图的所有概率之和恒为1(浮点精度范围内),这是概率分布的基本性质。