目标

学会

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

理论

那么直方图是什么?您可以将直方图视为图形或绘图,从而可以总体了解图像的强度分布。它是在X轴上具有像素值(不总是从0到255的范围),在Y轴上具有图像中相应像素数的图。

这只是理解图像的另一种方式。通过查看图像的直方图,您可以直观地了解该图像的对比度,亮度,强度分布等。当今几乎所有图像处理工具都提供直方图功能。以下是剑桥彩色网站的图片,我建议您访问该网站以获取更多详细信息。

您可以看到图像及其直方图。(请记住,此直方图是针对灰度图像而非彩色图像绘制的)。直方图的左侧区域显示图像中较暗像素的数量,而右侧区域则显示明亮像素的数量。从直方图中,您可以看到暗区域多于亮区域,而中间调的数量(中间值的像素值,例如127附近)则非常少。

寻找直方图

现在我们有了一个关于直方图的想法,我们可以研究如何找到它。OpenCV和Numpy都为此内置了功能。在使用这些功能之前,我们需要了解一些与直方图有关的术语。

BINS:上面的直方图显示每个像素值的像素数,即从0到255。即,您需要256个值来显示上面的直方图。但是考虑一下,如果您不需要分别找到所有像素值的像素数,而是找到像素值间隔中的像素数怎么办?

例如,您需要找到介于0到15之间的像素数,然后找到16到31之间,…,240到255之间的像素数。只需要16个值即可表示直方图。这就是在OpenCV教程中有关直方图的示例中显示的内容。

因此,您要做的就是将整个直方图分成16个子部分,每个子部分的值就是其中所有像素数的总和。

每个子部分都称为“ BIN”。在第一种情况下,bin的数量为256个(每个像素一个),而在第二种情况下,bin的数量仅为16个。BINS由OpenCV文档中的histSize术语表示。

DIMS:这是我们为其收集数据的参数的数量。在这种情况下,我们仅收集关于强度值的一件事的数据。所以这里是1。

RANGE:这是您要测量的强度值的范围。通常,它是[0,256],即所有强度值。

1. OpenCV中的直方图计算

因此,现在我们使用cv.calcHist()函数查找直方图。让我们熟悉一下该函数及其参数:

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

  1. images:它是uint8或float32类型的源图像。它应该放在方括号中,即“ [img]”。
  2. channels:也以方括号给出。它是我们计算直方图的通道的索引。例如,如果输入为灰度图像,则其值为[0]。对于彩色图像,您可以传递[0],[1]或[2]分别计算蓝色,绿色或红色通道的直方图。
  3. mask:图像掩码。为了找到完整图像的直方图,将其指定为“无”。但是,如果要查找图像特定区域的直方图,则必须为此创建一个掩码图像并将其作为掩码。(我将在后面显示一个示例。)
  4. histSize:这表示我们的BIN计数。需要放在方括号中。对于全尺寸,我们通过[256]。
  5. ranges:这是我们的RANGE。通常为[0,256]。

因此,让我们从示例图像开始。只需以灰度模式加载图像并找到其完整直方图即可。

img = cv.imread('home.jpg',0)
hist = cv.calcHist([img],[0],None,[256],[0,256])

hist是256x1的数组,每个值对应于该图像中具有相应像素值的像素数。

2. numpy的直方图计算

Numpy还为您提供了一个函数np.histogram()。因此,除了calcHist()函数外,您可以尝试下面的代码:

hist,bins = np.histogram(img.ravel(),256,[0,256])

hist与我们之前计算的相同。但是bin将具有257个元素,因为Numpy计算出bin的范围为0-0.991-1.992-2.99等。因此最终范围为255-255.99。为了表示这一点,他们还在最后添加了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. 使用Matplotlib

Matplotlib带有直方图绘图功能:matplotlib.pyplot.hist()

它直接找到直方图并将其绘制。您无需使用calcHist()或np.histogram()函数来查找直方图。请参见下面的代码:

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图是很好的。为此,您需要首先找到直方图数据。试试下面的代码:

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

结果:

您可以从上图中得出,蓝色在图像中具有一些高值域(显然这应该是由于天空)

2. 使用 OpenCV

好吧,在这里您可以调整直方图的值及其bin值,使其看起来像x,y坐标,以便您可以使用cv.line()或cv.polyline()函数绘制它以生成与上述相同的图像。OpenCV-Python2官方示例已经提供了此功能。检查示例/python/hist.py中的代码。

掩码的应用

我们使用了cv.calcHist()来查找整个图像的直方图。如果你想找到图像某些区域的直方图呢?只需创建一个掩码图像,在你要找到直方图为白色,否则黑色。然后把这个作为掩码传递。

img = cv.imread('home.jpg',0)
# create a mask
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, 'gray')
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()

查看结果。在直方图中,蓝线表示完整图像的直方图,绿线表示掩码区域的直方图。

附加资源

  1. Cambridge in Color website:http://www.cambridgeincolour.com/tutorials/histograms1.htm

欢迎关注磐创博客资源汇总站:

http://docs.panchuang.net/

欢迎关注PyTorch官方中文教程站:

http://pytorch.panchuang.net/

OpenCV中文官方文档:

http://woshicver.com/

