学习目标
这一节,我们将学习寻找和绘制2D直方图,对后面的章节非常有用。
简介
在直方图系列的第一节,我们计算并绘制了一维直方图。之所以称之为一维,是因为我们仅仅考虑一个特征(图像的灰度值)。但是,在二维直方图中,我们考虑2个特征。通常情况下,在计算彩色直方图的时候,考虑的2个特征为每个像素的色度和饱和度(Hue&Saturation)。
2D Histogram in OpenCV
使用的函数依然是:cv2.calcHist()
. 对于彩色直方图,我们需要将图像进行转换(BGR->HSV),在1D直方图中,我们将彩色图转换为灰度图(Grayscale)。2D直方图中,参数修改如下:
- channels = [0, 1],因为我们需要处理
H
和S
平面。 - bins = [180, 256],180是
H
通道,256是S
通道。 - range = [0, 180, 0, 256],Hue的范围为【0,180】,Saturation的范围【0,256】。
看下面的例子,计算2D直方图:
import cv2
import numpy as np
img = cv2.imread('home.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
2D Histogram in Numpy
Numpy计算2D直方图的函数为:np.histogram2d()
(1D直方图的函数为,np.histogram())。计算代码如下:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('home.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
h, s = hsv[:, :, 0], hsv[:, :, 1]
hist, xbins, ybins = np.histogram2d(h.ravel(),s.ravel(),[180,256],[[0,180],[0,256]])
Plotting 2D Histograms
方法1:cv2.imshow()
2D直方图返回的是大小为180x256
的数组。所以,我们可以使用cv2.imshow()
显示。但是显示的是灰度图,并不能反映彩色信息,除非知道不同颜色的Hue
值。
方法2:Matplotlib
可以使用不同的颜色图绘制2D直方图,函数为matplotlib.pyplot.imshow()
。这样可以方便得到不同像素强度。但是,同样无法得到具体的颜色信息,除非知道不同颜色的Hue
值。
注意,当使用该函数时,插值必须使用
nearsest
,这样可以达到更好的效果。
代码
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('home.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist = cv2.calcHist( [hsv], [0, 1], None, [180, 256], [0, 180, 0, 256] )
plt.imshow(hist,interpolation = 'nearest')
plt.show()
下图是运行结果,X轴表示 S
值,Y轴表示H
值,如下:
从图中可以看出,较高的值在 H=100和S=200附近,应该对应的是天空的蓝色。另外的高峰在 H=25和S=100附近,应该对应的是黄色的墙面(因为我们提前知道H值和S值对应的颜色,上面的论述中也强调了这一点)。
方法3:OpenCV sample style
上面我们说过,使用OpenCV绘制的2D直方图是灰度图,无法显示特定的颜色。那么应该操作如下:在HSV空间创建颜色图。然后转为BGR。然后将CV计算的直方图乘以该颜色图。当然也有一些预处理,比如移除孤立的像素。
下面是结果,可以看出,从2D直方图就可以看出对应图像中的区域: