跳转至

直方图

直方图

直方图简单来说就是图像中每个像素值的个数统计,比如说一副灰度图中像素值为0的有多少个,1的有多少个……直方图是一种分析图片的手段:

在计算直方图之前,有几个术语先来了解一下:

  • dims:要计算的通道数,对于灰度图dims=1,普通彩色图dims=3
  • range:要计算的像素值范围,一般为[0,256)
  • bins:子区段数目,如果我们统计0~255每个像素值,bins=256;如果划分区间,比如0~15, 16~31…240~255这样16个区间,bins=16

计算直方图

使用cv2.calcHist(images, channels, mask, histSize, ranges)计算,其中:

  • 参数1:要计算的原图,以方括号的传入,如:[img]
  • 参数2:类似前面提到的dims,灰度图写[0]就行,彩色图B/G/R分别传入[0]/[1]/[2]
  • 参数3:要计算的区域,计算整幅图的话,写None
  • 参数4:前面提到的bins
  • 参数5:前面提到的range
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('img/hist.jpg', 0)
hist = cv2.calcHist([img], [0], None, [256], [0, 256])  # 性能:0.025288 s

绘制直方图

其实Matplotlib自带了一个计算并绘制直方图的功能,不需要用到上面的函数:

plt.hist(img.ravel(), 256, [0, 256])
plt.show()

当然,也可以用前面计算出来的结果绘制:

plt.plot(hist)
plt.show()

从直方图上可以看到图片的大部分区域集中在150偏白的附近,这其实并不是很好的效果,下面我们来看看如何改善它。

直方图均衡化

一副效果好的图像通常在直方图上的分布比较均匀,直方图均衡化就是用来改善图像的全局亮度和对比度。

直方图均衡化(Histogram Equalization)是一种增强图像对比度(Image Contrast)的方法,其主要思想是将一副图像的直方图分布通过累积分布函数变成近似均匀分布,从而增强图像的对比度。

equ = cv2.equalizeHist(img)

OpenCV中用cv2.equalizeHist()实现均衡化。我们把两张图片并排显示,对比一下:

cv2.imshow('equalization', np.hstack((img, equ)))  # 并排显示
cv2.waitKey(0)

可以看到均衡化后图片的亮度和对比度效果明显好于原图。

示例代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('img/hist.jpg', 0)
# hist = cv2.calcHist([img], [0], None, [256], [0, 256])  # 性能:0.025288 s

# plt.hist(img.ravel(), 256, [0, 256])
equ = cv2.equalizeHist(img)
# plt.show()
cv2.imshow('equalization', np.hstack((img, equ)))  # 并排显示
cv2.waitKey(0)