OpenCV-Python 直方图-1:查找、绘制和分析 | 二十六的更多相关文章

  1. ❤️【Python从入门到精通】(二十六)用Python的PIL库(Pillow)处理图像真的得心应手❤️

    您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 本篇重点介绍Python处理图像的标准库PIL库,处理图像真的的很方便. 干货满满,建议收藏,需要用到时常看看. 小伙伴们如有问题及需要,欢迎踊跃 ...

  2. ABP源码分析二十六:核心框架中的一些其他功能

    本文是ABP核心项目源码分析的最后一篇,介绍一些前面遗漏的功能 AbpSession AbpSession: 目前这个和CLR的Session没有什么直接的联系.当然可以自定义的去实现IAbpSess ...

  3. Python脚本控制的WebDriver 常用操作 <二十六> 上传文件

    测试用例场景 上传文件的方法是找到上传文件的对象,通常是的对象.然后直接往这个对象send_keys,传入需要上传文件的正确路径.绝对路径和相对路径都可以,但是上传的文件必须存在,否则会报错. Pyt ...

  4. Vue.js 源码分析(二十六) 高级应用 作用域插槽 详解

    普通的插槽里面的数据是在父组件里定义的,而作用域插槽里的数据是在子组件定义的. 有时候作用域插槽很有用,比如使用Element-ui表格自定义模板时就用到了作用域插槽,Element-ui定义了每个单 ...

  5. 二十六. Python基础(26)--类的内置特殊属性和方法

    二十六. Python基础(26)--类的内置特殊属性和方法 ● 知识框架 ● 类的内置方法/魔法方法案例1: 单例设计模式 # 类的魔法方法 # 案例1: 单例设计模式 class Teacher: ...

  6. python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码

    python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码 python的json.dumps方法默认会输出成这种格式"\u535a\u ...

  7. spark 源码分析之十六 -- Spark内存存储剖析

    上篇spark 源码分析之十五 -- Spark内存管理剖析 讲解了Spark的内存管理机制,主要是MemoryManager的内容.跟Spark的内存管理机制最密切相关的就是内存存储,本篇文章主要介 ...

  8. python接口自动化(二十六)--批量执行用例 discover(详解)

    简介 我们在写用例的时候,单个脚本的用例好执行,那么多个脚本的时候,如何批量执行呢?这时候就需要用到 unittest 里面的 discover 方法来加载用例了.加载用例后,用 unittest 里 ...

  9. Python学习之旅(二十六)

    Python基础知识(25):常用内建模块 1.datetime:处理日期和时间 (1)获取当前日期和时间 from datetime import datetime now = datetime.n ...

随机推荐

  1. CentOS7 安装python 3.5 及 pip安装

    1.CentOS7 安装Python 的依赖包 # yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-d ...

  2. ASP.NET CORE 启动过程及源码解读

    在这个特殊的春节,大家想必都在家出不了们,远看已经到了回城里上班的日子,但是因为一只蝙蝠的原因导致我们无法回到工作岗位,大家可能有的在家远程办公,有些在家躺着看书,有的是在家打游戏:在这个特殊无聊的日 ...

  3. 数据结构 1 线性表详解 链表、 栈 、 队列 结合JAVA 详解

    前言 其实在学习数据结构之前,我也是从来都没了解过这门课,但是随着工作的慢慢深入,之前学习的东西实在是不够用,并且太皮毛了.太浅,只是懂得一些浅层的,我知道这个东西怎么用,但是要优化.或者是解析,就不 ...

  4. OpenFlow(OVS)下的“路由技术”

    前言 熟悉这款设备的同学,应该也快到不惑之年了吧!这应该是Cisco最古老的路由器了.上个世纪80年代至今,路由交换技术不断发展,但是在这波澜壮阔的变化之中,总有一些东西在嘈杂的机房内闪闪发光,像极了 ...

  5. 一块小饼干(Cookie)的故事-下篇

    上篇介绍了注册的基本流程,下篇简单的讲讲登录的流程以及Cookie的出现 实现登录的小功能 当你在浏览器的输入框里输入localhost:8080/sign_in的时候,会发起GET请求,去访问sig ...

  6. nginx如何连接多个服务?

    记录一下: 刚开始用nginx部署,在项目文件内touch了一个nginx.conf配置文件,然后将这个conf文件软链接到nginx的工作目录中 sudo ln -s /home/ubuntu/xx ...

  7. HDFS 客户端读写操作详情

    1. 写操作 客户端向namenode发起上传请求 namenode检查datanode是否已经存有该文件,并且检查客户端的权限 确认可以上传后,根据文件块数返回datanode栈 注:namenod ...

  8. 16 搭建Spring Data JPA的开发环境

    使用Spring Data JPA,需要整合Spring与Spring Data JPA,并且需要提供JPA的服务提供者hibernate,所以需要导入spring相关坐标,hibernate坐标,数 ...

  9. 浅谈Spring框架

    一.Spring简介 Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的.框架的主要优势之一就是其分层架构, 分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集 ...

  10. 编译putty 源码去掉 Are you sure you want to close this session? 提示

    0, 为什么要编译 putty ?在关闭窗口的时候,会弹出一个 Are you sure you want to close this session?要把这个去掉.当然也可以用 OD 之类的来修改. ...