前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >opencv(4.5.3)-python(二十三)--直方图的寻找、绘制、分析

opencv(4.5.3)-python(二十三)--直方图的寻找、绘制、分析

作者头像
用户9875047
发布2023-02-26 15:12:59
7470
发布2023-02-26 15:12:59
举报
文章被收录于专栏:机器视觉全栈er机器视觉全栈er

翻译及二次校对:cvtutorials.com

目标

学习:

  • • 使用OpenCV和Numpy函数寻找直方图
  • • 使用OpenCV和Matplotlib函数绘制直方图
  • • 你将看到这些函数:cv.calcHist(), np.histogram()等。

理论

那么什么是直方图?你可以把直方图看作是一种图,它可以让你对图像的灰度分布有一个整体的了解。它是一个在X轴上有像素值(范围从0到255,不一定),在Y轴上有图像中相应像素数的图。

它只是理解图像的另一种方式。通过观察图像的直方图,你可以获得关于该图像的对比度、亮度、灰度分布等的直觉。今天,几乎所有的图像处理工具都提供直方图的功能。下面是一张来自Cambridge in Color网站的图片,我建议你访问该网站了解更多细节。

你可以看到这个图像和它的直方图(这个直方图是为灰度图像绘制的,不是彩色图像)。直方图的左边区域显示图像中较暗像素的数量,右边区域显示较亮像素的数量。从直方图中,你可以看到暗色区域比亮色区域多,中间色调(中间范围的像素值,例如127左右)的数量非常少。

寻找直方图

现在我们对什么是直方图有了一个概念,我们可以研究如何找到它。OpenCV和Numpy都有内置的函数来完成这个任务。在使用这些函数之前,我们需要了解一些与直方图有关的术语。

BINS :上面的直方图显示了每个像素值的像素数,即从0到255,即你需要256个值来显示上述直方图。但请考虑,如果你不需要单独找到所有像素值的像素数,而是需要找到像素值的一个区间的像素数,怎么办?例如,你需要找到0到15之间的像素数,然后是16到31,...,240到255。你只需要16个值来表示直方图。

所以你要做的就是简单地把整个直方图分成16个子部分,每个子部分的值是其中所有像素数的总和。这个子部分被称为 "BIN"。在第一种情况下,BIN的数量是256(每个像素一个),而在第二种情况下,它只有16。在OpenCV的文档中,BINS是由术语histSize表示的。

DIMS : 它是我们收集数据的参数数量。在这种情况下,我们只收集一种数据,即灰度值。所以这里是1。

RANGE : 它是你想测量的灰度值的范围。通常情况下,它是[0,256],即所有灰度值。

  1. 1. OpenCV中的直方图计算

所以现在我们使用cv.calcHist()函数来寻找直方图。让我们熟悉一下这个函数和它的参数。

cv.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]] )

  • • images : 它是类型为uint8或float32的源图像,应在方括号内给出,即"[img]"。
  • • channels : 它也是在方括号中给出的。它是我们计算直方图的通道的索引。例如,如果输入的是灰度图像,它的值是[0]。对于彩色图像,你可以通过[0]、[1]或[2]来分别计算蓝色、绿色或红色通道的直方图。
  • • mask : 掩膜图像。要查找完整图像的直方图,它被指定为 "None"。但如果你想找到图像特定区域的直方图,你必须为其创建一个掩膜图像并将其作为掩膜(我将在后面展示一个例子)
  • • histSize:这代表我们的BIN计数。需要在方括号中给出。对于满刻度,我们传递256。
  • • ranges : 这是我们的RANGE。通常情况下,它是[0,256]。

那么,让我们从一个图像开始。简单地在灰度模式下加载一个图像,然后找到它的直方图。

代码语言:javascript
复制
img = cv.imread('home.jpg',0)
hist = cv.calcHist([img],[0],None,[256],[0,256])

hist是一个256x1的数组,每个值都对应于该图像中的像素数和其对应的像素值。

  1. 1. Numpy中的直方图计算

Numpy还为你提供了一个函数,np.histogram()。所以你可以用下面这行来代替calcHist()函数。

代码语言:javascript
复制
hist,bins = np.histogram(img.ravel(),256,[0,256])

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.histogram()快得多(大约10倍)。所以对于一维直方图,你最好试试这个。不要忘记在np.bincount中设置minlength = 256。例如,hist = np.bincount(img.ravel(),minlength=256) OpenCV函数比np.histogram()快(大约40倍)。所以请使用OpenCV函数。

现在我们应该绘制直方图,但如何绘制呢?

绘制直方图

有两种方法可以做到这一点。

  • • 方法1:使用Matplotlib的绘图函数
  • • 方法2:使用OpenCV绘图函数
  1. 1. 使用Matplotlib

Matplotlib有一个直方图绘制函数:matplotlib.pyplot.hist()

它直接找到直方图并绘制出来。你不需要使用calcHist()或np.histogram()函数来寻找直方图。请看下面的代码。

代码语言:javascript
复制
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('home.jpg',0)
plt.hist(img.ravel(),256,[0,256]); plt.show()

你会得到一个如下的图。

或者你可以使用matplotlib的正常绘图模式,这对BGR图很有帮助。为此,你需要先找到直方图的数据。试试下面的代码。

代码语言:javascript
复制
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('home.jpg')
color = ('b', 'g', 'r')
for i,col in enumerate(color):
    histr = cv.calcHist([img],[i],None,[256],[0,256])
    plt.plot(histr,color = col)
    plt.xlim([0,256])
plt.show()

结果:

你可以从上图中推断出,蓝色在图像中有一些高值区域(显然应该是由于天空的原因)。

  1. 1. 使用OpenCV

我们可以将直方图的值和它的bin值调整成x,y坐标的样子,这样你就可以用cv.line()或cv.polyline()函数来绘制它,生成与上面相同的图像。这在OpenCV-Python2官方样本中已经有了。请查看样本/python/hist.py中的代码。

掩膜的应用

我们用cv.calcHist()来寻找全图的直方图。如果你想找到图像中某些区域的直方图呢?只要在你想找直方图的区域创建一个白色的蒙版图像,其他区域设置为黑色。然后把它作为掩膜传给你。

代码语言:javascript
复制
img = cv.imread('home.jpg',0)
# 创建一个掩膜
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv.bitwise_and(img,img,mask = mask)
# 计算带掩膜和不带掩膜的直方图
# 检查第三个参数的掩膜
hist_full = cv.calcHist([img],[0],None,[256],[0,256] )
hist_mask = cv.calcHist([img],[0],mask,[256],[0,256] )
plt.subplot(221), plt.imshow(img, 'grey')
plt.subplot(222), plt.imshow(mask,'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0,256])
plt.show()

请看结果。在直方图图中,蓝线显示的是完整图像的直方图,而绿线显示的是被遮蔽区域的直方图。

其他资源

  • • 彩色剑桥
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-12-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器视觉全栈er 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
灰盒安全测试
腾讯知识图谱(Tencent Knowledge Graph,TKG)是一个集成图数据库、图计算引擎和图可视化分析的一站式平台。支持抽取和融合异构数据,支持千亿级节点关系的存储和计算,支持规则匹配、机器学习、图嵌入等图数据挖掘算法,拥有丰富的图数据渲染和展现的可视化方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档