OpenCV-Python(22):直方图的计算绘制与分析

目标

  • 了解直方图的原理及应用
  • 使用OpenCV 或Numpy 函数计算直方图
  • 使用Opencv 或者Matplotlib 函数绘制直方图
  • 学习函数cv2.calcHist()、np.histogram()等

原理及应用

        直方图是一种统计图形,是对图像的另一种解释,用于表示图像中各个像素值的频次分布。直方图的x 轴是灰度值(0 到255),y 轴是图片中具有同一个灰度值的点的数目。通过直方图你可以对整幅图像的灰度分布、对比度、亮度等有一个整体的了解。在计算机视觉中,直方图是一种常用的图像特征描述方法,可以用于图像处理、图像分割、图像匹配等应用,几乎所有的图像处理软件提供了直方图分析功能。

        在图像处理中,直方图可以用于对图像进行增强、对比度调整、色彩均衡等操作。通过分析图像的直方图,可以了解图像的亮度分布情况,进而进行亮度调整,使图像更加清晰、明亮或暗淡。

        在图像分割中,直方图可以用于选择合适的阈值进行图像分割。通过分析图像的直方图,可以找到合适的阈值,将图像分成不同的区域,达到目标检测和图像分割的目的。

        在图像匹配中,直方图可以用于计算图像之间的相似度。通过比较两幅图像的直方图,可以得到它们的相似程度,从而实现图像的匹配和检索。

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

参考以下连接获取更多相关信息:https://www.cambridgeincolour.com/tutorials/histograms1.htm

统计直方图 

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

  • BINS

        上面的直方图显示了每个像素灰度值对应的像素数目。如果像素值为0到255,你就需要256 个数来显示上面的直方图。但是,如果你不需要知道每一个像素值的像素点数目,而只希望知道两个像素值之间的像素点数目怎么办呢?举例来说,我们想知道像素值在0 到15 之间的像素点的数目,接着是16 到31,....240 到255。我们只需要16 个值来绘制直方图即可。

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

  • DIMS

        表示我们收集数据的参数数目。在本例中,我们对收集到的数据只考虑一件事:灰度值。所以这里就是1。

  • RANGE

        就是要统的灰度值范围,一般来说为[0-256],也就是所有的灰度值。

cv2.calcHist()函数是OpenCV中用于计算图像直方图的函数。函数原型为:

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

参数解释:

  • images:输入图像(图像格式为uint8 或float32)。它应该是一个包含图像的列表,每个图像都是一个NumPy数组。
  • channels:指定要计算直方图的通道。它是以0为基础的索引,例如,对于灰度图像,它的值为[0],对于彩色图像,可以传递[0],[1]或[2]来计算蓝色、绿色或红色通道的直方图。
  • mask:眼膜图像,可选参数,用于指定要计算直方图的区域。如果不需要,则传递None。。但是如果你想统计图像某一部分的直方图的话,你就需要制作一个掩模图像并使用它。
  • histSize:指定直方图的大小。它表示直方图中有多少个BIN(柱子),即分成多少个区间,应该用中括号括起来,例如[256]
  • ranges:指定像素值的范围。一般情况下,它的值为[0, 256],表示像素值的范围为0到255。

返回值:

  • hist:计算的直方图。它是一个一维数组,表示每个bin的频次。

我们从一副简单图像开始吧,示例代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt# 读取图像
image = cv2.imread('image.jpg')# 将图像转换为灰度图像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 计算直方图,别忘了参数中的中括号,只有mask 没有中括号
hist = cv2.calcHist([gray_image], [0], None, [256], [0, 256])# 绘制直方图
plt.plot(hist)
plt.show()

        上述代码中,首先使用cv2.imread()函数读取图像,然后使用cv2.cvtColor()函数将图像转换为灰度图像。接着,调用cv2.calcHist()函数计算灰度图像的直方图,其中channels参数为[0]表示只计算灰度通道的直方图,mask参数为None表示计算整个图像的直方图,histSize参数为[256]表示直方图分成256个bin,ranges参数为[0, 256]表示像素值的范围为0到255。最后,使用matplotlib库中的plt.plot()函数绘制直方图。

