3. 直方图基础
聊到光照校正,有个东西绕不开——直方图。
我刚开始做图像处理那会儿,总觉得直方图就是个统计图,没啥大用。后来在项目中调一个低照度视频的增强算法,调了三天效果都不对。最后画了张直方图一看,好家伙,像素全挤在暗区,亮部几乎空白。那一刻我才真正理解:直方图就是图像的“体检报告”。
3.1 图像直方图的定义
说白了,直方图就是统计图像里每个灰度级出现了多少个像素。
对于一张 8 位灰度图,灰度范围是 0~255,共 256 个灰度级。直方图就是一个离散函数:
h(r_k) = n_k
其中 r_k 是第 k 个灰度级,n_k 是灰度级为 r_k 的像素个数。
核心要点:直方图只反映像素的分布频率,不包含像素的空间位置信息。也就是说,两张内容完全不同的图,直方图可能一模一样。
举个例子:一张全白的图和一张棋盘格图,如果黑白像素比例相同,它们的直方图就一样。嗯,这里要注意——直方图是全局统计,不是局部特征。
3.2 灰度直方图的绘制
画直方图其实很简单。我习惯用 Python 的 matplotlib 配合 OpenCV 来做。给你看个标准流程:
import cv2
import matplotlib.pyplot as plt
# 读取灰度图
img = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
# 方法一:用 OpenCV 计算直方图
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
# 方法二:用 numpy 直接统计(更直观)
import numpy as np
hist_np, bins = np.histogram(img.ravel(), 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.xlim([0, 255])
plt.tight_layout()
plt.show()
我的习惯:实际项目中我更喜欢用 plt.bar() 画柱状图,因为柱状图能更直观地看到每个灰度级的“堆积”情况。但数据量大时建议用折线图,渲染快很多。
你想想看,一张 1920×1080 的图,有 200 多万个像素。如果一个个看像素值,眼睛会瞎。但一张直方图,一眼就能看出图像的整体亮度倾向。
3.3 直方图与图像亮度的关系
这是实战中最常用的技能。我总结了一个经验:看直方图的“重心”位置,就能判断图像是偏亮还是偏暗。
| 直方图特征 | 图像表现 | 典型场景 |
|---|---|---|
| 像素集中在低灰度区(0~80) | 图像偏暗,细节隐藏在暗部 | 夜间监控、背光拍摄 |
| 像素集中在高灰度区(180~255) | 图像偏亮,可能过曝 | 强光下拍摄、雪景 |
| 像素分布均匀(0~255 都有) | 图像对比度好,细节丰富 | 正常光照下的标准图 |
| 像素集中在中间灰度区(80~180) | 图像偏灰,对比度低 | 雾天、阴天拍摄 |
| 直方图出现多个“峰” | 图像包含多个亮度层次 | 逆光人像、明暗交界场景 |
我曾经踩过的坑:有一次做工业质检,产品表面有划痕,但直方图看起来很正常。后来才发现,划痕只占图像面积的 0.3%,在直方图上根本看不出来。所以记住:直方图对大面积分布敏感,对小目标不敏感。做缺陷检测时,不能只依赖直方图。
为什么会这样?因为直方图是全局统计。一个占 99% 的背景和占 1% 的前景,在直方图上背景会“淹没”前景。这时候就需要用局部直方图或者空间域的方法来补充。
3.4 知识结构图:直方图核心体系
我把这一章的核心逻辑画成了一张图,方便你理解直方图在整个光照校正中的位置:
3.5 实战小技巧:快速判断图像质量
在项目中,我经常用直方图做快速筛查。给你几个实用判断:
- 看峰值位置:峰值在 0 附近,大概率欠曝;峰值在 255 附近,大概率过曝。
- 看分布宽度:分布越宽,对比度越高;分布越窄,图像越“灰”。
- 看是否有“断崖”:直方图两端突然截断,说明有像素被裁剪(过曝或欠曝严重)。
- 看多峰形态:多个峰值说明场景中有多个亮度层次,比如逆光人像。
我的工作流:拿到一张图,先画直方图,3 秒内就能决定要不要做光照校正。如果直方图分布均匀,直接跳过预处理;如果像素挤在一头,再考虑用直方图均衡化或 Gamma 校正。这能省下大量不必要的计算时间。