根据直方图的原理,记录一下代码实现流程。
一、计算原始图像的灰度直方图
- 首先获取图片大小
w = img.shape[0]#获取图片宽度
h = img.shape[1]#获取图片高度
- 定义数组
n = np.zeros((256), dtype=np.float)#定义数组保存每个灰度的数量
p = np.zeros((256), dtype=np.float)#定义数组保存每个灰度出现的概率P(rk)
c = np.zeros((256), dtype=np.float)#定义数组保存每个灰度出现的概率P(sk')
- 遍历图像的每个像素,得到每个像素的数量
# 遍历图像的每个像素,得到每个像素的数量
for x in range(0, img.shape[0]):
for y in range(0, img.shape[1]):
print(img[x][y])
n[img[x][y]] += 1
二、计算原始图像的灰度分布频率
for i in range(0, 256):
p[i] = n[i] / m
三、计算原始图像的灰度累积分布频率
c[0] = p[0]
for i in range(1, 256):
c[i] = c[i - 1] + p[i]
四、计算rk
des = np.zeros((w, h, 3), dtype=np.uint8)
for x in range(0, w):
for y in range(0, h):
des[x][y] = 255 * c[img[x][y]]
灰度直方图均衡化完毕。
五、完整代码如下
import cv2
import numpy as np
img = cv2.imread('D:/project/intelligent image analysis/jetplane.png')#读图
########## Begin ##########
w = img.shape[0]#获取图片宽度
h = img.shape[1]#获取图片高度
m = w*h#获取图片大小
print('w',w)
print('h',h)
print('m',m)
n = np.zeros((256), dtype=np.float)#定义数组保存每个灰度的数量
p = np.zeros((256), dtype=np.float)#定义数组保存每个灰度出现的概率P(rk)
c = np.zeros((256), dtype=np.float)#定义数组保存每个灰度出现的概率P(sk')
# 遍历图像的每个像素,得到每个像素的数量
for x in range(0, img.shape[0]):
for y in range(0, img.shape[1]):
print(img[x][y])
n[img[x][y]] += 1
print('n', n)
# 计算灰度分布率
for i in range(0, 256):
p[i] = n[i] / m
print('p', p)
# 计算原始图像累计灰度分布率
c[0] = p[0]
for i in range(1, 256):
c[i] = c[i - 1] + p[i]
print('c', c)
#得到rk
des = np.zeros((w, h, 3), dtype=np.uint8)
for x in range(0, w):
for y in range(0, h):
des[x][y] = 255 * c[img[x][y]]
print('des', des)
out = des
########## End ##########
cv2.imwrite('D:\project\intelligent image analysis\out.png', out)
需要自己填写的部分为"Begin"和"End"之间的部分。
六、错误记录
- 最开始统计原始图像灰度直方图时,输入代码如下:
#遍历图像的每个像素,得到统计分布直方图
for x in range(0,img.shape[0]):
for y in range(0,img.shape[1]):
n[img[x][y]] += 1
print n
然后运行时出现了下面这个错误:
IndentationError: expected an indented block
经过查阅,发现是格式不对,应该改为下面的格式:
for x in range(0, img.shape[0]):
for y in range(0, img.shape[1]):
n[img[x][y]] += 1
print('n', n)
- 计算原始图像灰度分布率和灰度累计分布率时,最开始代码如下:
for i in range(0,256):
p[i] = n[i]/float(img.size)
print('p', p)
# 计算原始图像累计灰度分布率
c[0] = p[0]
for i in range(1, 256):
c[i] = c[i - 1] + p[i]
print('c', c)
由于我将c打印了出来,于是在这里便看出了不对头。
n、p、c这三个数组的值如下图所示:
显然c数组最后的值不满足加和为1。再回去找原因,发现可能是img.size的原因。查阅发现,它是像素长宽之积,也就是像素数量。然而,将它和图片长宽之积m=wh打印出来之后发现并不相等:
此处发现,长宽之积为512512=262144,而img.size=786432=3wh。此处我输入为一张灰度图,只有一个通道,因而我需要的值为m。
经过查阅发现,begin之前的语句
img = cv2.imread('D:/project/intelligent image analysis/jetplane.png')#读图
默认输入为3通道图片,详情请参考这位大佬的帖子
将img.size更改为m后,再次打印n、p、c这三个数组,没有问题:
最终加和为1。
- 将sk’量化为sk时,原代码如下:
des = np.zeros((w, h), dtype=np.uint8)
for x in range(0, w):
for y in range(0, h):
des[x][y] = 255 * c[img[x][y]]
print('des', des)
运行之后出现如下错误:
ValueError: setting an array element with a sequence.
经查阅发现还是数组对不上的原因。将img[x][y]打印出来后发现,是一个三维数组(此处只截取了一部分),且三个维度数值都相同:
联想刚刚那位大佬所介绍的,我将第一行输入的图像改为单通道,即将begin之前的那一行改为:
img = cv2.imread('D:/project/intelligent image analysis/jetplane.png', 0)#读图
没有报错,数组变为一维:
des也正确输出:
图片也得到增强。
然而规定begin之前的代码不能被改动,那么此处我将des数组改为3维,如下:
des = np.zeros((w, h, 3), dtype=np.uint8)
代码正确运行,没有错误。des数组如下:
图片增强效果如下:
- 将输入图片改为一张3通道的彩色图片,增强效果如下: