OpenCV官方教程中文版 —— 直方图均衡化

OpenCV官方教程中文版 —— 直方图均衡化

  • 前言
  • 一、原理
  • 二、 OpenCV 中的直方图均衡化
  • 三、 CLAHE 有限对比适应性直方图均衡化

前言

本小节我们要学习直方图均衡化的概念,以及如何使用它来改善图片的对比。

一、原理

想象一下如果一副图像中的大多是像素点的像素值都集中在一个像素值范围之内会怎样呢?例如,如果一幅图片整体很亮,那所有的像素值应该都会很高。但是一副高质量的图像的像素值分布应该很广泛。所以你应该把它的直方图做一个横向拉伸(如下图),这就是直方图均衡化要做的事情。通常情况下这种操作会改善图像的对比度。

在这里插入图片描述

推荐你去读读维基百科中关于直方图均衡化的条目。其中的解释非常给力,读完之后相信你就会对整个过程有一个详细的了解了。我们先看看怎样使用Numpy 来进行直方图均衡化,然后再学习使用 OpenCV 进行直方图均衡化。

# -*- coding: utf-8 -*-
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('wiki.png', 0)
# flatten() 将数组变成一维
hist, bins = np.histogram(img.flatten(), 256, [0, 256])
# 计算累积分布图
plt.figure()
plt.subplot(1,2,1)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis
plt.tight_layout()
plt.subplot(1,2,2)
cdf = hist.cumsum()
cdf_normalized = cdf * 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.tight_layout()
plt.show()

在这里插入图片描述
我们可以看出来直方图大部分在灰度值较高的部分,而且分布很集中。而我们希望直方图的分布比较分散,能够涵盖整个 x 轴。所以,我们就需要一个变换函数帮助我们把现在的直方图映射到一个广泛分布的直方图中。这就是直方图均衡化要做的事情。

图均衡化要做的事情。我们现在要找到直方图中的最小值(除了 0),并把它用于 wiki 中的直方图均衡化公式。但是我在这里使用了 Numpy 的掩模数组。对于掩模数组的所有操作都只对 non-masked 元素有效。你可以到 Numpy 文档中获取更多掩模数组的信息。

# 构建 Numpy 掩模数组,cdf 为原数组,当数组元素为 0 时,掩盖(计算时被忽略)。
cdf_m = np.ma.masked_equal(cdf,0)
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
# 对被掩盖的元素赋值,这里赋值为 0
cdf = np.ma.filled(cdf_m,0).astype('uint8')

现在就获得了一个表,我们可以通过查表得知与输入像素对应的输出像素的值。我们只需要把这种变换应用到图像上就可以了。

img2 = cdf[img]

我们再根据前面的方法绘制直方图和累积分布图,结果如下:

在这里插入图片描述
另一个重要的特点是,即使我们的输入图片是一个比较暗的图片(不象上边我们用到到的整体都很亮的图片),在经过直方图均衡化之后也能得到相同的结果。因此,直方图均衡化经常用来使所有的图片具有相同的亮度条件的参考工具。这在很多情况下都很有用。例如,脸部识别,在训练分类器前,训练集的所有图片都要先进行直方图均衡化从而使它们达到相同的亮度条件。

二、 OpenCV 中的直方图均衡化

OpenCV 中的直方图均衡化函数为 cv2.equalizeHist()。这个函数的输入图片仅仅是一副灰度图像,输出结果是直方图均衡化之后的图像。

下边的代码还是对上边的那幅图像进行直方图均衡化:

# -*- coding: utf-8 -*-
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('wiki.png', 0)
equ = cv2.equalizeHist(img)
res = np.hstack((img, equ))

plt.figure()
plt.imshow(res, cmap='gray', interpolation='bicubic')
plt.xticks([]), plt.yticks([])  # to hide tick values on X and Y axis
plt.show()

在这里插入图片描述

现在你可以拿一些不同亮度的照片自己来试一下了。

当直方图中的数据集中在某一个灰度值范围内时,直方图均衡化很有用。但是如果像素的变化很大,而且占据的灰度范围非常广时,例如:既有很亮的像素点又有很暗的像素点时。

三、 CLAHE 有限对比适应性直方图均衡化

我们在上边做的直方图均衡化会改变整个图像的对比度,但是在很多情况下,这样做的效果并不好。例如,下图分别是输入图像和进行直方图均衡化之后的输出图像。

