欢迎光临散文网 会员登陆 & 注册

【第20节】OpenCV直方图

2022-11-28 15:29 作者:海鸥之道  | 我要投稿

目标

  • 使用OpenCV或Numpy函数计算直方图

  • 使用OpenCV或Matplotlib函数绘制直方图

  • 将要学习的函数有:CV2.calcHist(),np.histogram()

原理

        什么是直方图呢?通过直方图你可以对整幅图像的灰度分布有一个整体的了解。 直方图的x 轴是灰度值(0到255 ), y轴是图片 中具有同一个灰度值的点的数目。

        直方图其实就是对图像的另一种解释。以下图为例,通过直方图我们可以对图像的对比度,亮度,灰度分布等有一个直观的认识。几乎所有的图像处理软件都提供了直方图分析功能。

下图来自Cambridge(https://www.cambridgeincolour.com/tutorials/histograms1.htm),强烈推荐你到这个网站了解更多知识。

        让我们来一起看看这幅图片和它的直方图吧。(要记住,直方图是根据灰度图像绘制的,而不是彩色图像)。直方图的左边区域像是了暗一点的像素数量,右侧显示了亮一点的像素的数量。从这幅图上你可以看到灰暗的区域比两的区域要大,而处于中间部分的像素点很少。

1、统计直方图

        现在我们知道什么是直方图了,那怎样获得一副图像的直方图呢?OpenCV和Numpy都有内置函数做这件事。在使用这些函数之前我们有必要想了解一下直方图相关的术语。

        BINS:上面的直方图显示了每个灰度值对应的像素数。如果像素值为0

到255,你就需要256个数来显示上面的直方图。但是,如果你不需要知道每一个像素值的像素点数目的,而只希望知道两个像素值之间的像素点数目怎么办呢?举例来说,我们想知道像素值在0到15之间的像素点的数目,接着是16到3.....240到255。我们只需要16个值来绘制直方图。OpenCV Tutorials on histograms(https://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html#histogram-calculation)中例子所演示的内容。

        那到底怎么做呢?你只需要把原来的256个值等分成16小组,取每组的总和。而这里的每一个小组就被成为BIN。第一个例子中有256个BIN,第二个例子中有16个BIN。在OpenCV的文档中用histSize表示BINS。

        DIMS:表示我们收集数据的参数数目。在本例中,我们对收集到的数据.

只考虑一件事:灰度值。所以这里就是1。

        RANGE:就是要统计的灰度值范围,-般来说为[0, 256],也就是说所

有的灰度值

        使用OpenCV统计直方图函数 CV2.calcHist可以帮助我们统计一幅图像的直方图。我们一起来熟悉一下这个函数和它的参数:

1. images:原图像(图像格式为uint8或float32 )。当传入函数时应该用中括号[]括起来,例如: [img]。.

2. channels:同样需要用中括号括起来,它会告诉函数我们要统计那幅图像的直方图。如果输入图像是灰度图,它的值就是[0];如果是彩色图像的话,传入的参数可以是[0], [1], [2] 它们分别对应着通道B, G, R。

3. mask:掩模图像。要统计整幅图像的直方图就把它设为None。但是如果你想统计图像某一部分的直方图的话, 你就需要制作一个掩模图像, 并使用它。(后边有例子)

4. histSize:BIN的数目。也应该用中括号括起来,例如: [256]。

5. ranges:像素值范围,通常为[0, 256]

        让我们从一副简单图像开始吧。以灰度格式加载一幅图像并统计图像的直方图。

        hist是一个256x1的数组,每一个值代表了与次灰度值对应的像素点数目。使用Numpy统计直方图Numpy 中的函数np.histogram()也可以帮我们统计直方图。你也可以尝试一下下面的代码:

        hist与上面计算的一样。但是这里的bins是257,因为Numpy计算bins的方式为: 0-0.99,1-1.99,2-2.99等。所以最后一个范围是255-255.99。为了表示它,所以在bins的结尾加上了256。但是我们不需要256,到255就够了。

其他: Numpy还有一个函数np.bincount(, 它的运行速度是np.histgram的十倍。所以对于一维直方图,我们最好使用这个函数。使用np.bincount 时别忘了设置minlength=256。例如,hist= np.bincount(img.ravelO, minlength= 256)

注意: OpenCV的函数要比np.histgram()快40倍。所以坚持使用OpenCV函数。

2、绘制直方图

有两种方法来绘制直方图:

    1)Short Way(简单方法):使用 Matplotlib 中的绘图函数。

    2)Long Way(复杂方法):使用 OpenCV 绘图函数

使用Matplotlib 

Matplotlib 中直方图绘制函数:matplotlib.pyplot.hist(),示例如下:

你会得到下面这样一幅图:

        或者你可以只使用matplotlib的绘图功能,这在同时绘制多通道( BGR )的直方图,很有用。但是你首先要告诉绘图函数你的直方图数据在哪里。运行一下下面的代码:

结果:

使用OpenCV

使用Opencv自带的绘图函数比较麻烦,这里不做推荐,给出示例代码,有兴趣的自己可以研究:

结果显示:

3、使用掩膜

        要统计图像某个局部区域的直方图只需要构建一副掩模图像。将要统计的部分设置成白色,其余部分为黑色,就构成了一副掩模图像。然后把这个掩模图像传给函数就可以了。

结果如下,其中蓝线是整幅图像的直方图,橘黄色是进行掩膜之后的直方图。





【第20节】OpenCV直方图的评论 (共 条)

分享到微博请遵守国家法律