兴趣所在,代码小白;自己学习,自我监督
学习《计算机视觉——算法与应用》(Richard Szeliski),希望自己坚持下来。
通过图像的直方图可以获得一些有意义的统计量,比如图1,它的亮度直方图为图2.我们看到其中的黑色最多,白色值稍多,中间值较少。利用直方图均衡化的方法,来使一些暗的值变亮,一些亮的值变暗。
图1
图2
直方图均衡化的方法,是寻找一个映射函数f(I)使映射后的直方图平坦。得到映射函数f(I)首先计算累计分布函数。一般通过下式计算:
c(I)=1N∑Ii=0h(i)=c(I−1)+1Nh(I)
一种方法是让累计分布函数为映射函数,即f(I) = c(I)。效果如图4。
图3 均衡化前
图4 均衡化后
从图3,图4的对比中可以看出,均衡化后亮的部分变暗。
另一种映射函数为
f(I)=αc(I)+(1−α)I
,是对采取局部补偿的方法改善结果。效果如图6,其中
α=0.3
(数自己瞎写的)。感觉过度效果稍好些。
图5 均衡化前
图6 均衡化后
代码用Python自己写,学习编程,理解思路。
import matplotlib.pyplot as plt
import cv2
import numpy as np
# 统计每个灰度值的像素点个数
# numPixels 为最大灰度值
def Hist(img, rows, cols, numPixels=256, dens=None):
hist = np.zeros(numPixels)
for i in range(rows):
for j in range(cols):
hist[img[i, j]] += 1
if (dens == True):
# 每个灰度值的像素点个数占总像素点的比例,即灰度密度
totalPixels = rows * cols
for i in range(numPixels):
hist[i] = hist[i] / totalPixels
return hist
else:
return hist
# 累计分布函数
# cum为累计函数
# cumProj为累计函数在灰度值上的对应值
def Cumulation(hist, numPixels=256):
cum = np.zeros(numPixels)
cumProj = np.zeros(numPixels, dtype="int32")
for i in range(numPixels):
if i == 0:
cum[i] = hist[i]
cumProj[i] = cum[i] * i
else:
cum[i] = cum[i-1] + hist[i]
cumProj[i] = cum[i] * i
return cum, cumProj
# 直方图均匀化
# "itype=True"可选择采用局部补偿的方法,同时选择alpha值改变均匀化效果
def cvtImage(img, rows, cols, cum, alpha=1):
if alpha != 1:
for i in range(rows):
for j in range(cols):
img[i, j] = cum[img[i, j]] * alpha + (1 - alpha) * img[i, j]
else:
for i in range(rows):
for j in range(cols):
img[i, j] = cum[img[i, j]]
return img
img = cv2.imread("./1.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
rows, cols = gray.shape
gray_ = gray.copy()
hist_ = Hist(gray_, rows, cols, dens=True)
hist = Hist(gray, rows, cols, dens=True)
cum, cumProj = Cumulation(hist)
gray = cvtImage(gray, rows, cols, cumProj, alpha=0.3)
hist = Hist(gray, rows, cols, dens=True)
fig = plt.figure(figsize=(12.5, 24))
ax1 = fig.add_subplot(411)
ax2 = fig.add_subplot(412)
ax3 = fig.add_subplot(413)
ax4 = fig.add_subplot(414)
cv2.imshow("original", gray_)
cv2.imshow("histogram", gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
ax1.plot([x for x in range(256)], cum)
ax2.plot([x for x in range(256)], cumProj)
ax3.plot([x for x in range(256)], hist_)
ax4.plot([x for x in range(256)], hist)
plt.show()