【OpenCV】直方图

理论

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

这只是理解图像的另一种方式。通过查看图像的直方图,您可以直观地了解该图像的对比度,亮度,强度分布等。当今几乎所有图像处理工具都提供直方图功能。

histogram_sample.jpg

可以看到图像及其直方图。(请记住,此直方图是针对灰度图像而非彩色图像绘制的)。直方图的左侧区域显示图像中较暗像素的数量,而右侧区域则显示较亮像素的数量。从直方图中,您可以看到暗区域多于亮区域,中间值的数量(中间值的像素值,例如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。

范围 :这是您要测量的强度值的范围。通常,它是[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.99、1-1.99、2-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()

如下图:

histogram_matplotlib.jpg

或者,可以使用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()

结果:

histogram_rgb_plot.jpg

蓝色在图像中具有一些高值区域(显然这应该是由于天空)

2.使用OpenCV

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

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

histogram_masking.jpg

直方图均衡

我们将学习直方图均衡化的概念,并将其用于改善图像的对比度。 理论 考虑一个图像,其像素值仅限于特定的值范围。例如,较亮的图像会将所有像素限制在较高的值。但是,好的图像将具有来自图像所有区域的像素。因此,您需要将此直方图拉伸到两端(如下图所示,来自维基百科),这就是直方图均衡化的作用(简单来说)。通常,这可以提高图像的对比度。

histogram_equalization.png

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('wiki.jpg',0)
hist,bins = np.histogram(img.flatten(),256,[0,256])
cdf = hist.cumsum()
cdf_normalized = cdf * float(hist.max()) / cdf.max()
plt.plot(cdf_normalized, color = 'b')
plt.hist(img.flatten(),256,[0,256], color = 'r')
plt.xlim([0,256])
plt.legend(('cdf','histogram'), loc = 'upper left')
plt.show()

histeq_numpy1.jpg

您可以看到直方图位于较亮的区域。我们需要全方位的服务。为此,我们需要一个转换函数,该函数将较亮区域中的输入像素映射到整个区域中的输出像素。这就是直方图均衡化的作用。

现在,我们找到最小的直方图值(不包括0)并应用Wiki页面中给出的直方图均衡方程。但是我在这里使用了Numpy的masked array概念数组。对于掩码数组,所有操作都在非掩码元素上执行。您可以从有关屏蔽数组的Numpy文档中了解有关此内容的更多信息。

cdf_m = np.ma.masked_equal(cdf,0)
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
cdf = np.ma.filled(cdf_m,0).astype('uint8')

现在我们有了查找表,该表为我们提供了有关每个输入像素值的输出像素值是什么的信息。因此,我们仅应用变换。

img2 = cdf[img]

现在我们像以前一样计算它的直方图和cdf(您这样做),结果如下所示:

histeq_numpy2.jpg

另一个重要特征是,即使图像是较暗的图像(而不是我们使用的较亮的图像),在均衡后,我们将获得与获得的图像几乎相同的图像。结果,它被用作“参考工具”,以使所有图像具有相同的照明条件。在许多情况下这很有用。例如,在人脸识别中,在训练人脸数据之前,将人脸图像进行直方图均衡,以使它们全部具有相同的光照条件。

OpenCV中的直方图均衡

OpenCV具有执行此操作的功能 cv.equalizeHist() 。它的输入只是灰度图像,输出是我们的直方图均衡图像。

下面是一个简单的代码片段,显示了它与我们使用的同一图像的用法:

img = cv.imread('wiki.jpg',0)
equ = cv.equalizeHist(img)
res = np.hstack((img,equ)) #stacking images side-by-side
cv.imwrite('res.png',res)

equalization_opencv.jpg

因此,现在您可以在不同的光照条件下拍摄不同的图像,对其进行均衡并检查结果。

当图像的直方图限制在特定区域时,直方图均衡化效果很好。在直方图覆盖较大区域(即同时存在亮像素和暗像素)的强度变化较大的地方,效果不好。

CLAHE(对比度受限的自适应直方图均衡)

我们刚刚看到的第一个直方图均衡化考虑了图像的整体对比度。在许多情况下,这不是一个好主意。例如,下图显示了输入图像及其在全局直方图均衡后的结果。

clahe_1.jpg

直方图均衡后,背景对比度确实得到了改善。但是在两个图像中比较雕像的脸。由于亮度过高,我们在那里丢失了大多数信息。这是因为它的直方图不像我们在前面的案例中所看到的那样局限于特定区域(尝试绘制输入图像的直方图,您将获得更多的直觉)。

因此,为了解决这个问题,使用了 自适应直方图均衡 。在这种情况下,图像被分成称为“ tiles”的小块(在OpenCV中,tileSize默认为8x8)。然后,像往常一样对这些块中的每一个进行直方图均衡。因此,在较小的区域中,直方图将局限于一个较小的区域(除非有噪声)。如果有噪音,它将被放大。为了避免这种情况,应用了 对比度限制 。如果任何直方图bin超过指定的对比度限制(在OpenCV中默认为40),则在应用直方图均衡之前,将这些像素裁剪并均匀地分布到其他bin。均衡后,要消除图块边界中的伪影,请应用双线性插值。

下面的代码片段显示了如何在OpenCV中应用CLAHE:

import numpy as np
import cv2 as cv
img = cv.imread('tsukuba_l.png',0)
# create a CLAHE object (Arguments are optional).
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
cv.imwrite('clahe_2.jpg',cl1)

查看下面的结果,并将其与上面的结果进行比较,尤其是雕像区域:

clahe_2.jpg

apachecn.github.io/opencv-doc-zh/#/

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MoeCTF2024-Web题解

目录 1、弗拉格之地的入口 2、垫刀之路01: MoeCTF?启动! 3、ez_http 4、ProveYourLove 5、弗拉格之地的挑战 6、ImageCloud前置 7、垫刀之路02: 普通的文件上传 8、垫刀之路03: 这是一个图床 9、垫刀之路05: 登陆网站 10、垫刀之路06: pop bas…

python学opencv|读取图像(六)读取图像像素RGB值

【1】引言 前序已经掌握了如何获取灰度图像的像素,文章链接为: python学opencv|读取图像(五)读取灰度图像像素-CSDN博客 实际上像素就像一个坐标轴,约束了图像的大小。 但实际上我们在学习过程中,对于同…

ThingsBoard规则链节点:RabbitMQ 节点详解

ThingsBoard 是一个开源的物联网平台,允许开发者快速构建IoT产品。它提供了设备连接、数据收集、处理和可视化等功能。为了实现高效的数据处理和消息传递,ThingsBoard 集成了多种消息队列服务,其中就包括了RabbitMQ。 RabbitMQ 是一个广泛使用…

如何创建基于udp的客户端和服务端

1.先创建好udpServer.hpp、udpServer.cc、udpClient.hpp、udpClient.cc的框架。 #pragma once #include <string> #include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <cerrno> #include…

TCP 2

文章目录 Tcp状态三次握手四次挥手理解TIME WAIT状态 如上就是TCP连接管理部分 流量控制滑动窗口快重传 延迟应答原理 捎带应答总结TCP拥塞控制拥塞控制的策略 -- 每台识别主机拥塞的机器都要做 面向字节流和粘包问题tcp连接异常进程终止机器重启机器掉电/网线断开 Tcp状态 建…

ChatGPT Pro是什么

ChatGPT Pro 和 ChatGPT Plus 的区别主要体现在功能范围、适用场景和目标用户上。 ChatGPT Plus 功能 • 价格&#xff1a;20美元/月。 • 目标用户&#xff1a;针对个人用户设计。 • 主要特点&#xff1a; • 在高峰期响应速度更快。 • 使用高级模型&#xff08;如 GPT-4…

【开源免费】基于Vue和SpringBoot的桂林旅游景点导游平台(附论文)

博主说明&#xff1a;本文项目编号 T 079 &#xff0c;文末自助获取源码 \color{red}{T079&#xff0c;文末自助获取源码} T079&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

C++ day3——C++核心

作业&#xff1a; 整理思维导图 2、整理课上代码 3、把课上类的三个练习题的构造函数写出来 1、定义一个矩形类Rec #include <iostream>using namespace std; class Rec {const int length;int width; public:Rec(int length,int width):length(length),width(width)…

目前Java后端就业前景到底怎么样?

很多人都说今年对于IT行业根本没有所谓的“金三银四”“金九银十”。在各大招聘网站或者软件上不管是大厂还是中小公司大多都是挂个招聘需求&#xff0c;实际并不招人&#xff1b;在行业内的程序员基本都已经感受到了任老前段时间口中所谓的“寒气”。 虽然事实确实是如此&…

倚光科技助力自由曲面设计与加工

近年来&#xff0c;自由曲面因其在光学、汽车、航空航天等领域的广泛应用&#xff0c;受到设计师和工程师的高度关注。自由曲面作为一种具有更高自由度的非球面透镜&#xff0c;能够在光学系统中实现更加精确的光线控制&#xff0c;优化像差校正&#xff0c;并且在满足功能需求…

算法论文/半监督1——2024最新半监督目标检测综述(CNN和Transformer)全文1.5W字

Semi-Supervised Object Detection: A Survey on Progress from CNN to Transformer 摘要 半监督学习的惊人进步促使研究人员探索其在计算机视觉领域内目标检测任务中的潜力。半监督对象检测 &#xff08;SSOD&#xff09; 利用小型标记数据集和较大的未标记数据集的组合。这…

在Windows 10中使用SSH远程连接服务器(附花生壳操作方法)

SSH 在 linux 中是一种重要的系统组件&#xff0c;用户可以使用 SSH 来远程连接 linux 系统的计算机&#xff0c;或者传输文件。不过在 win10 以前&#xff0c;windows 并不原生支持 SSH&#xff0c;需要借助第三方工具来使用 SSH 功能。而实际上&#xff0c;微软在 2015 年就曾…

自动秒收录程序与自动秒收录网站源码论坛版本下载

自动秒收录程序与自动秒收录网站源码论坛版本下载 随着互联网的快速发展&#xff0c;网站优化已成为众多企业和个人博主提升在线影响力的关键手段。其中&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;作为提升网站排名的核心策略&#xff0c;备受关注。而SEO优化的一个…

在Goland中对goroutine协程断点调试

在Goland中对goroutine协程断点调试 环境: Goland 参考了 chatgpt 的回复 进行断点调试的代码 package mainimport ("fmt""sync""time" )// worker 模拟处理任务 func worker(id int, wg *sync.WaitGroup) {defer wg.Done() // 确保任务完成后…

Sublime Text 64位:前端及全栈开发利器

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;Sublime Text作为一款高效的文本编辑器&#xff0c;在前端网页开发领域受到广泛青睐&#xff0c;特别是其64位版本在处理大型项目和高内存需求的场景下表现出色。编辑器内置Emmet插件&#xff0c;提供代码高亮、…

css矩形样式,两边圆形

废话不多说&#xff0c;代码如下&#xff0c;直接拷贝即可使用&#xff1a; index.vue文件 <template><view class"wrap"><view class"tabs"><view class"tab active"><view class"name">标签</view…

Spring Boot 3 中Bean的配置和实例化详解

一、引言 在Java企业级开发领域&#xff0c;Spring Boot凭借其简洁、快速、高效的特点&#xff0c;迅速成为了众多开发者的首选框架。Spring Boot通过自动配置、起步依赖等特性&#xff0c;极大地简化了Spring应用的搭建和开发过程。而在Spring Boot的众多核心特性中&#xff…

C# MVVM 牛牛的实现依赖注入和MVVM绑定(DependencyInjection+CommunityToolkit)

这段时间在网上发现搜索MVVM数据绑定时&#xff0c;发现很多都是最基本的数据绑定&#xff0c;完全没有考虑依赖注入的问题&#xff0c;这里实现一下我们的方法&#xff0c;让我们的数据绑定和依赖注入都变得简单起来。 安装资源包 首先我们要下载一下资源包DependencyInject…

最小二乘法拟合出二阶响应面近似模型

背景&#xff1a;根据样本试验数据拟合出二阶响应面近似模型&#xff08;正交二次型&#xff09;&#xff0c;并使用决定系数R和调整的决定系数R_adj来判断二阶响应面模型的拟合精度。 1、样本数据&#xff08;来源&#xff1a;硕士论文《航空发动机用W形金属密封环密封性能分析…

05-标准库开发-STM32-IIC协议

七、STM32中IIC协议 概述 Inter-Integrated Circuit (IIC)&#xff0c;也常称为I2C&#xff08;I squared C&#xff09;&#xff0c;是一种同步、串行、半双工通信总线协议。它主要用于连接低速外围设备到处理器或微控制器上&#xff0c;如MPU6050姿态传感器、OLED显示屏、存…