下面的程序给出了如何绘制一幅图像总体的直方图和每一个通道的直方图html
#-*- coding:utf-8 -*- import cv2 from matplotlib import pyplot as plt def whole_hist(image): ''' 绘制整幅图像的直方图 ''' plt.hist(image.ravel(), 256, [0, 256]) #numpy的ravel函数功能是将多维数组降为一维数组 plt.show() def channel_hist(image): ''' 画三通道图像的直方图 ''' color = ('b', 'g', 'r') #这里画笔颜色的值能够为大写或小写或只写首字母或大小写混合 for i , color in enumerate(color): hist = cv2.calcHist([image], [i], None, [256], [0, 256]) #计算直方图 plt.plot(hist, color) plt.xlim([0, 256]) plt.show() image = cv2.imread('/home/liubo/tmp/sample/00001.jpg') cv2.imshow('image', image) cv2.waitKey(0) whole_hist(image) channel_hist(image)
执行能够获得以下的结果
python
整幅图像的直方图以下所示
web
每一个通道的直方图以下所示
算法
能够明显看到这是一个直方图分布不是很均衡的图像,因此咱们将尝试在下面进行直方图均衡化。数组
若是图像曝光过分或者曝光不足会致使计算机视觉相关算法表现的不够稳定,好比说一幅曝光过分的图像颇有可能致使人脸识别算法的置信度下降甚至错误识别。直方图对于咱们理解曝光有很大的帮助,如下三幅图在同一时间段拍摄于同一地方,分别是欠曝、准确曝光和过曝的效果,右下角为其对应的直方图[1][2]svg
直方图无论是向右“撞墙”仍是向左“爬墙”了,只能说明高光像素量大,多是过曝了,仅可用做参考,不能100%肯定就是过曝。何况有时为了创意刻意而为之,这时的过曝是一种拍摄技法,能够起到烘托照片的气氛,或者起到纯化背景的做用,好比说下面这张图像
函数
针对曝光过分或者曝光欠缺能够使用 gamma 变化的方法,具体能够参考文章《opencv-python 图像灰度变换》。除了这种方法还能够使用直方图均衡化的方法。ui
在现实的拍摄过程当中,好比说视频监控领域,因为其图像的灰度分布集中在较窄的范围内,这就致使了图像的细节不够清晰。为何不清晰呢,由于灰度分布较窄时,那么,在计算对比度的时候,对比度就很小,因此就不清晰。为了使得图像变得清晰,那么就须要使得灰度值的差异变大,为了使得灰度值的差异变大,就意味着灰度分布就变的较宽,使得灰度值分布变得均匀,在某个灰度级区间内,像素的个数分布大体相同,这样才能使得图像的对比度加强,细节变得清晰可见[3]。spa
在opencv 3 中的函数 cv2.equalizeHist(img)
能够将输入图像进行图像均衡化处理,可是须要注意的是输入图像必须是 8 位的单通道图像,返回图像也是一个 8 位的单通道图像,对于彩色图像必须逐一通道处理,以下所示.net
# 直方图均衡化 (b, g, r) = cv2.split(frame) bH = cv2.equalizeHist(b) gH = cv2.equalizeHist(g) rH = cv2.equalizeHist(r) frameH = cv2.merge((bH, gH, rH))
可是在实践中,对RGB 图像中的每一个通道的图像单独应用直方图均衡不太可能给出美观的效果。一种可能比较好的方法是,将图像转换到 LAB 颜色空间,而后再将直方图均衡应用于亮度通道。
[1] 叶明 蜂鸟网 《教你如何判断一张照片的曝光是否彻底准确》
[2] brucebruce 豆瓣 断定照片曝光过分的4个窍门!
[3]菲尔因惹火 CSDN 《直方图均衡化(Histogram equalization)与直方图规定化》