当前位置: 首页 > 文档资料 > OpenCV 中文文档 >

4.9.3 二维直方图

优质
小牛编辑
125浏览
2023-12-01

目标

在本章中,我们将学习查找和绘制二维直方图。这将在未来的章节中有所帮助。

介绍

在第一篇文章中,我们计算和绘制了一维直方图。它是一维的,因为我们只考虑一个特征,即像素的灰度强度值。但是在二维直方图中,您会考虑两个特征。通常在查找颜色直方图时,这两个特征是每个像素的色调和饱和度值。

有一个 python 示例(samples/python/color_histogram.py)已经用于展示如何查找颜色直方图。我们将尝试了解如何创建这样一个颜色直方图,这将有助于理解进一步的主题,如直方图反向投影。

OpenCV 中的 2D 直方图

这很简单,同样使用函数 cv2.calcHist() 进行计算。对于颜色直方图,我们需要将图像从 BGR 转换为 HSV。 (请记住,对于一维直方图,我们从 BGR 转换为灰度)。对于 2D 直方图,其参数将被修改如下:

  • channels = [0,1],因为我们需要处理 H 和 S 平面。
  • bins = [180,256],180 for H 平面,256 for S 平面。
  • range = [0,180,0,256],色调值介于 0 和 180 之间,饱和度介于 0 和 256 之间。

现在看看下面的代码:

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])

Numpy 中的二维直方图

Numpy 还为此提供了一个专用函数:np.histogram2d()。 (请记住,对于一维直方图,我们使用 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)
hist, xbins, ybins = np.histogram2d(h.ravel(),s.ravel(),[180,256],[[0,180],[0,256]])

第一个参数是H平面,第二个是S平面,第三个是面元的数量,第四个是他们的范围。

现在我们可以来看看如何绘制这个颜色直方图。

绘制二维直方图

方法1:使用 cv2.imshow()

我们得到的结果是一个尺寸为180x256的二维数组。所以我们可以使用cv2.imshow()函数正常显示它们。这将是一个灰度图像,它不会给出太多的颜色信息,除非你知道不同颜色的色调值。

方法2:使用 Matplotlib

我们可以使用 matplotlib.pyplot.imshow() 函数来绘制不同颜色贴图的二维直方图。它给了我们关于不同像素密度的更多信息。但是,这也不能让我们一眼看出是什么颜色,除非你知道不同颜色的色调值。不过我更喜欢这种方法。这很简单,更好。

使用此功能时,请记住,插值标志应该是 nearest,以获得更好的结果。

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 = 100和S = 200附近的一些高值。它对应于天空的蓝色。同样,在H = 25和S = 100附近可以看到另一个峰值。它对应于宫殿的黄色。您可以使用任何图像编辑工具(如GIMP)来验证它。

方法3:OpenCV 示例风格

在OpenCV-Python示例(samples/python/color_histogram.py)中有一个用于颜色直方图的示例代码。

如果你运行代码,你可以看到直方图也显示相应的颜色。或者只是输出一个颜色编码的直方图。其结果是非常好的(尽管你需要添加额外的线)。

在该代码中,作者在HSV中创建了一个色彩图。然后转换成BGR。得到的直方图图像与该颜色图相乘。他还使用了一些预处理步骤去除小的孤立像素,从而得到一个很好的直方图。

我把运行代码,分析它,并自己 hack 一下的任务留给读者。

你可以在直方图中清楚地看到有什么颜色存在,蓝色在那里,黄色在那里,还有一些白色(因为图中有一个棋盘图案)在那里。