在这里插入图片描述

的确在进行完直方图均衡化之后,图片背景的对比度被改变了。但是你再对比一下两幅图像中雕像的面图,由于太亮我们丢失了很多信息。造成这种结果的根本原因在于这幅图像的直方图并不是集中在某一个区域(试着画出它的直方图,你就明白了)。

为了解决这个问题,我们需要使用自适应的直方图均衡化。这种情况下,整幅图像会被分成很多小块,这些小块被称为“tiles”(在 OpenCV 中 tiles 的大小默认是 8x8),然后再对每一个小块分别进行直方图均衡化(跟前面类似)。所以在每一个的区域中,直方图会集中在某一个小的区域中(除非有噪声干扰)。如果有噪声的话,噪声会被放大。为了避免这种情况的出现要使用对比度限制。对于每个小块来说,如果直方图中的 bin 超过对比度的上限的话,就把其中的像素点均匀分散到其他 bins 中,然后在进行直方图均衡化。最后,为了去除每一个小块之间“人造的”(由于算法造成)边界,再使用双线性差值,对小块进行缝合。

下面的代码显示了如何使用 OpenCV 中的 CLAHE。

# -*- coding: utf-8 -*-
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('tsukuba_l.png', 0)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
res = np.hstack((img, cl1))
plt.figure()
plt.imshow(res, cmap='gray', interpolation='bicubic')
plt.xticks([]), plt.yticks([])  # to hide tick values on X and Y axis
plt.show()

下面就是结果了,与前面的结果对比一下,尤其是雕像区域:
在这里插入图片描述

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

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

相关文章

哪些车企AEB标配率「不及格」

对于汽车智能化来说,基础安全不分高低配。但实际情况,却是另一番景象。 在全球范围,目前不少国家及地区的监管机构正在考虑将AEB(紧急制动系统)作为乘用车的标配纳入法规,“这是道路安全向前迈出了重要的一…

2023全新TwoNav开源网址导航系统源码 | 去授权版

2023全新TwoNav开源网址导航系统源码 已过授权 所有功能可用 测试环境:NginxPHP7.4MySQL5.6 一款开源的书签导航管理程序,界面简洁,安装简单,使用方便,基础功能免费。 TwoNav可帮助你将浏览器书签集中式管理&#x…

C++中显示构造和隐式构造

截图来源于C primerplus 第六版。

行情分析——加密货币市场大盘走势(10.25)

目前大饼继续上涨,还没有看到震荡盘整的迹象。从MACD日线来看,连续绿色实心柱已经10天。现在有点上涨无力了,而现在入场做空性价比更高,看反弹到33000-32000。如果谨慎点,可以继续等待。 以太目前来看和大饼一样那个也…

Ubuntu OpenLDAP配置笔记

Ubuntu OpenLDAP配置笔记 问题(需求)LDAP服务端安装slapd和ldap-utils配置域名编辑hosts修改主机名验证增加一个域账号修改用户的密码 Linux桌面加域安装软件验证允许远程账号首次登录时自动创建HOME目录桌面登录 其它问题Ubuntu更新和安装太慢LDAP服务端…

深入了解JavaScript中的AJAX和HTTP请求

在现代Web开发中,AJAX(Asynchronous JavaScript and XML)和HTTP请求被广泛应用于实现动态交互式网页。本文将深入探讨AJAX的概念、工作原理以及使用方法。 什么是AJAX? AJAX是一种利用JavaScript和HTTP请求与服务器进行异步通信的…

Banana Pi BPI-W3(Armsom W3)RK3588开当板之调试UART

前言 本文主要讲解如何关于RK3588开发板UART的使用和调试方法,包括UART作为普通串口和控制台两种不同使用场景 一. 功能特点 Rockchip UART (Universal Asynchronous Receiver/Transmitter) 基于16550A串口标准,完整模块支持以下功能: 支…

从零开始做一个SDWAN

VPN和SD-WAN的区别 VPN(Virtual Private Network)和SD-WAN(Software-Defined Wide Area Network)是两种不同的网络技术,它们在目的、功能和实施方式上有一些重要的区别。 目的和应用场景: VPN:VPN主要用于…

什么是有效种草!900万播放成B站“网红品牌”

