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。归一化后,直方图就变成了概率分布函数,方便后续做数学变换。
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 本章知识结构
下面这张图,是我梳理的直方图基础知识体系。你看一遍,心里就有谱了:
1.7 直方图的实际应用场景
直方图不只是理论概念。我在实际项目中,至少遇到过这些场景:
- 曝光检测 — 直方图偏左或偏右,直接提示曝光问题
- 对比度评估 — 直方图越窄,对比度越低,图像越「灰」
- 阈值分割 — 双峰直方图的谷底,是最佳分割阈值
- 图像匹配 — 通过直方图相似度做图像检索
- 预处理诊断 — 做增强前,先看直方图判断该用什么方法