使用Numpy 中的函数np.histogram() 也可以帮我们统计直方图。你也可以尝试以下代码:

#img.ravel() 将图像转换成一维数组,这里没有中括号。
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就够了。 

绘制直方图

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

  • 1. Short Way(简单方法):使用Matplotlib 中的绘图函数。
  • 2. Long Way(复杂方法):使用OpenCV 绘图函数

Matplotlib 中有直方图绘制函数matplotlib.pyplot.hist()它可以直接统计并绘制直方图。你应该使用函数calcHist() 或np.histogram()统计直方图。代码如下:

import cv2
import numpy as np
from matplotlib import pyplot as pltimg = cv2.imread('home.jpg',0)
plt.hist(img.ravel(),256,[0,256]);plt.show()

或者使用如下的方式:

mport cv2
import numpy as np
import matplotlib.pyplot as plt# 读取图像
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)# 计算灰度直方图
hist = cv2.calcHist([image], [0], None, [256], [0, 256])# 绘制直方图
plt.figure()
plt.title('Grayscale Histogram')
plt.xlabel('Bins')
plt.ylabel('# of Pixels')
plt.plot(hist)
plt.xlim([0, 256])
plt.show()

你会得到如下的图:

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

import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('home.jpg')
color = ('b','g','r')
# 对一个列表或数组既遍历索引又遍历历元素时
# 使用内置enumerrate 函数会有更加直接
#enumerate 会将数组或列表组成一个索引序列。
# 使我们再获取索引和索引内容的时候更加方便
for i,col in enumerate(color):histr = cv2.calcHist([img],[i],None,[256],[0,256])plt.plot(histr,color = col)plt.xlim([0,256])
plt.show()

从上面的直方图你可以推断出蓝色曲线右侧的最多,很明显那些就是天空。 使用OpenCV 自带函数绘制直方图比较麻烦,可以单独研究。 

使用掩模绘制直方图

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

img = cv2.imread('home.jpg',0)
# create a mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv2.bitwise_and(img,img,mask = mask)
# Calculate histogram with mask and without mask
# Check third argument for mask
hist_full = cv2.calcHist([img],[0],None,[256],[0,256])
hist_mask = cv2.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://www.mzph.cn/news/586896.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux驱动开发之杂项设备注册和Linux2.6设备注册

目录 一、杂项设备注册 杂项设备注册简介 杂项设备注册特点: 杂项设备注册相关API misc_register() misc_deregister() 杂项设备注册相关例程 例程简介 源码分享 二、Linux 2.6设备注册 Linux2.6设备注册简介 Linux 2.6设备注册特点 Linux2.6设备注册流程 ​Linu…

sklearn 中matplotlib编制图表

代码 # 导入pandas库,并为其设置别名pd import pandas as pd import matplotlib.pyplot as plt# 使用pandas的read_csv函数读取名为iris.csv的文件,将数据存储在iris_data变量中 iris_data pd.read_csv(data/iris.txt,sep\t)# 使用groupby方法按照&quo…

人机交互中信息数量与质量

在人机交互中,信息的数量和质量都是非常重要的因素。 信息的数量指的是交互过程中传递的信息的多少。信息的数量直接影响到交互的效率和效果,如果交互中传递的信息量太少,可能导致交互过程中的信息不足,用户无法得到想要的结果或者…

三菱人机交互GT Designer的使用(二,开关,指示灯,数值显示,数值输入)

今天也开始每日一学,内容为开关,指示灯,数值显示,数值输入,以为这篇文章比较长,所有小编决分为3篇内容写完,谢谢大家阅读,不足之处,欢迎指正。 目录 开关 位&#xff0c…

【UE5蓝图】读取本地json文件修改窗口大小

效果 插件 蓝图 1.判断文件存在 2.1文件不存在,生成文件 {"ResolutionX":540, "ResolutionY":960} 2.2文件存在,直接读取 3.设置窗口大小 遇到的坑 1.分辨率太大,导致效果不理想,建议先往小填写。 2.选对…

JSON 详解

