新闻  |   论坛  |   博客  |   在线研讨会
【计算机视觉】什么是直方图均衡化?
MrWinter | 2022-03-01 14:47:13    阅读:7410   发布文章

计算机视觉教程之直方图均衡化原理


1 点算子

点算子是两个像素灰度值间的映射关系,属于像素的逐点运算,相邻像素不参与运算。点算子是最简单的图像处理手段,如:亮度调整、对比度调整、颜色变换、直方图均衡化等等。


2 线性灰度变换

线性灰度变换表达为:


image.png


其中$r_k$、$s_k$分别为输入、输出点像素灰度值。


image.png


当$a>1$时,输出图像像素灰度范围扩大,图像对比度增强,当$a<1$时反之。这是因为<font color=#F00>**人眼不易区分相近的灰度值**</font>,因此若图像灰度值范围较小,观感上细节不够清晰。当$a=1$、$b\ne0$时,点算子使图像灰度整体上移或下移,即整体变亮或变暗。


image.png


3 直方图均衡化

下图再次给出了关于图像对比度的例子


image.png


直方图均衡化是以累计分布函数为核心,将原始图像灰度直方图从比较集中的某个灰度区间,非线性地映射为在全部灰度范围内的较均匀分布,从而增强对比度


下面阐述直方图均衡化的数学原理。首先作原始图像灰度的概率直方图如图


image.png


设输入像素灰度值为$r_k$,累计分布函数为

$$C\left( r_k \right) =\frac{1}{n}\sum_{i=0}^k{n_i}$$


其中$n_i$为图像中灰度值为$r_i$的像素频数,$n$为图像像素总数。设输出像素灰度值为$s_k$,像素范围为$s_{min}-s_{max}$。期望输出灰度直方图是均匀分布,即


$$P\left( s \right) =\frac{1}{s_{\max}-s_{\min}}\,\,   s_{\min}\leqslant s\leqslant s_{\max}$$


令$C\left( s_k \right) =C\left( r_k \right)$,即得


$$\left( C\left( r_k \right) _{\max}-C\left( r_k \right) _{\min} \right) \frac{s_k-s_{\min}}{s_{\max}-s_{\min}}+C\left( r_k \right) _{\min}=C\left( r_k \right) \\\Rightarrow \,\,                                            \frac{s_k-s_{\min}}{s_{\max}-s_{\min}}=\frac{C\left( r_k \right) -C\left( r_k \right) _{\min}}{C\left( r_k \right) _{\max}-C\left( r_k \right) _{\min}}\\\Rightarrow \,\,                                            \frac{s_k-s_{\min}}{s_{\max}-s_{\min}}=C'\left( r_k \right)$$


所以最终直方图均衡化的点算子为


$$s_k=\left( s_{\max}-s_{\min} \right) C'\left( r_k \right) +s_{\min}=T\left( r_k \right)$$


# 4 代码实战

按照前文的原理编写累积分布函数计算公式,以及均衡化算子


```python

# 计算累计分布函数

def C(rk):

  # 读取图片灰度直方图

  # bins为直方图直方柱的取值向量

  # hist为bins各取值区间上的频数取值

  hist, bins = np.histogram(rk, 256, [0, 256])

  # 计算累计分布函数

  return hist.cumsum()

```


```python

# 计算灰度均衡化映射

def T(rk):

  cdf = C(rk)

  # 均衡化

  cdf = (cdf - cdf.min()) * (255 - 0) / (cdf.max() - cdf.min()) + 0

  return cdf.astype('uint8')

```


<font size=4 color=#000>均衡化时直接调用函数即可,下面给出完整代码


```python

import numpy as np

import cv2 as cv

from matplotlib import pyplot as plt


# 计算累计分布函数

def C(rk):

  # 读取图片灰度直方图

  # bins为直方图直方柱的取值向量

  # hist为bins各取值区间上的频数取值

  hist, bins = np.histogram(rk, 256, [0, 256])

  # 计算累计分布函数

  return hist.cumsum()


# 计算灰度均衡化映射

def T(rk):

  cdf = C(rk)

  # 均衡化

  cdf = (cdf - cdf.min()) * (255 - 0) / (cdf.max() - cdf.min()) + 0

  return cdf.astype('uint8')



# 读取图片

img = cv.imread('1.png', 0)

# 将二维数字图像矩阵转变为一维向量

rk = img.flatten()


# 原始图像灰度直方图

plt.hist(rk, 256, [0, 255], color = 'r')

cv.imshow("原图像",img)


# 直方图均衡化

imgDst = T(rk)[img]

cv.imshow("直方图均衡化后的图像",imgDst)

plt.hist(imgDst.flatten(), 256, [0, 255], color = 'b')


plt.show()

```


看看效果:


image.png

均衡化前:


image.png



均衡化后:



image.png


更多优质内容、更好的阅读体验、完整配套代码详见下方公众号“AI技术社”


image.png



*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客