1. 直方图基础:图像直方图的概念、统计原理与可视化

聊图像处理,直方图是绕不开的第一个坎儿。我刚开始接触这个领域时,总觉得直方图不就是个柱状图嘛,有啥好讲的?后来做项目才发现,这玩意儿是理解图像质量的一把钥匙。说白了,直方图就是图像的「体检报告」——它告诉你这张图的亮度分布到底健不健康。

1.1 什么是图像直方图

图像直方图,统计的是图像中每个灰度级出现的频次。对于一张 8 位深度的灰度图,灰度范围是 0~255,共 256 个级别。直方图的横轴是灰度级,纵轴是该灰度级出现的像素个数(或概率)。

举个例子。一张 4×4 的 tiny 图像:

像素矩阵:
[50, 50, 100, 100]
[50, 100, 100, 150]
[50, 50, 100, 150]
[50, 100, 100, 150]

直方图统计:
灰度 50 → 出现 6 次
灰度 100 → 出现 6 次
灰度 150 → 出现 4 次
其他灰度 → 0 次

你看,直方图把图像从「空间域」映射到了「统计域」。空间信息丢了,但亮度分布一目了然。

核心要点: 直方图不关心像素在哪儿,只关心每个亮度值有多少像素。这种「丢位置保分布」的特性,正是后续做直方图均衡化的理论基础。

1.2 统计原理与数学表达

严格来说,直方图是一个离散函数:

h(r_k) = n_k,  k = 0, 1, 2, ..., L-1

其中:

  • r_k — 第 k 个灰度级
  • n_k — 图像中灰度级为 r_k 的像素个数
  • L — 灰度级总数(8 位图就是 256)

归一化直方图更常用:

p(r_k) = n_k / N

N 是图像总像素数。p(r_k) 就是灰度级 r_k 出现的概率,所有 p(r_k) 之和为 1。归一化后,直方图就变成了概率分布函数,方便后续做数学变换。

我的习惯: 做直方图分析时,我一般先看归一化直方图。因为不同尺寸的图像,原始频次没法直接比,归一化后才有可比性。之前有个项目,两张图尺寸差 10 倍,直接比频次差点闹笑话。

1.3 直方图的可视化方法

可视化直方图,最常用的是柱状图。但这里有个细节——图像直方图的横轴是连续的灰度值,所以用「条形图」比「柱状图」更准确。每个灰度级一根竖线,线高代表频次。

用 Python 画直方图,我习惯用 OpenCV 算直方图,Matplotlib 画图。给你看代码:

import cv2
import matplotlib.pyplot as plt

# 读取灰度图
img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)

# 计算直方图
hist = cv2.calcHist([img], [0], None, [256], [0, 256])

# 可视化
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.imshow(img, cmap='gray')
plt.title('原始图像')
plt.axis('off')

plt.subplot(1, 2, 2)
plt.plot(hist, color='black')
plt.title('灰度直方图')
plt.xlabel('灰度级')
plt.ylabel('像素个数')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

这里我用了 plt.plot 而不是 plt.bar。为什么?因为 256 根柱子挤在一起根本看不清,折线图反而更清晰。嗯,这是个小技巧。

1.4 直方图的四种典型形态

我在项目中总结过,直方图大致有四种典型形态。每种形态都对应着图像的某种「病症」:

形态 特征 图像表现 常见场景
窄峰型 像素集中在狭窄灰度范围 对比度低,画面发灰 雾天拍摄、欠曝/过曝
双峰型 两个明显峰值 前景与背景分离明显 文档扫描、显微图像
偏左型 峰值靠近 0(暗区) 整体偏暗,细节丢失 夜景、逆光拍摄
偏右型 峰值靠近 255(亮区) 整体偏亮,高光溢出 雪景、强光环境
我曾经踩过的坑: 有次做工业质检,一张金属表面的图像直方图看起来是完美的「均匀分布」,我以为是好信号。结果发现是光照不均匀导致的假象——局部过亮和过暗的区域互相抵消了。所以,全局直方图好看不代表局部没问题。这也是为什么后来要做局部直方图处理。

1.5 直方图与图像质量的关系

直方图能直接反映图像的三个关键质量指标:

  • 亮度 — 直方图的整体位置偏左还是偏右
  • 对比度 — 直方图的宽度和分布均匀程度
  • 动态范围 — 直方图覆盖的灰度级范围

你想想看,一张好图的直方图应该长什么样?理想情况下,它应该覆盖整个灰度范围,且分布相对均匀。但现实中很少这么完美。直方图均衡化,就是要把「不完美」的分布,强行拉成「均匀」分布。

1.6 本章知识结构

下面这张图,是我梳理的直方图基础知识体系。你看一遍,心里就有谱了:

直方图基础知识体系 图像直方图 概念与定义 统计原理 可视化方法 灰度级与像素频次 空间域 → 统计域映射 离散函数 h(r_k) = n_k 归一化概率 p(r_k) = n_k / N 柱状图 / 折线图 OpenCV + Matplotlib 应用:图像质量评估 → 直方图均衡化 💡 直方图是后续所有增强技术的基础,务必吃透 四种典型形态:窄峰型 | 双峰型 | 偏左型 | 偏右型

1.7 直方图的实际应用场景

直方图不只是理论概念。我在实际项目中,至少遇到过这些场景:

  • 曝光检测 — 直方图偏左或偏右,直接提示曝光问题
  • 对比度评估 — 直方图越窄,对比度越低,图像越「灰」
  • 阈值分割 — 双峰直方图的谷底,是最佳分割阈值
  • 图像匹配 — 通过直方图相似度做图像检索
  • 预处理诊断 — 做增强前,先看直方图判断该用什么方法
我的建议: 拿到一张图,别急着调算法。先画直方图,看 3 秒。你就能判断这张图是欠曝、过曝、还是对比度不足。这个习惯,能帮你省掉大量试错时间。