OpenCV:图像直方图计算

b153934801fde1833a08eca77f3b97e0.jpeg

图像直方图为图像中像素强度的分布提供了有价值的见解。通过了解直方图,你可以获得有关图像对比度、亮度和整体色调分布的信息。这些知识对于图像增强、图像分割和特征提取等任务非常有用。

本文旨在为学习如何使用 OpenCV 执行图像直方图计算提供清晰且全面的指南。通过理解和应用直方图分析技术,你可以提高图像质量、执行阈值操作、分析颜色成分、提取有用的特征以及更有效地可视化和理解图像。

图像直方图

每个图像都由单独的像素组成,就像网格上的小点一样。假设我们有一个大小为 250 列和 100 行的图像,总共 2500 个像素。每个像素都可以有不同的颜色值,用 0 到 255 范围内的数字表示。

为了可视化图像中颜色值的分布,我们可以创建直方图。该直方图充当一组条形图,显示具有相同颜色值的像素数。通过比较条形的高度,我们可以轻松识别图像中哪些颜色值更突出或更频繁地出现。这种图形表示为图像的整体颜色组成和分布提供了宝贵的见解。

364b4a7ae167f57b3adeda7bd611df67.jpeg

图像直方图(单色)

现在记住,像素强度

0 → 黑色

255 → 白色

因此,如果我们的直方图向左移动(左偏),则图像会包含更多黑色像素;如果我们的直方图向右移动(右偏),图像会包含更多白色像素。

a2353b9b67b4a4b07a73f6f49827e6fc.jpeg

左偏和右偏直方图

所以我相信你已经完全理解了,

  • 更黑→更暗的图像

  • 更白→更亮的图像

0c3d5815073cc9e250b7aab3c4a126d7.jpeg

现在让我们在 OpenCV 中进行直方图计算。

首先,我们将加载图像并将其可视化。

#import necessary libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt#using opencv to read an image
#BGR Image
image = cv2.imread("C:/users/public/pictures/nature.jpg")#visualizing
cv2.namedWindow("BGR Image", cv2.WINDOW_NORMAL);
cv2.imshow("BGR Image",image);cv2.waitKey(0) & 0xFF 
cv2.destroyAllWindows()
e212df181a390649a75aec4219fdfb5c.jpeg

在绘制直方图之前,我们可以分离该图像中的颜色通道。

B = image[:,:,0] #blue layer
G = image[:,:,1] #green layer
R = image[:,:,2] #red layer

现在我们使用 OpenCV 函数 cv.calcHist() 计算并找到每一层的直方图,并使用 OpenCV 和 Matplotlib 函数绘制这些直方图

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

● images:uint8 或float32 类型的源图像。它应该放在方括号中,即“[img]”。

● channels:也在方括号中给出。它是我们计算直方图的通道的索引。例如,如果输入是灰度图像,则其值为[0]。对于彩色图像,可以通过[0]、[1]或[2]分别计算蓝色、绿色或红色通道的直方图。

● mask:蒙版图像。为了找到整个图像的直方图,它被指定为“None”。但是,如果你想找到图像特定区域的直方图,则必须为其创建一个蒙版图像并将其作为蒙版。

● histSize:BIN 计数。需要在方括号中给出。对于全尺寸,我们通过[256]。

● ranges:范围。通常是[0,256]。

B_histo = cv2.calcHist([image],[0], None, [256], [0,256])
G_histo = cv2.calcHist([image],[1], None, [256], [0,256])
R_histo = cv2.calcHist([image],[2], None, [256], [0,256])

现在我们使用 matplotlib 将它们绘制在子图中。

e9261b5669957f3ebd95e324c03f54a0.jpeg

你可以在不同设置的图像上尝试此操作。

4e970f7c0b4c0e9fe614efe6207bfa47.jpeg
20e29018fa217a983364a3904bbb6022.jpeg

完整代码

#import necessary libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt#using opencv to read an image
#BGR Image
image = cv2.imread("C:/users/public/pictures/nature.jpg")#seperating colour channels
B = image[:,:,0] #blue layer
G = image[:,:,1] #green layer
R = image[:,:,2] #red layer#calculating histograms for each channel
B_histo = cv2.calcHist([image],[0], None, [256], [0,256])
G_histo = cv2.calcHist([image],[1], None, [256], [0,256])
R_histo = cv2.calcHist([image],[2], None, [256], [0,256])#visualizing histograms
plt.subplot(2, 2, 1)
plt.plot(B_histo, 'b')
plt.subplot(2, 2, 2)
plt.plot(G_histo, 'g')
plt.subplot(2, 2, 3)
plt.plot(R_histo, 'r')#visualizing image
cv2.namedWindow("BGR Image", cv2.WINDOW_NORMAL);
cv2.imshow("BGR Image",image);
cv2.waitKey(0) & 0xFF 
cv2.destroyAllWindows()

