图像的构成是由像素点构成的,每个像素点的值代表着该点的颜色(灰度图或者彩色图)。所谓直方图就是对图像中的这些像素点的值进行统计,得到一个统一的整体的灰度概念。直方图的好处就在于可以清晰了解图像的整体灰度分布,这对于后面依据直方图处理图像来说至关重要。
一般情况下直方图都是灰度图像,直方图x轴是灰度值(一般0~255),y轴就是图像中每一个灰度级对应的像素点的个数。
那么如何获得图像的直方图?首先来了解绘制直方图需要的一些量:灰度级,正常情况下就是0-255共256个灰度级,从最黑一直到最亮(白)(也有可能统计其中的某部分灰度范围),那么每一个灰度级对应一个数来储存该灰度对应的点数目。也就是说直方图其实就是一个1m(灰度级)的一个数组而已。但是有的时候我们不希望一个一个灰度的递增,比如现在我想15个灰度一起作为一个灰度级来花直方图,这个时候我们可能只需要1(m/15)这样一个数组就够了。那么这里的15就是直方图的间隔宽度了。
以下是两种获得图像直方图的方法:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
def plot_demo(image): # 绘图都可以调用matplotlib.pyplot库来进行,其中的hist函数可以直接绘制直方图
plt.hist(image.ravel(), 256, [0, 255]) # ravel函数是将多维数组降为一维数组
plt.show()
def image_hist(image):
color = ('blue', 'green', 'red')
for i, color in enumerate(color): # 遍历序列中的元素以及它们的下标
hist = cv.calcHist([image], [i], None, [256], [0, 256])
plt.plot(hist, color = color)
plt.xlim([0, 256])
plt.show()
print("--------- Hello Python ---------")
src = cv.imread("D:/opencv/wall.jpg")
cv.namedWindow("red", cv.WINDOW_AUTOSIZE)
cv.imshow("red", src)
image_hist(src)
cv.waitKey(0)
cv.destroyAllWindows()
enumerate 函数用于遍历序列中的元素以及它们的下标,例如:
>>> color = ('blue', 'green', 'red')
>>> for i, color in enumerate(color):
print(i, color)
0 blue
1 green
2 red
numpy的ravel函数功能是将多维数组降为一维数组,这与flatten函数功能一样,不同的是,flatten不会影响原数组,而ravel则会改变原数组,例如:
>>> x = np.array([[1, 2], [3, 4]])
>>> x.flatten()[1] = 100
>>> x
array([[1, 2],
[3, 4]]) # flatten:返回的是拷贝
>>> x.ravel()[1] = 100
>>> x
array([[ 1, 100],
[ 3, 4]]) # ravel:返回的是修改后的结果
plt.hist参数详解:
matplotlib.pyplot.hist(
x, bins=10, range=None, normed=False,
weights=None, cumulative=False, bottom=None,
histtype=u'bar', align=u'mid', orientation=u'vertical',
rwidth=None, log=False, color=None, label=None, stacked=False,
hold=None, **kwargs)
x : (n,) array or sequence of (n,) arrays,这个参数是指定每个bin(箱子)分布的数据,对应x轴
bins : 这个参数指定bin(箱子)的个数,也就是总共有几条条状图
range:筛选数据范围,即横坐标显示的范围,范围之外的将被舍弃,默认是最小到最大的取值范围
normed : 这个参数指定密度,也就是每个条状图的占比例比,默认为1
cv2.calcHist
该函数是opencv自带的,而numpy.histogram也可用来统计直方图
原型为:calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]) -> hist
images参数表示输入图像,传入时应该用中括号[ ]括起来
channels参数表示传入图像的通道,如果是灰度图像,那就不用说了,只有一个通道,值为0,如果是彩色图像(有3个通道),那么值为0,1,2,中选择一个,对应着BGR各个通道。这个值也得用[ ]传入。
mask参数表示掩膜图像。如果统计整幅图,那么为None。主要是如果要统计部分图的直方图,就得构造相应的掩膜来计算。
histSize参数表示灰度级的个数,需要中括号,比如[256]
ranges参数表示像素值的范围,通常[0,256]。此外,假如channels为[0,1],ranges为[0,256,0,180],则代表0通道范围是0-256,1通道范围0-180。
hist参数为返回值,返回计算出来的直方图。
关于pyplot模块里plot()函数、xlim()函数等的用法参考:
Python可视化库matplotlib(基础整理)
matplotlib.pyplot.plot()参数详解