直方图是图像处理过程中的一种非常重要的分析工具。直方图从图像内部灰度级的角度对图像进行表述,包含十分丰富而重要的信息。从直方图的角度对图像进行处理,可以达到增强图像显示效果的目的。
从统计的角度讲,直方图是图像内灰度值的统计特性与图像灰度值之间的函数,直方图统计图像内各个灰度级出现的次数。从直方图的图形上观察,横坐标是图像中各像素点的灰度级,纵坐标是具有该灰度级(像素值)的像素个数。
在 OpenCV 的官网上,特别提出了要注意三个概念:DIMS、BINS、RANGE。
例如,在灰度图像中,将[0, 255]区间内的256个灰度级,按照每16 个像素一组划分为子集:
[0, 255] = [0, 15] ∪ [16, 31] ∪…∪[240, 255]
按照上述方式,整个灰度级范围可以划分为16 个子集,具体为:整个灰度级范围= bin1 ∪ bin2 ∪…∪ bin16
子集划分完以后,某灰度图像生成的直方图如图所示(图中的b1 代表bin1,b2 代表bin2,以此类推)
hist = cv2.calcHist( images, channels, mask, histSize, ranges, accumulate )
使用 matplotlib.pyplot 模块内的plot()函数,可以将函数cv2.calcHist()的返回值绘制为图像直方图。下面通过三个例子来学习plot()函数的基本使用方法。
#将给定的x= [0,1,2,3,4,5,6],y = [0.3,0.4,2,5,3,4.5,4],使用plot()函数绘制出来。
import matplotlib.pyplot as plt
x = [0,1,2,3,4,5,6]
y = [0.3,0.4,2,5,3,4.5,4]
plt.plot(x,y)
#给定y = [0.3, 0.4, 2, 5, 3, 4.5, 4],使用plot()函数将其绘制出来,观察绘制结果。
import matplotlib.pyplot as plt
y = [0.3,0.4,2,5,3,4.5,4]
plt.plot(y)
#使用plot()函数将两组不同的值a= [0.3, 0.4, 2, 5, 3, 4.5, 4],b=[3, 5, 1, 2, 1, 5, 3]以不同的颜色绘制出来。
import matplotlib.pyplot as plt
a = [0.3,0.4,2,5,3,4.5,4]
b=[3,5,1,2,1,5,3]
plt.plot(a,color='r')
plt.plot(b,color='g')
#使用函数plot()将函数cv2.calcHist()的返回值绘制为直方图。
import cv2
import matplotlib.pyplot as plt
o=cv2.imread("image\\boatGray.bmp")
histb = cv2.calcHist([o],[0],None,[256],[0,255])
plt.plot(histb,color='b')
plt.show()
#使用函数plot()和函数cv2.calcHist(),将彩色图像各个通道的直方图绘制在一个窗口内。
import cv2
import matplotlib.pyplot as plt
o=cv2.imread("image\\girl.bmp")
histb = cv2.calcHist([o],[0],None,[256],[0,255])
histg = cv2.calcHist([o],[1],None,[256],[0,255])
histr = cv2.calcHist([o],[2],None,[256],[0,255])
plt.plot(histb,color='b')
plt.plot(histg,color='g')
plt.plot(histr,color='r')
plt.show()
左图是原始图像O,中间的是掩模图像M,右图是使用掩模图像M 对原始图像O 进行掩模运算的结果图像R:
import cv2
import numpy as np
import matplotlib.pyplot as plt
image=cv2.imread("image\\girl.bmp",cv2.IMREAD_GRAYSCALE)
mask=np.zeros(image.shape,np.uint8)
mask[200:400,200:400]=255
image2=cv2.bitwise_and(image,mask)
histImage=cv2.calcHist([image],[0],None,[256],[0,255])
histMI=cv2.calcHist([image],[0],mask,[256],[0,255])
plt.plot(histImage)
plt.plot(histMI)
cv2.imshow("origin",image)
cv2.imshow("after",image2)
cv2.waitKey()
cv2.destroyAllwindows()
如果一幅图像拥有全部可能的灰度级,并且像素值的灰度均匀分布,那么这幅图像就具有高对比度和多变的灰度色调,灰度级丰富且覆盖范围较大。在外观上,这样的图像具有更丰富的色彩,不会过暗或过亮。
dst = cv2.equalizeHist( src )
#-----------导入使用的模块---------------
import cv2
import matplotlib.pyplot as plt
#-----------读取原始图像---------------
img = cv2.imread('image\\equ.bmp',cv2.IMREAD_GRAYSCALE)
#-----------直方图均衡化处理---------------
equ = cv2.equalizeHist(img)
#-----------显示均衡化前后的图像---------------
cv2.imshow("original",img)
cv2.imshow("result",equ)
#-----------显示均衡化前后的直方图---------------
plt.figure("原始图像直方图") #构建窗口
plt.hist(img.ravel(),256)
plt.figure("均衡化结果直方图") #构建新窗口
plt.hist(equ.ravel(),256)
#----------等待释放窗口---------------------
cv2.waitKey()
cv2.destroyAllWindows()
直方图均衡化使图像色彩更均衡、外观更清晰,也使图像更便于处理,它被广泛地应用在医学图像处理、车牌识别、人脸识别等领域。
matplotlib.pyplot模块提供了一个类似于MATLAB绘图方式的框架,可以使用其中的函数方便地绘制图形。
模块 matplotlib.pyplot 提供了函数matplotlib.pyplot.subplot()用来向当前窗口内添加一个子窗口对象。该函数的语法格式为:
matplotlib.pyplot.subplot(nrows, ncols, index)
例如,subplot(2, 3, 4)表示在当前的两行三列的窗口的第4 个位置上,添加1 个子窗口:
需要注意的是,窗口是按照行方向排序的,而且序号是从“1”开始而不是从“0”开始的。如果所有参数都小于10,可以省略彼此之间的逗号,直接写三个数字。例如,上述subplot(2, 3, 4)可以直接表示为subplot(234)。
模块matplotlib.pyplot 提供了函数matplotlib.pyplot.imshow()用来显示图像。其语法格式为:
matplotlib.pyplot.imshow(X, cmap=None)
#使用函数matplotlib.pyplot.imshow()显示彩色图像。
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('image\\girl.bmp')
imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
plt.figure("显示结果")
plt.subplot(121)
plt.imshow(img),plt.axis('off')
plt.subplot(122)
plt.imshow(imgRGB),plt.axis('off')
左图是直接使用默认色彩空间参数模式显示的彩色图像的结果,图像没有正常显示出来。这是因为通过函数cv2.imread()读取的图像,其通道顺序是BGR模式的。而函数matplotlib.pyplot.imshow()的显示顺序是RGB模式的,所以显示出来的图像通道顺序是错乱的,因而无法正常显示。
#使用函数matplotlib.pyplot.imshow()显示灰度图像。
import cv2
import matplotlib.pyplot as plt
o = cv2.imread('image\\girl.bmp')
g=cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)
plt.figure("灰度图像显示演示")
plt.subplot(221)
plt.imshow(o),plt.axis('off')
plt.subplot(222)
plt.imshow(o,cmap=plt.cm.gray),plt.axis('off')
plt.subplot(223)
plt.imshow(g),plt.axis('off')
plt.subplot(224)
plt.imshow(g,cmap=plt.cm.gray),plt.axis('off')
只有使用灰度图像作为参数, 并且将色彩空间参数值设置为“cmap=plt.cm.gray”,灰度图像才被正常显示。
#使用函数matplotlib.pyplot.imshow()以不同的参数形式显示灰度图像。
import cv2
import matplotlib.pyplot as plt
o = cv2.imread('image\\8.bmp')
g=cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)
plt.figure("灰度图像显示演示")
plt.subplot(221); plt.imshow(g, cmap=plt.cm.gray)
plt.subplot(222); plt.imshow(g, cmap=plt.cm.gray_r)
plt.subplot(223); plt.imshow(g, cmap='gray')
plt.subplot(224); plt.imshow(g, cmap='gray_r')
上述代码中,色彩空间参数cmap 的参数值“plt.cm.gray_r”及“gray_r”中的“r”是英文“reverse”的缩写,表示逆转的意思。