曝光过度和曝光不足的图像

然后我们可以扩展这个想法来识别曝光过度(太亮)的图像和曝光不足(太暗)的图像。

b86b040451e1b3e7909fb46b0175dd09.jpeg

让我们看看这些图像的直方图。

f587701d1d47cc98a94c0f16f8cd7097.jpeg

使用 Matplotib 和 OpenCV 绘制直方图

显然,一个直方图左偏,表示图像曝光不足,而另一直方图右偏,表示图像曝光过度。

在这里,我们只需查看直方图就可以清楚地了解图像是否曝光不足或曝光过度。

直方图均衡

考虑曝光不足或曝光过度的图像,其像素值仅局限于某个特定的值范围。

例如:较亮的图像将所有像素限制为高值。

但是一个好的图像将具有来自图像的所有区域的像素。所以你需要将这个直方图拉伸到两端。这通常会提高图像的对比度。

当对彩色图像执行直方图均衡时,我们通常将该过程分别应用于图像中RGB颜色值的红色、绿色和蓝色分量。

首先,我们读取图像并将图像分成三个颜色层。

import cv2
import numpy as np
import matplotlib.pyplot as plt#using opencv to read an image
#BGR Image
image = cv2.imread("C:/users/public/pictures/underexposed_image.jpg")#seperating colour channels
B = image[:,:,0] #blue layer
G = image[:,:,1] #green layer
R = image[:,:,2] #red layer

然后我们使用 cv.equalizeHist () 来均衡每个颜色层的直方图。使用 Matplotlib 和 OpenCV 将它们可视化。

b_equi = cv2.equalizeHist(B)
g_equi = cv2.equalizeHist(G)
r_equi = cv2.equalizeHist(R)plt.imshow(b_equi)
plt.title("b_equi")
plt.show()
plt.imshow(g_equi)
plt.title("g_equi")
plt.show()
plt.imshow(r_equi)
plt.title("r_equi")
plt.show()
45aac29ecd5ae5819268e61fdb51b592.jpeg

使用 OpenCV 均衡 R、G 和 B 层

通过均衡的颜色层,我们使用 cv.calcHist() 计算每种颜色的直方图。然后将它们全部绘制出来。

B_histo = cv2.calcHist([b_equi],[0], None, [256], [0,256]) 
G_histo = cv2.calcHist([g_equi],[0], None, [256], [0,256])
R_histo = cv2.calcHist([r_equi],[0], None, [256], [0,256])plt.subplot(2, 2, 1)
plt.plot(G_histo, 'g')
plt.subplot(2, 2, 2)
plt.plot(R_histo, 'r')
plt.subplot(2, 2, 3)
plt.plot(B_histo, 'b')

你一定已经注意到,我们在“channels”位置仅使用了 [0]。在前面的例子中,我们使用了所有[0]、[1]和[2]。这是由于分离通道的可用性。因此只有 1 个通道。因此,对于所有直方图,“channels”为 [0]

或者,你可以获取原始图像中每个通道的直方图,并使用均衡后的颜色层绘制它们。

#calculate histograms for each channel seperately
#Equilized channels
B_histo = cv2.calcHist([b_equi],[0], None, [256], [0,256]) 
G_histo = cv2.calcHist([g_equi],[0], None, [256], [0,256])
R_histo = cv2.calcHist([r_equi],[0], None, [256], [0,256])
#Original channels
BO_histo = cv2.calcHist([image],[0], None, [256], [0,256]) 
GO_histo = cv2.calcHist([image],[1], None, [256], [0,256])
RO_histo = cv2.calcHist([image],[2], None, [256], [0,256])#visualize the channel histograms seperately
plt.figure(figsize=(10,12), )plt.subplot(3, 2, 1)
plt.title("Green Original")
plt.plot(GO_histo, 'g')plt.subplot(3, 2, 2)
plt.title("Green Equilized")
plt.plot(G_histo, 'g')plt.subplot(3, 2, 3)
plt.title("Red Original")
plt.plot(RO_histo, 'r')plt.subplot(3, 2, 4)
plt.title("Red Equilized")
plt.plot(R_histo, 'r')plt.subplot(3, 2, 5)
plt.title("Blue Original")
plt.plot(BO_histo, 'b')plt.subplot(3, 2, 6)
plt.title("Blue Equilized")
plt.plot(B_histo, 'b')
774c438574d3a46867d9cc7ef9d59230.jpeg
s

原始图像颜色直方图与均衡图像颜色直方图

继续下一步,我们现在拥有的只是层。为了从中获得图像,我们需要合并它们。

equi_im = cv2.merge([b_equi,g_equi,r_equi])

现在让我们并排查看均衡后的图像和原始图像。

cv2.namedWindow("Original Image", cv2.WINDOW_NORMAL);
cv2.imshow("Original Image",image);
cv2.namedWindow("New Image", cv2.WINDOW_NORMAL);
cv2.imshow("New Image",equi_im);cv2.waitKey(0) & 0xFF 
cv2.destroyAllWindows()
5802428c21667de49ea0f314ee3d9dd3.jpeg

使用 OpenCV 均衡图像

完整代码

import cv2
import numpy as np
import matplotlib.pyplot as plt#using opencv to read an image
#BGR Image
image = cv2.imread("C:/users/public/pictures/underexposed_image.jpg")#seperating colour channels
B = image[:,:,0] #blue layer
G = image[:,:,1] #green layer
R = image[:,:,2] #red layer#equilize each channel seperately
b_equi = cv2.equalizeHist(B)
g_equi = cv2.equalizeHist(G)
r_equi = cv2.equalizeHist(R)#calculate histograms for each channel seperately
B_histo = cv2.calcHist([b_equi],[0], None, [256], [0,256]) 
G_histo = cv2.calcHist([g_equi],[0], None, [256], [0,256])
R_histo = cv2.calcHist([r_equi],[0], None, [256], [0,256])#merge thechannels and create new image
equi_im = cv2.merge([b_equi,g_equi,r_equi])#visualize the equilized channels seperately
plt.imshow(b_equi)
plt.title("b_equi")
plt.show()
plt.imshow(g_equi)
plt.title("g_equi")
plt.show()
plt.imshow(r_equi)
plt.title("r_equi")
plt.show()#visualize the channel histograms seperately
plt.subplot(2, 2, 1)
plt.plot(G_histo, 'g')
plt.subplot(2, 2, 2)
plt.plot(R_histo, 'r')
plt.subplot(2, 2, 3)
plt.plot(B_histo, 'b')#visualize the original and equilized images
cv2.namedWindow("Original Image", cv2.WINDOW_NORMAL);
cv2.imshow("Original Image",image);
cv2.namedWindow("New Image", cv2.WINDOW_NORMAL);
cv2.imshow("New Image",equi_im);cv2.waitKey(0) & 0xFF 
cv2.destroyAllWindows()

感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/12824.shtml

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

相关文章

高清视频制作GIF怎么操作?一个工具在线完成视频转GIF

