Python版本是Python3.7.3,OpenCV版本OpenCV3.4.1,开发环境为PyCharm

直方图均衡化
如果一幅图像拥有全部可能的灰度级,并且像素值的灰度均匀分布,那么这幅图像就具有高对比度和多变的灰度色调,灰度级丰富且覆盖范围较大。在外观上,这样的图像具有更丰富的色彩,不会过暗或过亮。
下图展示了对一幅图像进行直方图均衡化前后的对比,左图是原始图像,比较暗;右图是均衡化后的图像,色彩比较均衡。

png图像直方图均衡化python python opencv 直方图均衡_Python-OpenCV


在OpenCV的官网上,对图像均衡化(即直方图均衡化)前后的直方图进行了对比,如下图所示。其中,左图是原始图像的直方图,可以看到灰度级集中在中间,图像中没有较暗和较亮的像素点;右图是对原图均衡化后的直方图,像素分布更均衡。

png图像直方图均衡化python python opencv 直方图均衡_png图像直方图均衡化python_02

直方图均衡化的主要目的是将原始图像的灰度级均匀地映射到整个灰度级范围内,得到一个灰度级分布均匀的图像。这种均衡化,既实现了灰度值统计上的概率均衡,也实现了人类视觉系统(Human Visual System, HVS)上的视觉均衡。

例如,在某幅图像内仅仅出现了1、2、3、101、102、103等6个像素值,其分布分别如下表中的情况A和情况B所示。

png图像直方图均衡化python python opencv 直方图均衡_Python-OpenCV_03

下面分别讨论这两种情况下像素值均衡的情况。
● 情况A:每一个灰度级在图像内出现的次数都是1,灰度级均匀地映射到当前的灰度级范围内,所以可以理解为其直方图是均衡的。
● 情况B:灰度级1、2、3出现的次数都是1次,灰度级103出现的次数是3次,灰度级101、102出现的次数是0次。从表面上看,灰度级是不均衡的。但是,从HVS的角度来说,人眼的敏感度不足以区分1个像素值的差异,即人眼会将灰度级1、2和3看作是相同的,会将灰度级101、102和103看作是相同的。也就是说,HVS会自动地将灰度级划分为两组,灰度级[1, 3]为一组,灰度级[101, 103]为另一组。在整幅图像内,这两组的灰度级出现的次数都是3次,概率是相等的。在均衡化处理中,综合考虑了统计概率和HVS的均衡。

直方图均衡化原理

直方图均衡化的算法主要包括两个步骤:

(1)计算累计直方图。

(2)对累计直方图进行区间转换

在此基础上,再利用人眼视觉达到直方图均衡化的目的。

下面我们通过一个例子进行讲解。例如,图像A如下图所示,它是一幅3位的位图,即共有8(23)个灰度级,有49个像素。

png图像直方图均衡化python python opencv 直方图均衡_直方图均衡化原理_04

图像A共有8个灰度级,范围为[0, 7],计算其统计直方图如下表所示。

png图像直方图均衡化python python opencv 直方图均衡_图像处理_05

在此基础上,计算归一化统计直方图,计算方式是计算每个像素在图像内出现的概率。出现概率=出现次数/像素总数,用每个灰度级的像素个数除以总的像素个数(49),就得到归一化统计直方图,如下表所示。

png图像直方图均衡化python python opencv 直方图均衡_直方图均衡化原理_06

接下来,计算累计统计直方图,即计算所有灰度级的累计概率,结果如下表所示。

png图像直方图均衡化python python opencv 直方图均衡_均衡化_07

在累计直方图的基础上,对原有灰度级空间进行转换。可以在原有范围内对灰度级实现均衡化,也可以在更广泛的灰度空间范围内对灰度级实现均衡化。下面分别介绍这两种形式。

1.在原有范围内实现均衡化
在原有范围内实现直方图均衡化时,用当前灰度级的累计概率乘以当前灰度级的最大值7,得到新的灰度级,并作为均衡化的结果。下表所示的就是计算得到的新灰度级。

png图像直方图均衡化python python opencv 直方图均衡_图像处理_08


根据表中各个灰度级的关系,完成均衡化值(新的灰度级)的映射,如下表所示。此处的对应关系为:

