项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
欢迎大家star,留言,一起学习进步
在统计学中,直方图(Histogram)是一种对数据分布情况的图形表示,是一种二维统计图表,它的两个坐标分别是统计样本和该样本对应的某个属性的度量。一般来说用横轴表示数据类型,纵轴表示分布情况。
直方图是数值数据分布的精确图形表示。 这是一个连续变量(定量变量)的概率分布的估计,并且被卡尔·皮尔逊(Karl Pearson)首先引入。它是一种条形图。 为了构建直方图,第一步是将值的范围分段,即将整个值的范围分成一系列间隔,然后计算每个间隔中有多少值。 这些值通常被指定为连续的,不重叠的变量间隔。 间隔必须相邻,并且通常是(但不是必须的)相等的大小。
直方图也可以被归一化以显示“相对”频率。 然后,它显示了属于几个类别中的每个案例的比例,其高度等于1。
在图像处理中,直方图是非常重要,也非常有用的一个处理要素。
一般来说图像直方图的横轴表示亮度,从左到右表示亮度从低到高。直方图的纵轴表示像素数量,从下到上表示像素从少到多。直方图在某个亮度区间的凸起越高,就表示在这个亮度区间内的像素越多。比如这个直方图的凸起就主要集中在左侧,也就是说这张照片的亮度整体偏低。
而直方图均衡则是图像对比增强的一种常用方法。一般来说,图像对比增强的方法分为两大类:一种是直接对比度增强,另外一种是间接对比度增强。直方图拉伸与直方图均衡化就是两种最常见的间接对比度增强的方法。直方图均衡化的基本思想就是把原始图像的灰度直方图从比较集中的某个灰度区间变成全部灰度范围内的均匀分布,具体的做法就是通过对图像进行非线性拉伸,重新分配图像的像素值,使一定灰度范围内的像素数量大致相同。
直方图均衡化优点:
1.均衡化后的图像明暗对比更明显。亮的地方更亮,暗的地方更暗,拉开了差距。
2.直方图被均匀分开。
3.增大图像的信息量。
直方图均衡化缺点:
1.变换后图像的灰度级减少,某些细节消失;
2.某些图像,如直方图有高峰,经处理后对比度不自然的过分增强
在直方图均衡化的过程中,有两个问题需要搞定。一是为什么要选用累积分布函数,二是为什么使用累积分布函数处理后像素值会均匀分布。
第一个问题。均衡化过程中,必须要保证两个条件:①像素无论怎么映射,一定要保证原来的大小关系不变,较亮的区域,依旧是较亮的,较暗依旧暗,只是对比度增大,绝对不能明暗颠倒;②如果是八位图像,那么像素映射函数的值域应在0和255之间的,不能越界。综合以上两个条件,累积分布函数是个好的选择,因为累积分布函数是单调增函数(控制大小关系),并且值域是0到1(控制越界问题),所以直方图均衡化中使用的是累积分布函数。
第二个问题。累积分布函数具有一些好的性质,那么如何运用累积分布函数使得直方图均衡化?比较概率分布函数和累积分布函数,前者的二维图像是参差不齐的,后者是单调递增的。直方图均衡化过程中,映射方法是
s k = ∑ i = 1 n n j n , k = 0 , 1 , 2 , ⋯ , L − 1 s_k = \displaystyle{\sum_{i=1}^{n}}\frac{n_j}{n}, k = 0,1,2,\cdots,L-1 sk=i=1∑nnnj,k=0,1,2,⋯,L−1
其中, n n n是图像中像素的总和, n k n_k nk是当前灰度级的像素个数, L L L是图像中可能的灰度级总数。
具体的严格数学推导过程可以查看后面的参考链接。
来看看通过上述公式怎样实现的拉伸。假设有如下图像:
得图像的统计信息如下图所示,并根据统计信息完成灰度值映射:
映射后的图像如下所示:
以上就是直方图映射均衡化的步骤,当然还有一些基于此的更优算法,比如Photoshop中的方法,在此就不一一列举了,大同小异。
import numpy as np
from skimage import exposure, io, data
import matplotlib.pyplot as plt
def histdemo():
image = io.imread('XXX')
arr = image.flatten()
plt.subplot(221)
plt.imshow(image)
plt.subplot(222)
plt.hist(arr, bins=256, normed=1, edgecolor='None', facecolor='red') # 原始图像直方图
img1 = exposure.equalize_hist(image)
arr1 = img1.flatten()
plt.subplot(223)
plt.imshow(img1, plt.cm.gray) # 均衡化图像
plt.subplot(224)
plt.hist(arr1, bins=256, normed=1, edgecolor='None', facecolor='red') # 均衡化直方图
plt.show()
histdemo()
代码详解:
matplotlib.pyplot中的hist函数可以直接绘制直方图。而hist函数的参数非常多,函数签名如下:
# This function was autogenerated by boilerplate.py. Do not edit as
# changes will be lost
@_autogen_docstring(Axes.hist)
def hist(x, bins=None, range=None, normed=False, weights=None, cumulative=False,
bottom=None, histtype='bar', align='mid', orientation='vertical',
rwidth=None, log=False, color=None, label=None, stacked=False,
hold=None, data=None, **kwargs):
其中,
x: 为需要计算直方图的一维数组,在代码中为arr,由图像矩阵flatten而来。
bins: 为直方图的柱数。
normed: 是否归一化
histtype:直方图的类型
参考链接:
1.https://zhuanlan.zhihu.com/p/24507450
2.https://zh.wikipedia.org/wiki/%E7%9B%B4%E6%96%B9%E5%9B%BE%E5%9D%87%E8%A1%A1%E5%8C%96
3.https://www.zhihu.com/question/37204742 直方图均衡化的数学推导过程
4.http://blog.csdn.net/rushkid02/article/details/9178117 直方图均衡化的例子来自本文