目标
在本章中,我们将学习如何找到并绘制二维直方图。 这将对后续章节有所帮助。
简介
在第一篇文章中,我们计算并绘制了一维直方图。 之所以称为一维,是因为我们只考虑一个特征,即像素的灰度强度值。 但是在二维直方图中,您会考虑两个特征。 通常,它用于查找颜色直方图,其中两个特征是每个像素的色调和饱和度值。
已经有一个 python 示例 (samples/python/color_histogram.py) 用于查找颜色直方图。 我们将尝试了解如何创建这样的颜色直方图,这将有助于理解诸如直方图反投影之类的后续主题。
OpenCV 中的二维直方图
它非常简单,可以使用相同的函数 cv.calcHist() 来计算。 对于颜色直方图,我们需要将图像从 BGR 转换为 HSV。 (记住,对于一维直方图,我们从 BGR 转换为灰度)。 对于二维直方图,其参数将被修改如下
- channels = [0,1] 因为我们需要处理 H 和 S 平面。
- bins = [180,256] H 平面为 180,S 平面为 256。
- range = [0,180,0,256] 色调值介于 0 和 180 之间,饱和度介于 0 和 256 之间。
现在查看下面的代码
import numpy as np
import cv2 as cv
assert img is not None, "file could not be read, check with os.path.exists()"
hist =
cv.calcHist([hsv], [0, 1],
None, [180, 256], [0, 180, 0, 256])
CV_EXPORTS_W Mat imread(const String &filename, int flags=IMREAD_COLOR_BGR)
从文件加载图像。
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0, AlgorithmHint hint=cv::ALGO_HINT_DEFAULT)
将图像从一个颜色空间转换为另一个颜色空间。
void calcHist(const Mat *images, int nimages, const int *channels, InputArray mask, OutputArray hist, int dims, const int *histSize, const float **ranges, bool uniform=true, bool accumulate=false)
计算一组数组的直方图。
就是这样。
Numpy 中的二维直方图
Numpy 也为此提供了一个特定的函数:np.histogram2d()。 (记住,对于一维直方图,我们使用了 np.histogram() )。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
assert img is not None, "file could not be read, check with os.path.exists()"
hist, xbins, ybins = np.histogram2d(h.ravel(),s.ravel(),[180,256],[[0,180],[0,256]])
第一个参数是 H 平面,第二个是 S 平面,第三个是每个平面的 bins 数,第四个是它们的范围。
现在我们可以查看如何绘制这个颜色直方图。
绘制二维直方图
方法 - 1:使用 cv.imshow()
我们得到的结果是一个大小为 180x256 的二维数组。 所以我们可以像通常一样,使用 cv.imshow() 函数来显示它们。 它将是一个灰度图像,除非您知道不同颜色的色调值,否则它不会给出太多关于颜色的概念。
方法 - 2:使用 Matplotlib
我们可以使用 matplotlib.pyplot.imshow() 函数来绘制具有不同颜色图的二维直方图。 它使我们更好地了解不同的像素密度。 但同样,除非您知道不同颜色的色调值,否则乍一看,它也不会让我们知道那里有什么颜色。 不过我更喜欢这种方法。 它简单且更好。
- 注意
- 在使用此函数时,请记住,为了获得更好的结果,插值标志应为 nearest。
考虑代码
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
assert img is not None, "file could not be read, check with os.path.exists()"
hist =
cv.calcHist( [hsv], [0, 1],
None, [180, 256], [0, 180, 0, 256] )
plt.imshow(hist,interpolation = 'nearest')
plt.show()
下面是输入图像及其颜色直方图。 X 轴显示 S 值,Y 轴显示色调。
image
在直方图中,您可以看到 H = 100 和 S = 200 附近的一些高值。它对应于天空的蓝色。 类似地,在 H = 25 和 S = 100 附近可以看到另一个峰值。它对应于宫殿的黄色。 您可以使用任何图像编辑工具(如 GIMP)来验证它。
方法 3:OpenCV 示例样式!!
OpenCV-Python2 示例 (samples/python/color_histogram.py) 中有一个颜色直方图示例代码。 如果您运行该代码,您可以看到直方图也显示了相应的颜色。 或者简单地说,它输出一个颜色编码的直方图。 它的结果非常好(尽管您需要添加额外的一堆行)。
在该代码中,作者在 HSV 中创建了一个颜色图。 然后将其转换为 BGR。 生成的直方图图像与此颜色图相乘。 他还使用一些预处理步骤来删除小的孤立像素,从而获得良好的直方图。
我将其留给读者运行代码、分析它并进行自己的 hack 操作。 下面是该代码对上述相同图像的输出
image
您可以在直方图中清楚地看到存在哪些颜色,蓝色存在,黄色存在,还有一些由于棋盘而产生的白色。 真好!!!