原理
什么是直方图呢?通过直方图你可以对整幅图像的灰度分布有一个整体的了解。直方图的 x 轴是灰度值(0 到 255),y 轴是图片中具有同一个灰度值的点的数目。

一、统计直方图
BINS:上面的直方图显示了每个灰度值对应的像素数。如果像素值为 0 到 255,你就需要 256 个数来显示上面的直方图。但是,如果你不需要知道每一个像素值的像素点数目的,而只希望知道两个像素值之间的像素点数目怎么办呢?举例来说,我们想知道像素值在 0 到 15 之间的像素点的数目,接着是 16 到 31,…,240 到 255。我们只需要 16 个值来绘制直方图。OpenCVTutorials on histograms中例子所演示的内容。那到底怎么做呢?你只需要把原来的 256 个值等分成 16 小组,取每组的总和。而这里的每一个小组就被成为 BIN。第一个例子中有 256 个 BIN,第二个例子中有 16 个 BIN。在 OpenCV 的文档中用 histSize 表示 BINS。

DIMS:表示我们收集数据的参数数目。在本例中,我们对收集到的数据只考虑一件事:灰度值。所以这里就是 1。

RANGE:就是要统计的灰度值范围,一般来说为 [0,256],也就是说所有的灰度值

使用 OpenCV 统计直方图 函数 cv2.calcHist 可以帮助我们统计一幅图像的直方图。我们一起来熟悉一下这个函数和它的参数:
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])

  1. images: 原图像(图像格式为 uint8 或 float32)。当传入函数时应该用中括号 [] 括起来,例如:[img]。
  2. channels: 同样需要用中括号括起来,它会告诉函数我们要统计那幅图像的直方图。如果输入图像是灰度图,它的值就是 [0];如果是彩色图像的话,传入的参数可以是 [0][1],[2] 它们分别对应着通道 B,G,R。
  3. mask: 掩模图像。要统计整幅图像的直方图就把它设为 None。但是如果你想统计图像某一部分的直方图的话,你就需要制作一个掩模图像,并使用它。(后边有例子)
  4. histSize:BIN 的数目。也应该用中括号括起来,例如:[256]。
  5. ranges: 像素值范围,通常为 [0,256]

img = cv2.imread(‘home.jpg’,0) # 别忘了中括号 [img],[0],None,[256],[0,256],只有 mask 没有中括号
hist = cv2.calcHist([img],[0],None,[256],[0,256])

使用 Numpy 统计直方图 Numpy 中的函数 np.histogram() 也可以帮我们统计直方图
#img.ravel() 将图像转成一维数组,这里没有中括号。
hist,bins = np.histogram(img.ravel(),256,[0,256])

二、绘制直方图

有两种方法来绘制直方图:

  1. Short Way(简单方法):使用 Matplotlib 中的绘图函数。
  2. Long Way(复杂方法):使用 OpenCV 绘图函数 使用 Matplotlib Matplotlib 中有直方图绘制函数:matplotlib.pyplot.hist()
1.  import cv2
 import numpy as np
 from matplotlib import pyplot as plt
 img = cv2.imread(‘home.jpg’,0)
 plt.hist(img.ravel(),256,[0,256]);
 plt.show()