- 导语 众所周知,B站早期是二次元小众社区,所以ACG(动画、漫画、游戏三者的合称)内容一直是B站的核心品类,B站经过多品类内容的摸索和发展,一直到现在成为年轻一代聚集的多元化社区,但ACG内容仍…

AI智能监控平台EasyCVR+无人机方案:实时全景无死角全方面助力山区安防系统新升级

无人机作为高速发展的高科技设备,技术日趋成熟,目前已经被广泛应用于农业、森林防护、医疗、交通物流等等场景。但随着城市化进程的加快,人类对自然环境日益严重的破坏,近十几年来,森林火灾的发生频率和失火严重程度一…

Zabbix出现 404Not FoundThe requested URL /zabbix was not found on this server.

目录 一、问题: 二、原因: 三、解决方法: 一、问题: Not Found The requested URL /zabbix was not found on this server. 二、原因: 未找到 在此服务器上找不到请求的 URL /zabbix。 /etc/httpd/conf.d 目录…

【uniapp】小程序开发7:自定义组件、自动注册组件

一、自定义轮播图组件、自动注册 以首页轮播图组件为例。 1、创建组件文件src/components/my-swipper.vue 代码如下&#xff1a; <template><view><view class"uni-margin-wrap"><swiper class"swiper" circular :indicator-dots…

22 行为型模式-状态模式

1 状态模式介绍 2 状态模式结构 3 状态模式实现 代码示例 //抽象状态接口 public interface State {//声明抽象方法,不同具体状态类可以有不同实现void handle(Context context); }

Golang 数据库操作

文章目录 初始化连接连接池SetMaxOpenConnsSetMaxIdleConnsSetConnMaxIdleTimeSetConnMaxLifetime 查询数据插入数据更新数据删除数据实现账号密码登录功能sqlx的部分用法 首先安装包&#xff1a;Install go get -u github.com/go-sql-driver/mysql // MySQL数据库的包 go get…

单片机中的 _nop_() 延时以及其相关的基础扩展

使用 _nop_() 函数做延时遇到的一些问题 以及对此延伸出的一些需要了解的基本概念 ...... by 矜辰所致 完善文章内容结构&#xff0c;补充指令周期、机器周期等一些基本概念 2023/10/25前言 最近还是继续做着项目&#xff0c;因为在某 8051 内核芯片上使用到了 I…

【MySQL】用户与权限管理

文章目录 一、用户管理1、用户信息表2、创建用户3、删除用户4、修改用户密码 二、权限管理1、MySQL 权限2、给用户授权3、回收用户权限 一、用户管理 之前为了方便&#xff0c;我们学习 MySQL 时统一使用的都是 root 账号进行登录&#xff0c;但在实际的开发场景中必然是需要进…

opencalib中lidar2camera安装记录

目录 一、opencalib安装 二、lidar2camera的安装 三、测试运行 四、出现过的问题 一、opencalib安装 代码地址&#xff1a;https://github.com/PJLab-ADG/SensorsCalibration/blob/master/README.md # pull docker image sudo docker pull scllovewkf/opencalib:v1 # Aft…

RISC-V架构——中断委托和中断注入

1、中断委托 1.1、中断委托的作用 &#xff08;1&#xff09;默认情况下&#xff0c;所有的陷入&#xff08;中断和异常&#xff09;都是在M模式下处理&#xff0c;然后再返回到发生陷入前的模式&#xff1b; &#xff08;2&#xff09;所有陷入都在M模式处理会涉及到模式切换…

1个月5次发版:测试人的模块测试策略分类归纳

笔者所在项目经历了一个月开发周期&#xff0c;该项目有5名开发人员&#xff0c;1名项目经理&#xff0c;1名测试人员&#xff0c;涵盖OA系统8个模块&#xff0c;在短短1个月中进行了5次发布。 现进行模块测试策略分类归纳。 已有模块 配置项优化 对于已有模块的配置项优化&…

【JavaEE】线程安全的集合类 -- 多线程篇(9)

线程安全的集合类 多线程环境使用 ArrayList多线程环境使用队列多线程环境使用哈希表 多线程环境使用 ArrayList 自己使用同步机制 (synchronized 或者 ReentrantLock)Collections.synchronizedList(new ArrayList); synchronizedList 是标准库提供的一个基于 synchronized 进…