python OpenCV学习笔记之绘制直方图的方法
作者:JS_XH 发布时间:2023-06-04 02:34:38
本篇文章主要介绍了python OpenCV学习笔记之绘制直方图的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
官方文档 – https://docs.opencv.org/3.4.0/d1/db7/tutorial_py_histogram_begins.html
直方图会让你对图像的强度分布有一个全面的认识。它是一个在x轴上带有像素值(从0到255,但不总是),在y轴上的图像中对应的像素数量的图。
这只是理解图像的另一种方式。通过观察图像的直方图,你可以直观地看到图像的对比度、亮度、强度分布等。现在几乎所有的图像处理工具都提供了直方图的特性。下面是剑桥彩色网站的图片,建议去访问这个网站,了解更多细节。
你可以看到图像和它的直方图。(这个直方图是用灰度图像绘制的,而不是彩色图像)。直方图的左边部分显示了图像中较暗像素的数量,右边区域显示了更明亮的像素。从直方图中可以看到,深色区域的像素数量比亮色区域更多,而中间色调的数量(中值大约在127左右)则少得多。
直方图
现在我们已经知道了什么是直方图,我们可以看看如何找到它。OpenCV和Numpy都有内置的功能。在使用这些函数之前,我们需要了解一些与直方图相关的术语。
BINS:上面的直方图显示了每个像素值的像素数,从0到255。您需要256个值来显示以上的直方图。但是,考虑一下,如果您不需要单独查找所有像素值的像素数量,而是在一个像素值区间内的像素数量,该怎么办?例如,你需要找到介于0到15之间的像素数,然后是16到31……240到255。您只需要16个值来表示这个直方图。OpenCV Tutorials on histograms中展示了这个例子。
所以你要做的就是把整个直方图分成16个子部分,每个子部分的值是所有像素数的和。每个子部分都被称为“BIN”。在第一种情况下,BINS的数量是256(每个像素一个),而在第二种情况下,它只有16个。在OpenCV文档中,用术语 histSize 表示 BINS。
DIMS:它是我们收集数据的参数的个数。在这种情况下,我们收集的数据只有一件事,强度值。所以这里是1。
RANGE:它是你想测量的强度值的范围。通常,它是 [ 0,256 ],也就是所有的强度值。
OpenCV中直方图的计算
现在我们使用cv.calcHist()
函数来找到直方图。让我们熟悉一下这个函数及其参数: cv.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
images:它是uint8类型或float32的源图像。它应该用方括号括起来,也就是”[img]”。
channels:它也用方括号括起来。它是我们计算直方图的信道的索引。例如,如果输入是灰度图像,它的值是0。对于颜色图像,您可以通过0、1或2来分别计算蓝色、绿色或红色通道的直方图。
mask:遮罩图。为了找到完整图像的直方图,它被指定为“None”。但如果你想找到图像的特定区域的直方图,你必须为它创建一个遮罩图,并将其作为遮罩。
histSize:这代表了我们的BINS数。需要用方括号来表示。在整个范围内,我们通过了256。
ranges:强度值范围,通常是 [ 0,256 ]
让我们从一个样本图像开始。只需在灰度模式下加载图像并找到其完整的直方图。
img = cv.imread('home.jpg', 0)
hist = cv.calcHist([img], [0], None, [256], [0,256])
hist是一个256x1阵列,每个值对应于该图像中的像素值及其对应的像素值。
Numpy中直方图的计算
Numpy中提供了np.histogram()
方法
hist, bins = np.histogram(img.ravel(), 356, [0,256])
hist和之前计算的一样。但是bins有257个元素,因为Numpy计算bins是以0-0.99,1-1.99等,所以最后一个是255-255.99。为了表示这一点,他们还在bins的末端添加了256。但我们不需要256。到255就足够了。
Numpy还有另一个函数,np.bincount()
,比np.histograme()
要快得多(大约10X)。对于一维直方图,你可以试一下。不要忘记在np.bincount中设置minlength=256。例如,hist=np.bincount(img.ravel(),minlength=256)
OpenCV函数比np.histogram()
快(大约40X)。所以坚持用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官方的样本了。检查sampl/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)
#Calculate histogram with mask and without mask
Check third argument for 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()
蓝线表示完整图片的直方图
绿线表示遮罩之后的直方图
来源:http://blog.csdn.net/js_xh/article/details/79262886


猜你喜欢
- 目录1. 最直观的相加2. 借助 itertools3. 使用 * 解包4. 使用 extend5. 使用列表推导式6. 使用 heapq7
- 导语好消息!下一个假期已经在路上了,正在向我们招手呢!大家只要再坚持5天就能迎来中秋小长假啦~“海上生明月,天涯共此时”又是一年中秋至!快跟
- 本文实例讲述了Python基于csv模块实现读取与写入csv数据的方法。分享给大家供大家参考,具体如下:通过csv模块可以轻松读取格式为cs
- 如果想让字典的VALUE成为字典,只有最开始让其成为列表,如下面程序中的b>>> b={}>>> b={
- 如下所示:mystring.strip().replace(' ', '').replace('\n
- 在运维场景下,我们经常需要在服务器上用正则表达式来匹配IP地址。shell和其它编程语言一样,也可以使用正则分组捕获,不过不能使用 $1或\
- 定义流的作用是使用统一的方式处理文件、网络和数据压缩等共用同一套函数和用法的操作。简单而言,流是具有流式行为的资源对象。因此,流可以线性读写
- 这篇文章主要介绍了python enumerate内置函数用法总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价
- MySQL清空表数据清空表数据一共有三种方式1 、truncate (速度很快) 自增字段清空从1开始 全表清空首选2、drop 直接删表&
- 影响的范围: IE的所有版本在表单的radio/checkbox控件中,一旦他们的DOM结构被更改过就会出现这个bug。bug描述当象下例中
- 运行python程序时,有时需要在命令行传入一些参数。常见的方式是在执行时,在脚本名后直接追加空格分隔的参数列表(例如 python tes
- 之前写了一个ajax上传工具。但是只是客户端的工具是我写的,服务器端的那个程序,我是修改了一个网上流传的无组件上传类。因为当时我还不懂什么a
- 前言这篇博文的目的是演示如何使用 OpenCV、Python 和面部标志对齐人脸。给定一组面部标志(输入坐标),我们的目标是将图像扭曲并转换
- 在访问数据库时,特别是新手,可能会需要查询表中数据总数,以下这段代码可以非常简便的获取到数据数目//先建立数据库连接,执行查询语句Conne
- Mysql参数优化对于新手来讲,是比较难懂的东西,其实这个参数优化,是个很复杂的东西,对于不同的网站,及其在线量,访问量,帖子数量,网络情况
- 安装MySQL假设你把所有必须的源码或者包都放在了/tmp下。如果你下载的是RPM包的话,那比较简单;如果你下载的是二进制包(你没有rpm程
- 如下所示:import numpy as np a=np.random.randint(0,10,size=[3,3,3])print(a)
- 下面我摘录了SQL Server官方教程中的一段关于触发器的文字,确实有用的一点文字描述。 可以定义一个无论何时用INSERT语句向表中插入
- 本文实例讲述了Python实现简单的列表冒泡排序和反转列表操作。分享给大家供大家参考,具体如下:# -*- coding:utf-8 -*-
- 1. python中创建新的csv文件(1). 使用csv.writer()创建:代码如下:import csvheaders = [