OpenCV学习17-直方图均衡-Numpy计算

'''
直方图均衡化,如何使用它来改善图片的对比。
如果一副图像中的大多是像素点的像素值都集中在一个像素值范围之内会怎样
呢?例如,如果一幅图片整体很亮,那所有的像素值应该都会很高。但是一副
高质量的图像的像素值分布应该很广泛。所以你应该把它的直方图做一个横向
拉伸(如下图),这就是直方图均衡化要做的事情。通常情况下这种操作会改
善图像的对比度。
使用Numpy
'''

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('timg8.jpg',0)

#hist 是一个 256x1 的数组,每一个值代表了与次灰度值对应的像素点数目。
#bins 是 257,因为 Numpy 计算bins 的方式为:0-0.99,1-1.99,2-2.99 等。
#所以最后一个范围是 255-255.99。为了表示它,所以在 bins 的结尾加上了 
#256。但是我们不需要 256,到 255就够了。
#img.flatten() 将数组变成一维
hist,bins = np.histogram(img.flatten(),256,[0,256])

# 计算累积分布图 cumsum()累计求和
cdf = hist.cumsum()

cdf_normalized = cdf * hist.max()/ cdf.max()
plt.plot(cdf_normalized, color = 'b')
plt.hist(img.flatten(),256,[0,256], color = 'r')
plt.xlim([0,256])
plt.legend(('cdf','histogram'), loc = 'upper left')
plt.show()

'''
我们可以看出来直方图大部分在灰度值较高的部分,而且分布很集中。而
我们希望直方图的分布比较分散,能够涵盖整个 x 轴。所以,我们就需要一个
变换函数帮助我们把现在的直方图映射到一个广泛分布的直方图中。这就是直
方图均衡化要做的事情。
我们现在要找到直方图中的最小值(除了 0),并把它用于 wiki 中的直方
图均衡化公式。但是我在这里使用了 Numpy 的掩模数组。对于掩模数组的所
有操作都只对 non-masked 元素有效。你可以到 Numpy 文档中获取更多掩
模数组的信息。
'''

在这里插入图片描述
在这里插入图片描述

'''
直方图均衡化,如何使用它来改善图片的对比。
如果一副图像中的大多是像素点的像素值都集中在一个像素值范围之内会怎样
呢?例如,如果一幅图片整体很亮,那所有的像素值应该都会很高。但是一副
高质量的图像的像素值分布应该很广泛。所以你应该把它的直方图做一个横向
拉伸(如下图),这就是直方图均衡化要做的事情。通常情况下这种操作会改
善图像的对比度。
使用Numpy
'''

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
#设置中文字体
matplotlib.rcParams['font.family'] = 'SimHei'

img = cv.imread('timg8.jpg',0)

#hist 是一个 256x1 的数组,每一个值代表了与次灰度值对应的像素点数目。
#bins 是 257,因为 Numpy 计算bins 的方式为:0-0.99,1-1.99,2-2.99 等。
#所以最后一个范围是 255-255.99。为了表示它,所以在 bins 的结尾加上了 
#256。但是我们不需要 256,到 255就够了。
#img.flatten() 将数组变成一维
hist,bins = np.histogram(img.flatten(),256,[0,256])

# 计算原图累积分布图 cumsum()累计求和
cdf = hist.cumsum()
cdf_normalized = cdf * hist.max()/ cdf.max()

'''
我们可以看出来直方图大部分在灰度值较高的部分,而且分布很集中。而
我们希望直方图的分布比较分散,能够涵盖整个 x 轴。所以,我们就需要一个
变换函数帮助我们把现在的直方图映射到一个广泛分布的直方图中。这就是直
方图均衡化要做的事情。
我们现在要找到直方图中的最小值(除了 0),并把它用于 wiki 中的直方
图均衡化公式。但是我在这里使用了 Numpy 的掩模数组。对于掩模数组的所
有操作都只对 non-masked 元素有效。你可以到 Numpy 文档中获取更多掩
模数组的信息。
'''

#直方图均衡化
#构建 Numpy 掩模数组, cdf 为原数组,当数组元素为 0 时,掩盖(计算时被忽略)。
cdf_m = np.ma.masked_equal(cdf,0)
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
#对被掩盖的元素赋值,这里赋值为 0
cdf = np.ma.filled(cdf_m,0).astype('uint8')

# 计算直方图均衡后的直方图
img2 = cdf[img]
hist2,bins2 = np.histogram(img2.flatten(),256,[0,256])
cdf2 = hist2.cumsum()
cdf_normalized2 = cdf2 * hist2.max()/ cdf2.max()

#绘图
plt.subplot(221), plt.imshow(img, 'gray')
plt.title(u'原图'), plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(img2,'gray')
plt.title(u'均衡后'), plt.xticks([]), plt.yticks([])
plt.subplot(223),plt.title(u'原图直方图')
plt.plot(cdf_normalized, color = 'b')
plt.hist(img.flatten(),256,[0,256], color = 'r')
plt.xlim([0,256])
plt.legend(('cdf','histogram'), loc = 'upper left')
plt.subplot(224),plt.title(u'均衡后直方图')
plt.plot(cdf_normalized2, color = 'b')
plt.hist(img2.flatten(),256,[0,256], color = 'r')
plt.xlim([0,256])
plt.legend(('cdf2','histogram2'), loc = 'upper left')

plt.show()
'''
即使我们的输入图片是一个比较暗的图片(不象上边我们用到到的整体都很亮的图片),
在经过直方图均衡化之后也能得到相同的结果。因此,直方图均衡化经常用来使所有的图
片具有相同的亮度条件的参考工具。这在很多情况下都很有用。例如,脸部识别,在训练
分类器前,训练集的所有图片都要先进行直方图均衡化从而使它们达到相同的亮度条件。
'''

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值