直方图均衡化是数字图像处理的一个基本操作。其核心目标是把像素均匀地分布到[0,255]的区间上(别问为啥是0-255)。数学原理详见直方图均衡化的数学原理。
我们的做法就是先求出图像上像素分布的累积分布函数 C D F CDF CDF,定义域为离散的0~255,原始图像的像素点 x x x作为输入,得到 C D F ( x ) CDF(x) CDF(x),再用 C D F ( x ) ∗ 255 CDF(x)*255 CDF(x)∗255就得到了新的像素值。不难理解,原始像素值输入后,得到的是这个像素点在所有像素值中的百分位点,我们把这个百分位点的值作为新的像素值(0-1区间下)。这样的话,原始的像素值就映射到了它在平衡状态下应该在的位置。
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
def histogram(image):
hist = np.zeros(shape=256,dtype=np.int)
for i in range(256):
hist[i] = int(np.sum(image==i))
return hist
def get_cdf(image):
hist = histogram(image)
res = np.zeros(shape=256,dtype=np.int)
for i in range(256):
res[i] = np.sum(hist[:i+1])
res = res*1.0/sum(hist)
return res
def hist_equalization(image):
pdf = get_cdf(image)
new_img = np.zeros_like(image)
new_img = pdf[image]*255
new_img = np.clip(new_img,0,255).astype(np.int)
return new_img
是不是很简单呢
# 读入图像并转为灰度图,可以改为自己的图片路径
src = Image.open('lena_512.tif').convert(mode='L')
src = np.array(src)
dst = hist_equalization(src) # 直方图均衡化
plt.figure(1,figsize=(10,15))
plt.subplot(3,2,1)
plt.imshow(src,cmap='gray')
plt.title('source image')
plt.subplot(3,2,2)
plt.imshow(dst,cmap='gray')
plt.title('histogram equalization')
plt.subplot(3,2,3)
plt.bar(np.arange(0,256,1),histogram(src))
plt.title('source histogram')
plt.subplot(3,2,4)
plt.bar(np.arange(0,256,1),histogram(dst))
plt.title('destination histogram')
plt.subplot(3,2,5)
plt.plot(np.arange(0,256,1),get_cdf(src))
plt.title('source cdf')
plt.subplot(3,2,6)
plt.plot(np.arange(0,256,1),get_cdf(dst))
plt.title('destination cdf')
plt.show()