3、直方图均衡化:让暗部细节亮起来

你有没有拍过这样的照片?

明明场景很美,但拍出来暗部一团黑,亮部又白得刺眼。我刚开始做图像处理时,遇到这种图第一反应就是调亮度。后来发现,单纯调亮度会把亮部也拉爆,效果反而更差。

直到我接触了直方图均衡化。说实话,这招真的很管用。它不直接调亮度,而是重新分配像素的灰度值,让暗部细节自己「跳」出来。

什么是直方图?

先聊聊直方图。说白了,它就是一张统计图。横轴是像素亮度(0到255),纵轴是每个亮度值有多少个像素。

举个例子:一张纯黑的图,直方图就是一根柱子立在0的位置。一张正常曝光的风景照,直方图会像一座小山,中间高两边低。

我在项目中遇到过一张夜景图,直方图几乎全挤在左边(暗部)。右边亮部区域几乎没像素。这种图看起来就是灰蒙蒙的,细节全藏在暗处。

核心观点:直方图均衡化的目标,就是把原本集中在某个区域的像素,均匀地「摊开」到整个亮度范围。

均衡化是怎么做到的?

原理其实不复杂。我尽量用大白话讲清楚。

假设你有一张图,像素值集中在0到50之间。均衡化会做两件事:

  1. 计算累积分布:统计每个亮度值以下有多少像素。比如亮度值10以下有1000个像素,亮度值20以下有3000个像素……
  2. 映射到新值:把累积分布的结果,映射到0到255的完整范围。原本亮度10的像素,可能会变成80;原本亮度20的,可能会变成160。

你想想看,原本挤在一起的暗部像素,被拉伸到了更宽的区间。暗部细节自然就「亮」起来了。

我的小技巧:均衡化后的直方图,看起来像一条接近水平的直线。但实际应用中,完全水平反而不好看。我一般会保留一点原始分布的特征,效果更自然。

代码实现:OpenCV 一行搞定

嗯,这里要注意。OpenCV 里实现直方图均衡化,真的就一行代码。但背后的原理你得懂,不然出了问题不知道怎么调。

import cv2
import numpy as np
import matplotlib.pyplot as plt

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

# 直方图均衡化
equ = cv2.equalizeHist(img)

# 显示结果
plt.subplot(1, 2, 1)
plt.imshow(img, cmap='gray')
plt.title('原始图像')
plt.axis('off')

plt.subplot(1, 2, 2)
plt.imshow(equ, cmap='gray')
plt.title('均衡化后')
plt.axis('off')

plt.show()

这段代码跑完,你会看到暗部明显变亮了。但别急着高兴,我踩过坑——彩色图不能直接这么搞。

警告:彩色图直接对RGB三个通道分别做均衡化,颜色会严重失真。我刚开始就犯过这个错,结果人脸变成了「阿凡达」。

正确的做法是:先把RGB转成HSV或YCrCb颜色空间,只对亮度通道做均衡化,再转回RGB。这样既提亮了暗部,又保住了颜色。

# 彩色图均衡化(正确做法)
img_color = cv2.imread('dark_photo_color.jpg')
img_yuv = cv2.cvtColor(img_color, cv2.COLOR_BGR2YUV)
img_yuv[:,:,0] = cv2.equalizeHist(img_yuv[:,:,0])
img_output = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2BGR)

直方图均衡化的知识体系

我画了一张图,帮你理清本章的核心逻辑。从输入到输出,每一步都环环相扣。

直方图均衡化核心流程 输入图像(暗部集中) 步骤1:计算灰度直方图 步骤2:计算累积分布函数 输出图像(细节增强) 关键点 像素分布统计 累积概率计算 像素值重新映射 暗部细节增强

避坑指南:我曾经踩过的三个坑

做直方图均衡化,有几个地方特别容易翻车。我一个个说。

  • 坑一:过度增强。均衡化后,原本平滑的区域会出现「块状感」。比如天空,均衡化后可能变成一块一块的。我后来加了限制对比度自适应直方图均衡化(CLAHE),才解决了这个问题。
  • 坑二:噪声放大。暗部区域本来噪声就多,均衡化把噪声也一起增强了。我的经验是:先做一次轻微的去噪,再做均衡化,效果会好很多。
  • 坑三:彩色图直接处理。前面说过了,RGB三通道分别均衡化,颜色会乱掉。记得转颜色空间。

我的推荐方案:日常用 OpenCV 的 createCLAHE() 函数。它自带限制对比度的功能,效果比普通均衡化自然得多。参数 clipLimit 我一般设2.0到3.0之间,具体看图像噪点程度。

实战效果对比

我拿一张暗部细节丰富的照片做了测试。原始图直方图集中在左侧,均衡化后分布明显均匀了。暗部的纹理、轮廓都清晰可见。

指标 原始图像 均衡化后
直方图分布 集中在暗部(0-80) 均匀分布(0-255)
暗部细节可见度
整体对比度
噪声水平 低(但细节也低) 可能略有增加

说白了,直方图均衡化就是一把双刃剑。用好了,暗部细节全出来;用不好,噪声和块状感也跟着来。我个人习惯是:先试普通均衡化,效果不满意再上CLAHE。多试几次,你就能找到手感。

专注资料整理