当前位置: 首页 > news >正文

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

感谢阅读!

相关文章:

OpenCV:图像直方图计算

图像直方图为图像中像素强度的分布提供了有价值的见解。通过了解直方图,你可以获得有关图像对比度、亮度和整体色调分布的信息。这些知识对于图像增强、图像分割和特征提取等任务非常有用。 本文旨在为学习如何使用 OpenCV 执行图像直方图计算提供清晰且全面的指南。…...

用QFramework来重构 祖玛游戏

资料 Unity - 祖玛游戏 GitHub 说明 用QF一个场景就够了,在UIRoot下切换预制体达到面板切换。 但测试中当然要有一个直接跳到测试面板的 测试脚本,保留测试Scene(不然初学者也不知道怎么恢复测试Scene),所以全文按S…...

生活杂记-显示器尺寸

以下是常见显示器尺寸的对角线长度换算成厘米的结果(已经四舍五入到最接近的厘米数): 19英寸显示器 ≈ 48.26厘米21.5英寸显示器 ≈ 54.61厘米24英寸显示器 ≈ 60.96厘米27英寸显示器 ≈ 68.58厘米32英寸显示器 ≈ 81.28厘米34英寸显示器 ≈…...

在CSDN学Golang云原生(Kubernetes Pod无状态部署)

一,静态pod Kubernetes中的Pod是可以动态创建、销毁的,如果希望Pod只使用静态的IP地址而不是自动生成一个IP地址,那么就需要使用静态Pod。 静态Pod是在kubelet启动时通过指定文件夹路径来加载的。当kubelet检测到这些配置文件变化后&#x…...

@Bean的作用

Bean通常和Configuration注解一起使用 Bean可以用在方法上,方法返回的对象交给spring容器管理,和提供给其他程序组件使用 Bean是一个注解,用于将方法标记为Spring容器中的一个Bean。具体来说,Bean注解可以用于方法上&#xff0c…...

【论文阅读22】Label prompt for multi-label text classification

论文相关 论文标题:Label prompt for multi-label text classification(基于提示学习的多标签文本分类) 发表时间:2023 领域:多标签文本分类 发表期刊:Applied Intelligence(SCI二区&#xff0…...

EasyExcel数据导出功能封装

起因: 最近需要用到excel导出功能,使用EasyExcel可以快速实现导出,又需要优雅的对EasyExcel进行封装,在实现自己的导出功能时又可以制定一定的规则,让其他同事方便使用,最近研究了下网上的常规写法,站在巨人的肩上重新添加了自己的思路,供大家参考,有任何问题请多指教…...

通过web.xml来配置servlet程序

IDEA 2022.3.3 tomcat-9.0.27 Java EE8 JDK-16 配置访问的虚拟路径 web.xml <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3.org/2001/XMLSchema-insta…...

umi 创建的项目中,如何配置多个环境变量

创建env.js 在config.js中配置 在页面中使用 env.js和config.js的目录顺序 package.json中的配置...

Mysql 5.7 连接数爆满 清理连接数

Mysql 5.7 连接数爆满 清理连接数 我在做项目的时候遇到了这个报错&#xff0c;然后搜了半天也没有在网上找到mysql清理连接数的方案&#xff0c;后面还是自己写了一个 打开MySQL命令行或客户端&#xff0c;并使用管理员权限登录到MySQL服务器。 我这里使用的是navicat 输入…...

HTTPS工作原理

先简述一下什么是HTTPS&#xff0c;HTTPS就是在HTTP的基础上增加了SSL/TLS来完成加密传输&#xff0c;以免敏感信息被第三方获取&#xff0c;所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。 一、客户端发起HTTPS请求 这个没什么好说的&#xff0c;就是…...

十大基础算法

一、选择排序 过程简单描述&#xff1a; 首先&#xff0c;找到数组中最小的那个元素&#xff0c;其次&#xff0c;将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。其次&#xff0c;在剩下的元素中找到最小的元素&#xff0c;将它与数组的第二…...

Java---第八章(字符串-----String,StringBuilder 和 StringBuffer)

Java---第八章 字符串String字符串的常用方法StringBuilder和StringBuffer常用方法 对比String 和StringBuilder 和 StringBuffer 字符串 String 特性&#xff1a; String 类位于java.lang包中&#xff0c;无需引入&#xff0c;可直接使用String 类是由final修饰的&#xff…...

k8s集群的部署

【1】安装docker systemctl enable docker所有节点均需要安装docker,并且使其开机自启&#xff0c;每个节点均部署镜像加速器 【2】配置k8s的yum文件 [rootk8s1 ~]# cd /etc/yum.repos.d/ [rootk8s1 yum.repos.d]# vim k8s.repo [rootk8s1 yum.repos.d]# cat k8s.repo [k8s…...

设计模式——观察者模式

文章目录 1 概述2 实现3 总结 1 概述 观察者模式可以分为观察者和被观察者&#xff0c;观察者通过注册到一个被观察者中&#xff0c;也可视为订阅&#xff0c;当被观察者的数据发生改变时&#xff0c;会通知到观察者&#xff0c;观察者可以据此做出反应。 可以类比订阅报纸&am…...

在Debian 12 上安装 PHP 5.6, 7.4

环境&#xff1a;Debian 12 Debian 12 默认的PHP版本为 8.2 如果直接安装php7.4就出现下面的报错&#xff1a; sudo apt-get install libapache2-mod-php7.4 php7.4 php7.4-gd php7.4-opcache php7.4-mbstring php7.4-xml php7.4-json php7.4-zip php7.4-curl php7.4-imap p…...

微服务——统一网关Getway

为什么需要网关&#xff1f; 网关的两种实现: 网关Getway——快速入门 步骤一 网关背身也是一个微服务&#xff0c;需要注册到nacos中去 步骤二 成功运行后 可以通过网关进行请求转发到对应服务。 流程如下&#xff1a; 路由断言工厂 网关路由可以配置的东西有如下。 spri…...

[ELK安装篇]:基于Docker虚拟容器化(主要LogStash)

文章目录 一&#xff1a;前置准备-(参考之前博客)&#xff1a;1.1&#xff1a;准备Elasticsearch和Kibana环境&#xff1a;1.1.1&#xff1a;地址&#xff1a;https://blog.csdn.net/Abraxs/article/details/128517777 二&#xff1a;Docker安装LogStash(数据收集引擎&#xff…...

纪录片《打铁文艺社》:从全美高中生电影节到多项国际赞誉,聚焦城市公共艺术的蜕变之路

7月21日&#xff0c;在全美高中生电影节&#xff08;All American High School Film Festival&#xff0c;AAHSFF&#xff09;公布的入围名单中&#xff0c;一部取材于中国深圳的纪录片《打铁文艺社Datie: The Art Tribe of Tiegang》以其深刻的主题和精良的制作&#xff0c;引…...

VLAN---虚拟局域网

VLAN— 虚拟局域网 LAN—局域网 MAN—城域网 WAN—广域网 1.一个VLAN相当于是一个广播域 VLAN—通过路由器和交换机协同工作后&#xff0c;将原本的一个广播域逻辑上&#xff0c;拆 分为多个虚拟的广播域。 VLAN配置&#xff1a; 1.创建VLAN VID—VLAN ID------用来区分和…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...