本章将学习如何查找和绘制二维直方图。这将在接下来的章节中有所帮助。
介绍
在第一篇文章中,我们计算并绘制了一维直方图。 它被称为一维,因为只考虑一个特征,即像素的灰度强度值。 但在二维直方图中,考虑了两个特征。 通常,它用于查找颜色直方图,其中两个特征是每个像素的色调和饱和度值。
官方示例中已经有一个python示例用于查找颜色直方图。 将尝试了解如何创建这样的颜色直方图,这将有助于理解直方图反投影等其他主题。
OpenCV中的二维直方图
非常简单,可使用相同的函数cv2.calcHist()
计算。
对于颜色直方图,需要将图像从BGR转换为HSV。(记住,对于1D直方图,我们从BGR转换为灰度)。
对于二维直方图,其参数将修改如下:
channels=[0,1]
,因为我们需要同时处理H和S平面。bins=[180256]
180用于H平面,256用于S平面。range=[0180,0256]
色调值在0到180之间,饱和度在0到256之间。
import cv2
import numpy as np
img = cv2.imread('/data/cvdata/home.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
from matplotlib import pyplot as plt
plt.imshow(hist)
<matplotlib.image.AxesImage at 0x7f9f2772ff20>
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('/data/cvdata/home.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hsv.shape
(384, 512, 3)
h = hsv[0]
s = hsv[1]
v = hsv[2]
hist, xbins, ybins = np.histogram2d(h.ravel(),s.ravel(),[180,256],[[0,180],[0,256]])
第一个参数是H平面,第二个参数是S平面,第三个参数是每个平面的箱数,第四个参数是它们的范围。
现在我们可以检查如何绘制这个颜色直方图。
绘制二维直方图
使用cv2.imshow()
结果是一个大小为180x256的二维数组。所以可以像往常一样显示它们,使用cv2.imshow()
函数。
这将是一张灰度图像,除非知道不同颜色的色调值,否则它不会给出太多关于颜色的信息。
使用Matplotlib
使用matplotlib.pyplot.imshow()
函数绘制具有不同颜色图的二维直方图。
让对不同的像素密度有了更好的了解。
但这也不能第一眼就知道是什么颜色,除非知道不同颜色的色调值。
相比较还是更喜欢这种方法。它简单而更好。
注意: 使用此函数时,请记住,插值标志应该最接近以获得更好的结果。
代码如下:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('/data/cvdata/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=100和S=200附近的一些高值。它对应于天空的蓝色。 类似地,在H=25和S=100附近可以看到另一个峰值。它对应于宫殿的黄色。 可以使用GIMP等任何图像编辑工具进行验证。
OpenCV示例样式
OpenCV-Python2示例中有一个颜色直方图的示例代码。如果运行代码,可以看到直方图也显示了相应的颜色。 或者简单地输出一个颜色编码的直方图。结果非常好(尽管需要添加额外的行)。
在该代码中,作者用HSV创建了一个颜色图。然后将其转换为BGR。 将得到的直方图图像与此颜色图相乘。还使用了一些预处理步骤来去除小的孤立像素,从而得到一个好的直方图。
下面把运行代码、分析代码和解决问题的方法留给读者。以下是与上述图像相同的代码的输出:
可以在直方图中清楚地看到存在的颜色,蓝色在那里,黄色在那里,还有一些棋盘上的白色。