文章目录 JSON 的由来JSON 的基本语法JSON 的序列化简单使用stringify 方法之 replacerstringify 方法之 replacer 参数传入回调函数stringify 方法之 spacestringify 方法之 toJSONparse 方法之 reviver 利用 stringify 和 parse 实现深拷贝 json 相信大家一定耳熟能详&#x…

React Hooks 面试题 | 08.精选React Hooks面试题

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

原生微信小程序如何动态配置主题颜色及如何调用子组件的方法

一、最终效果 二、步骤 1、在初始化进入项目时,获取当前主题色 2、把主题色定义成全局变量(即在app.js中设置) 3、tabBar也需要定义全局变量,在首页时需要重新赋值 三、具体实现 1、app.js onLaunch () {//获取主题数据this.set…

MySQL数据库导入100万数据不同方式的性能差异

本文将介绍MySQL数据库导入100万数据的三种方式性能比较。 三种方式分别为: (1)逐条INSERT (2)批量INSERT提交 (3)通过mysql自带的load data命令 应用场景:假设需要向100万个号码…

neo4j运维管理

管理数据库 概念 Neo4j 5(从v4.0),可以同时创建和使用多个活动数据库。 DBMS Neo4j是一个数据库管理系统(DBMS),能够管理多个数据库。DBMS可以管理一个独立的服务器,也可以管理集群中的一组服务器。 实例 Neo4j实例是运行Neo4j服务器代…

gitLab页面打tag操作步骤

作者:moical 链接:gitLab页面打tag简单使用 - 掘金 (juejin.cn) 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 ---------------------------------------------------------------------…

Linux lpr命令教程:如何使用lpr命令打印文件(附案例详解和注意事项)

Linux lpr命令介绍 lpr命令在Unix-like操作系统中用于提交打印任务。如果在命令行中指定了文件名,那么这些文件将被发送到指定的打印机(如果没有指定目的地,则发送到默认目的地)。如果命令行中没有列出文件,lpr将从标…

RK3568测试tdd

RK3568测试tdd 一、门禁取包二、烧录三、跑tdd用例四、查看结果参考资料 一、门禁取包 右键复制链接,粘贴下载;解压到文件夹; 二、烧录 双击\windows\RKDevTool.exe打开烧写工具,工具界面击烧写步骤如图所示: 推荐…

1229-方法引用(简化lambda)-stream流-单元测试-单例模式

方法引用stream流单元测试(junit)单例模式 方法引用 概念:对特殊的lambda简化的一种语法 使用时机:()-> {lambda体} 特殊的lambda:当lambda体只有1句代码,并且这句代码是在调用…

二叉树BFS

前置知识 二叉树节点的定义 二叉树是递归定义的 /*** Definition for a binary tree node.(LeetCode)*/public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode…

【java爬虫】获取个股详细数据并用echarts展示

前言 前面一篇文章介绍了获取个股数据的方法,本文将会对获取的接口进行一些优化,并且添加查询数据的接口,并且基于后端返回数据编写一个前端页面对数据进行展示。 具体的获取个股数据的接口可以看上一篇文章 【java爬虫】基于springbootjd…

Leetcode的AC指南 —— 双指针:18. 四数之和

摘要: Leetcode的AC指南 —— 双指针:18. 四数之和。题目介绍:给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (…

Android : 使用GestureOverlayView进行手势识别—简单应用

示例图: GestureOverlayView介绍: GestureOverlayView 是 Android 开发中用于识别和显示手势的视图组件。它允许用户在屏幕上绘制手势,并且应用程序可以检测和响应这些手势。以下是关于 GestureOverlayView 的主要特点: 手势识别…

Canal的学习

Canal 基本概念整合SpringBoot 基本概念 Canal是一个基于MySQL数据库增量日志解析,提供增量数据订阅和消费,支持将增量数据投递到下游消费者(如Kafka、RocketMQ等)或者存储(如 Elasticsearch、HBase 等)的…

nodejs+vue+微信小程序+python+PHP特困救助供养信息管理系统-计算机毕业设计推荐

通过走访某特困救助供养机构实际情况,整理特困救助供养机构管理的业务流程,分析当前特困救助供养机构管理存在的各种问题,利用软件开发思想对特困救助供养机构特困救助供养机构管理进行系统设计分析。通过服务端程序框架进行设计,…