这几天一直在做一个图像处理的任务,简单来说就是对一个过曝的图片进行处理,使得被亮光“遮盖”的一些细节信息显现出来。
注:我处理的是医学图像,所以某些细节问题可能不太一样(比如对RGB不考虑,全部转为灰度图)
环境:win10、python 3.6.6、Jupyter Notebook、opencv 3.4.2
相关代码已上传至个人github
一、直方图均衡化(Histogram Equalization)
一个很经典的算法就是利用直方图均衡化的方法。这个内容我在之前的一篇文章中有所提及。首先,直方图就是一种对图的像素强度分布的图形表达方式,它能直观地向我们展示一张图片的像素分布情况。
举一个例子:
经常地,在一张直方图中,可能会存在一个或多个尖峰,而尖峰的高度差非常大的情况。均衡化就是拉伸像素强度的分布范围,增强图像局部的对比度。
换句话说就是 将像素值重新分配。我们需要建立一个映射,将原图的像素分布映射到另一个分布上。而要实现均衡化,映射函数就应该是一个累积分布函数(CDF)
实际上我们不需要知道这个分布函数的内容到底是什么,因为opencv已经给我们封装处理好了。我直接说我的实验结果。
opencv和numpy各有各的实现方式,不过效果差不多。
1.opencv 实现
equ = cv2.equalizeHist(tmp)
复制代码
调用这个函数就行了,全都封装好了。
2.numpy 实现
这里我展示一下手动制作直方图的代码
img = cv2.imread("test.jpg",0)
cv2.normalize(img,img, 0, 255, cv2.NORM_MINMAX)
#归一化
lut = np.zeros(256, dtype = img.dtype )
#创建空的查找表
hist,bins = np.histogram(img.flatten(),256,[0,256])
#计算原图的直方图
#计算累积直方图
cdf = hist.cumsum()
cdf_m = np.ma.masked_equal(cdf,0) #除去直方图中的0值
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
#等同于公式lut[i] = int(255.0 *p[i]) 将像