一段视频为了方便传输分享想要做成GIF动画的时候要怎么操作呢?很简单,只需要一款专业的GIF在线制作工具-GIF中文网,使用视频转GIF(https://www.gif.cn/)功能,上新MP4格式视频,能够快速制作1分钟…

Django学习笔记-视图(views)的使用

Django中可以使用views进行管理,类似于WPF的MVVM的ViewModel层,也相当于MVC架构的模Controller层。 一、基于函数的视图FBV(Function-Based View) 通过定义一个函数,包含HttpRequest对象作为参数,用来接受…

如何提高自己的软件测试水平之bug定位

同学们在面试投简历的时候会经常看到人家公司JD上写的要求之一,如下: 这句话大家不要以为随便写写的,在我工作的十几年过程中起码见过10个以上试用期没过的公司新人,公司在衡量一个测试工程师是否专业的标准之一就是:…

Linux下在终端输入密码隐藏方法

Linux系统中,如何将在终端输入密码时将密码隐藏? 最近做简单的登录界面时,不做任何操作的话,在终端输入密码的同时也会显示输入的密码是什么,这样对于隐蔽性和使用都有不好的体验。那么我就想到将密码用字符*隐藏起来…

freeswitch的mod_xml_curl模块

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 随着fs服务的增多,每一台fs都需要在后台单独配置,耗时耗力,心力憔悴。 如果有一个集中管理配置的配置中心,统一管理所有fs的配置,并可以实现动态的修改配置就…

mybatis日志工厂

前言: 如果一个数据库操作,出现异常,我们需要排错,日志就是最好的助手 官方给我们提供了logImpl:指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 默认工厂: 在配置文件里添加&#xf…

深度剖析APP开发中的UI/UX设计

作为一个 UI/UX设计师,除了要关注 UI/UX设计之外,还要掌握移动开发知识,同时在日常工作中也需要对用户体验有一定的认知,在本次分享中,笔者就针对自己在工作中积累的一些经验来进行一个总结,希望能够帮助到…

如何连接远程服务器?快解析内内网穿透可以吗?

如今我们迎来了数字化转型的时代,众多企业来为了更好地推动业务的发展,常常需要在公司内部搭建一个远程服务器。然而,对于企业员工来说,在工作过程中经常需要与这个服务器进行互动,而服务器位于公司的局域网中&#xf…

简述IO(BIO NIO IO多路复用)

在unix网络变成中的五种IO模型: Blocking IO(阻塞IO) NoneBlocking IO (非阻塞IO) IO mulitplexing(IO多路复用) signal driven IO (信号驱动IO) asynchronous IO (异步IO) BIO BIO(Blocking IO)是一种阻塞IO模型,也是传统的IO操作模型之一…

RocketMQ概论

目录 前言: 1.概述 2.下载安装、集群搭建 3.消息模型 4.如何保证吞吐量 4.1.消息存储 4.1.1顺序读写 4.1.2.异步刷盘 4.1.3.零拷贝 4.2.网络传输 前言: RocketMQ的代码示例在安装目录下有全套详细demo,所以本文不侧重于讲API这种死…

数据结构:快速的Redis有哪些慢操作?

redis 为什么要这莫快?一个就是他是基于内存的,另外一个就是他是他的数据结构 说到这儿,你肯定会说:“这个我知道,不就是 String(字符串)、List(列表)、 Hash&#xff08…

1.Ansible

文章目录 Ansible概念作用特性总结 部署AnsibleAnsible模块commandshellcronusergroupcopyfilehostnamepingyumserice/systemdscriptmountarchiveunarchivereplacesetup inventory主机清单主机变量组变量组嵌套 Ansible 概念 Ansible是一个基于Python开发的配置管理和应用部署…

数据结构:分块查找

分块查找,也叫索引顺序查找,算法实现除了需要查找表本身之外,还需要根据查找表建立一个索引表。例如图 1,给定一个查找表,其对应的索引表如图所示: 图 1 查找表及其对应的索引表 图 1 中,查找表…

安装Anaconda3和MiniConda3

MiniConda3官方版是一款优秀的Python环境管理软件。MiniConda3最新版只包含conda及其依赖项如果您更愿意拥有conda以及超过720个开源软件包,请安装Anaconda。MiniConda3官方版还是一个开源的软件包管理系统和环境管理系统,能够帮助用户安装多个版本的软件…

ChatGPT漫谈(三)

AIGC(AI Generated Content)指的是使用人工智能技术生成的内容,包括文字、图像、视频等多种形式。通过机器学习、深度学习等技术,AI系统可以学习和模仿人类的创作风格和思维模式,自动生成大量高质量的内容。AIGC被视为继用户生成内容(UGC)和专业生成内容(PGC)之后的下…

上传图片到腾讯云对象存储桶cos 【腾讯云对象存储桶】【cos】【el-upload】【vue3】【上传头像】【删除】

1、首先登录腾讯云官网控制台 进入对象存储页面 2、找到跨越访问CIRS设置 配置规则 点击添加规则 填写信息 3、书写代码 这里用VUE3书写 第一种用按钮出发事件形式 <template><div><input type="file" @change="handleFileChange" /&…

数值线性代数:奇异值分解SVD

本文记录计算矩阵奇异值分解SVD的原理与流程。 注1&#xff1a;限于研究水平&#xff0c;分析难免不当&#xff0c;欢迎批评指正。 零、预修 0.1 矩阵的奇异值 设列满秩矩阵&#xff0c;若的特征值为&#xff0c;则称为矩阵的奇异值。 0.2 SVD(分解)定理 设&#xff0c;则…

神经网络简单介绍

人工神经网络(artififial neural network) 简称神经网络&#xff0c;它是一种模仿生物神经网络结构和功能的非线性数学模型。 神经网络通过输入层接受原始特征信息&#xff0c;再通过隐藏层进行特征信息的加工和提取&#xff0c;最后通过输出层输出结果。 根据需要神经网络可以…

RTPSv2.2(中文版)

实时发布订阅协议 &#xff08;RTPS&#xff09; DDS互操作性 有线协议规范 V2.2 &#xff08;2014-09-01正式发布&#xff09; https://www.omg.org/spec/DDSI-RTPS/2.2/PDF 目 录 1 范围Scope 9 2 一致性Conformance 9 3 参考文献References 9 4 术语和定义Terms a…

centos(linux)手动配置ip地址

查看系统 查看ip 进入网卡配置的目录 [root178-119-30-16 ~]# cd /etc/sysconfig/network-scripts/ [root178-119-30-16 network-scripts]# ls ifcfg-ens192 ifdown ifdown-ippp ifdown-post ifdown-sit ifdown-tunnel ifup-bnep ifup-ipv6 ifup-plus…