01 什么是直方图
简单的来说, 直方图就是对数据进行统计, 并且将统计值组织到一系列事先定义好的 bin 当中,
bin 中的数值是从数据中计算出来的特征的统计量,这些特征可以是物体的色彩分布, 物体的梯度等等。。
这里我们着重看一下灰度直方图,
在灰度为 [0, L-1] 的范围内, 数字图像的直方图是离散函数 h(rk) = nk , 其中rk 表示第k 级灰度值,
nk 则是图像中第k 级灰度值像素的个数。
经常使用nk 来除以像素总数(M*N), 从而归一化直方图。
直方图是多种空间域处理技术的基础, 直方图操作可用于图像增强的目的。
02 如何绘制直方图
好, 那么我们来看一下应当如何获取一幅灰度图像的直方图;
说到直方图, 我首先想到的是matplotlib 这个库, 它可以根据你所给出的数据来绘制直方图,
下面我们来看一下:
import matplotlib.pyplot as plt
import cv2
def plot_histogram(image):
# 这里使用了 ravale 方法, 原因是cv2.imread的返回值类型为ndarray
plt.xlabel('gray')
plt.ylabel('numbers')
plt.hist(x=image.ravel(), bins=256, range=[0, 256])
plt.suptitle('histogram of grayimage')
plt.show()
img_path = os.path.join(os.getcwd(), 'zebra.jpeg')
images = cv2.imread(filename=img_path)
gray_it = cv2.cvtColor(images, cv2.COLOR_BGR2GRAY)
cv2.namedWindow('input image', cv2.WINDOW_AUTOSIZE)
cv2.imshow('input image', gray_it)
cv2.waitKey()
plot_histogram(gray_it)
cv2.destroyAllWindows()
输出结果如下
OK , 现在可以看到, 图像的直方图大概是一个什么样子,
现在我们来正式引入 opencv :
我们如何使用 opencv 来得到我们图像的直方图呢?
----------- 我们使用 cv2. calcHist() 这个函数来计算我们图像的直方图, 其返回值同样是 ndarray 类型的数组,
然后我们使用 plt.imshow 来显示。
def cv2_histogram(image):
# 首先, 我们要表示图像的三个通道
img_color = ('blue', 'green', 'red')
for i, iter_color in enumerate(img_color):
hist = cv2.calcHist([image], [i], None,
[256], [0, 256])
print(type(hist))
plt.plot(hist, color=iter_color)
# bins is bin_size
plt.hist(hist, bins=256, range=[0, 256], color=iter_color)
plt.xlim([0, 256])
plt.show()
img_path = os.path.join(os.getcwd(), 'zebra.jpeg')
images = cv2.imread(filename=img_path)
# gray_it = cv2.cvtColor(images, cv2.COLOR_BGR2GRAY)
cv2.namedWindow('input image', cv2.WINDOW_AUTOSIZE)
cv2.imshow('input image', images)
cv2.waitKey()
cv2_histogram(images)
cv2.destroyAllWindows()
ps : 如果你觉得 plot 绘制出来的不能称之为直方图, 那么你可以使用 hist 来绘制,
二者绘制的斑马的图像如下: