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

news2024/9/23 19:21:39

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

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

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

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

相关文章

竞赛 深度学习卫星遥感图像检测与识别 -opencv python 目标检测

文章目录 0 前言1 课题背景2 实现效果3 Yolov5算法4 数据处理和训练5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **深度学习卫星遥感图像检测与识别 ** 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐…

如何处理单据保存/审核时提示:“更新即时库存时,基本单位数量与辅单位数量为一正一负,即时库存更新不成功

文章目录 如何处理单据保存/审核时提示:“更新即时库存时,基本单位数量与辅单位数量为一正一负,即时库存更新不成功问题描述前提问题分析:解决方案 如何处理单据保存/审核时提示:“更新即时库存时,基本单位数量与辅单位数量为一正一负,即时库存更新不成功 问题描述…

模拟输入信号保护方法,确保数据准确性和系统稳定性

在各种电子系统中,模拟输入信号的处理和保护至关重要。 这些信号可能会受到各种干扰和噪声的影响,从而影响数据的准确性和系统的稳定性。为了应对这些问题,本文将介绍一些模拟输入信号的保护方法。 今天分享几种模拟输入信号保护电路的方法…

npm改变npm缓存路径和改变环境变量

在安装nodejs时,系统会自动安装在系统盘C, 时间久了经常会遇到C盘爆满,有时候出现红色,此时才发现很多时候是因为npm 缓存保存在C盘导致的,下面就介绍下如何改变npm缓存路径。 1、首先找到安装nodejs的路径&#xff0c…

Elasticsearch:使用 Open AI 和 Langchain 的 RAG - Retrieval Augmented Generation (一)

最近看了一个同事的几个视频。他总结的很好。在使用 LangChain 时,根据 LangChain 的官方文档 https://integrations.langchain.com/vectorstores,目前有三种方法可以进行使用:ElasticVectorSearch,ElasticsearchStore 及 Elastic…

SpringCloudAlibaba实战-快速上手

写在前面:在学习了很多理论知识后,虽然对理论知识有了个概念,但是搭建项目的配置步骤做的少,还是不熟,方便日后复习,在此记录一下。 一、创建父项目 1. 创建项目基础信息 1. 选择项目基础信息 服务器UR…

【OpenCV实现图像的几何变换】

文章目录 概要:OpenCV实现图像的几何变换、图像阈值和平滑图像变换小结 概要:OpenCV实现图像的几何变换、图像阈值和平滑图像 使用OpenCV库进行图像处理的三个重要主题:几何变换、图像阈值处理以及图像平滑。在几何变换部分,详细…

第二章 基于模型的系统工程 P1|系统建模语言SysML实用指南学习

仅供个人学习记录 基于文档与基于模型的方法对比 MBSE潜在优势 增进沟通: 团队与利益相关方共享对系统的理解从系统多个维度展示和集成视图的能力 降低开发风险: 持续需求确认与设计验证对系统开发做精确成本估计 提高质量: 更多的完整、…

超级强大!送你几款Linux 下终极SSH客户端

更多IT技术,请关注微信公众号:“运维之美” 超级强大!送你几款Linux 下终极SSH客户端 1.MobaXterm2.Xshell3.SecureCRT4.PuTTY5.FinalShell6.Termius7.WindTerm 安全外壳协议(Secure Shell,简称 SSH)是一种网络连接协议…

服务器安装宝塔面板

参考官方文档 【教程贴】如何登录您的Linux云服务器并安装宝塔面板 - Linux面板 - 宝塔面板论坛 换言之: 下载 宝塔终端 使用ssh连接远程服务器 输入命令行安装 curl -sSO http://download.bt.cn/install/install_panel.sh && bash install_panel.sh 安…

在 Python 中将 Unicode 转换为 ASCII

通过本文,我们将学习如何将 Unicode 编码为字节,了解系统编码的不同方法以及在 Python 中将 Unicode 转换为 ASCII。 在 Python 中将 Unicode 转换为 ASCII Python 3 字符串的基本问题是由字符组成的; Python 中没有字符类型,但它…

数据清洗与规范化详解

数据处理流程,也称数据处理管道,是将原始数据转化为有意义的信息和知识的一系列操作步骤。它包括数据采集、清洗、转换、分析和可视化等环节,旨在提供有用的见解和决策支持。在数据可视化中数据处理是可视化展示前非常重要的一步,…

搭建SNMP服务器

要搭建SNMP服务器,您可以按照以下步骤进行操作: 选择合适的操作系统:您可以选择在Windows、Linux或其他操作系统上搭建SNMP服务器。不同的操作系统有不同的安装和配置方法。 安装SNMP软件:根据您选择的操作系统,安装相…

AIGC扫盲和应用场景探究

什么是AIGC? AIGC(Artificial Intelligence Generated Content)是指利用人工智能技术生成内容的能力。火爆的虚拟数字人,就是AIGC的典型代表,它可以通过学习大量数据和知识,生成与人类创作相似甚至超越人类…

UG\NX二次开发 同时设置多个对象的高亮状态 UF_DISP_set_highlights

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 感谢粉丝订阅 感谢 captainliubang 订阅本专栏,非常感谢。 简介 UG\NX二次开发 同时设置多个对象的高亮状态 UF_DISP_set_highlights 效果 代码(在for循环中逐个设置多个对象…

数据结构零基础C语言版 严蔚敏-线性表、顺序表

二、顺序表和链表 1. 线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...... 线性表在逻辑上是线性结构,…

【MySQL索引与优化篇】索引的数据结构

文章目录 1. 概述2. 常见索引结构2.1 聚簇索引2.2 二级索引(辅助索引、非聚簇索引)2.3 联合索引 3. InnoDB的B树索引的注意事项3.1 根页面位置万年不动3.2 内节点中目录项记录的唯一性 4. MyISAM中的索引方案5. InnoDB和MyISAM对比6. 小结7. 补充:MySQL数据结构的合…

有六家机器视觉公司今年11月份初放假到明年春节后,除夕不放假看住企业不跑路,不倒闭,明年大家日子会越来越甜

不幸的消息一个接着一个,请大家注意下面的消息 我已经收到已经有6家机器视觉公司今年11月份初放假到明年春节后,他们真的没有订单了,其中4家宣布员工可以自行寻找工作,今年除夕不放假是经济下行经济考量吗?看住企业不…

分布式:一文搞定Redis/Zookeeper/MySQL实现分布式锁

目录 一、项目准备spring项目数据库 二、传统锁演示超卖现象使用JVM锁解决超卖解决方案JVM失效场景 使用一个SQL解决超卖使用mysql悲观锁解决超卖使用mysql乐观锁解决超卖四种锁比较Redis乐观锁集成Redis超卖现象redis乐观锁解决超卖 三、分布式锁概述四、Redis分布式锁实现方案…

全连接层是什么,有什么作用?

大家好啊,我是董董灿。 如果你是搞AI算法的同学,相信你在很多地方都见过全连接层。 无论是处理图片的卷积神经网络(CNN),还是处理文本的自然语言处理(NLP)网络,在网络的结尾做分类…