● 原始图像A中的灰度级0,经直方图均衡化后调整为新的灰度级1(即均衡化值1)。在原始图像A中,灰度级0共有9个像素点,所以在均衡化后的图像中,灰度级1共有9个像素点。

● 原始图像A中的灰度级1和2经直方图均衡化后调整为灰度级3。在原始图像A中,灰度级1共有9个像素点,灰度级2共有6个像素点,所以在均衡化后的图像中,灰度级3共有9 + 6=15个像素点。

● 原始图像A中的灰度级3经直方图均衡化后调整为灰度级4。在原始图像A中,灰度级3共有5个像素点,所以在均衡化后的图像中,灰度级4共有5个像素点。

● 原始图像A中的灰度级4和5经直方图均衡化后调整为灰度级5。在原始图像A中,灰度级4共有6个像素点,灰度级5共有3个像素点,所以在均衡化后的图像中,灰度级5共有6 + 3=9个像素点。

● 原始图像A中的灰度级6经直方图均衡化后调整为灰度级6。在原始图像A中,灰度级6共有3个像素点,所以在均衡化后的图像中,灰度级6共有3个像素点。

● 原始图像A中的灰度级7经直方图均衡化后调整为灰度级7。在原始图像A中,灰度级7共有8个像素点,所以在均衡化后的图像中,灰度级7共有8个像素点。

png图像直方图均衡化python python opencv 直方图均衡_Python-OpenCV_09

在均衡化后的图像中,不存在灰度级0和灰度级2的像素点。
根据上述关系,可以得到下表。其中列出了直方图均衡化后每个灰度级的像素个数。

png图像直方图均衡化python python opencv 直方图均衡_直方图均衡化原理_10

经过均衡化处理后,灰度级在整个灰度空间内的分布会更均衡。下图所示的是直方图均衡化前后的对比图。其中,左图是均衡化之前的直方图,右图是均衡化之后的直方图。

png图像直方图均衡化python python opencv 直方图均衡_Python-OpenCV_11


从图中可以看出,右图的灰度级在整个灰度空间内分布更均衡。值得注意的,这里的均衡化是综合考虑了统计概率和HVS的结果。

● 在图像A中,未进行直方图均衡化之前:灰度级0 - 3之间的像素个数为29个,灰度级4~7之间的像素个数为20个。

● 对图像A进行直方图均衡化之后:灰度级0~ 3之间的像素个数为24个,灰度级4~7之间的像素个数为25个。

通过上述比较,可以看出,直方图均衡化之后图像的灰度级分布更均衡了。2.在更广泛的范围内实现均衡化

在更广泛的范围内实现直方图均衡化时,用当前灰度级的累计概率乘以更广泛范围灰度级的最大值,得到新的灰度级,并作为均衡化的结果。例如,要将灰度级空间扩展为[0, 255]共256个灰度级,就必须将原灰度级的累计概率乘以255,得到新的灰度级。下表所示的是图像A在新的灰度级空间[0, 255]内的新的灰度级。

png图像直方图均衡化python python opencv 直方图均衡_图像处理_12

经过均衡化处理后,图像A的灰度级在新灰度空间[0,255]内保持均衡。下图所示的是对图像A进行均衡化前的直方图,灰度级集中在[0, 7]之内。

png图像直方图均衡化python python opencv 直方图均衡_均衡化_13

下图所示的是均衡化后的直方图,灰度级在整个灰度空间[0, 255]内分布得更均衡。

png图像直方图均衡化python python opencv 直方图均衡_png图像直方图均衡化python_14

通过上述分析可知,通过如下两个步骤:

(1)计算累计直方图。

(2)将累计直方图进行区间转换。

可以让直方图达到均衡化的效果。

下面我们用数学表达式描述以上的直方图均衡化过程。假设图像中像素的总数是N,图像的灰度级数是L,灰度级空间是[0, L-1],用nk表示第k级灰度(第k个灰度级,像素值为k)在图像内的像素点个数,那么该图像中灰度级为rk(第k个灰度级)出现的概率为:

png图像直方图均衡化python python opencv 直方图均衡_直方图均衡化原理_15

根据灰度级概率,对其进行均衡化处理的计算公式为:

png图像直方图均衡化python python opencv 直方图均衡_Python-OpenCV_16

直方图均衡化使图像色彩更均衡、外观更清晰,也使图像更便于处理,它被广泛地应用在医学图像处理、车牌识别、人脸识别等领域。