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 pltimg = 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()
下面就是结果了,与前面的结果对比一下,尤其是雕像区域:

相关文章:
OpenCV官方教程中文版 —— 直方图均衡化
OpenCV官方教程中文版 —— 直方图均衡化 前言一、原理二、 OpenCV 中的直方图均衡化三、 CLAHE 有限对比适应性直方图均衡化 前言 本小节我们要学习直方图均衡化的概念,以及如何使用它来改善图片的对比。 一、原理 想象一下如果一副图像中的大多是像素点的像素值…...
如何使用navicat图形化工具远程连接MariaDB数据库【cpolar内网穿透】
公网远程连接MariaDB数据库【cpolar内网穿透】 文章目录 公网远程连接MariaDB数据库【cpolar内网穿透】1. 配置MariaDB数据库1.1 安装MariaDB数据库1.2 测试局域网内远程连接 2. 内网穿透2.1 创建隧道映射2.2 测试随机地址公网远程访问3. 配置固定TCP端口地址3.1 保留一个固定的…...
【uniapp】uview1.x使用upload上传图片
和2.x不同的是,要用 action 来配置后端上传图片的接口地址; 再来一些配置项的命名有所不同,一般1.x的命名用 -,2.x的命名使用小驼峰; 1.x 的上传会自带删除时的提示框,2.x 没有; 重要的几个配置…...
基于nodejs+vue食力派网上订餐系统
目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性:…...
软件测试常用的8种功能测试类型有哪些?
软件测试常用的8种功能测试类型有哪些? 单元测试 单元测试确保在一个段中编写的每一段代码都能产生最佳结果。开发人员在单元测试期间只看接口和确定部件。它提供了代码进展的文档,因为每个代码单元在继续下一个之前都经过了彻底的测试。 集成测试 至少对…...
动态规划之01背包问题
01背包问题 1. 【模板】01背包2. 分割等和子集3. 目标和4. 最后一块石头的重量 II 01背包问题是一种动态规划问题,用于求解在有限容量的背包中装入最大价值的物品组合。具体步骤如下: 定义一个二维数组dp[i][j],表示从前i个物品中选择若干个…...
安防监控项目---boa服务器的移植
文章目录 前言一、boa服务器简介二、移植步骤三、测试结果四、A9平台移植BOA总结 前言 书接上期,在配置完成环境后,那么接下来呢还得移植两个非常关键的东西,一个呢时boa服务器,另一个呢时cgi接口,boa服务器能够使得我…...
Gson 字符串常用转换方式(集合转换为Json数组
数组转换为 Json 字符串: GsonUtils.toJson(itemListBean.getImgs())json 字符串转换为数组 Gson().fromJson(goodsDbBean.getImgs(), String[].class)Json 转换为已知实体类 GsonUtils.parseJSON(result, AFileInfoBean.class);Json 转换为已知实体类集合 List<…...
MyBatis的使用(XML映射文件)
MyBatis的使用(XML映射文件) MyBatis基于注解开发简单便捷,但是弊端是失去SQL语句的灵活性,不能根据实际情况产生不同的SQL语句 MyBatis除了支持注解开发以外,还支持一种开发方式:XML映射文件,…...
localhost知识
文章目录 一、localhost是什么?二、localhost 在平时用到的地方三、 localhost 与 127.0.01 一、localhost是什么? localhost 是一个特殊的主机名,通常指代本机。它被用来进行本地开发和测试,也常被用作网络配置中的占位符&#…...
PyTorch入门学习(八):神经网络-卷积层
目录 一、数据准备 二、创建卷积神经网络模型 三、可视化卷积前后的图像 一、数据准备 首先,需要准备一个数据集来演示卷积层的应用。在这个示例中,使用了CIFAR-10数据集,该数据集包含了10个不同类别的图像数据,用于分类任务。…...
【EI会议征稿】 2024年遥感、测绘与图像处理国际学术会议(RSMIP2024)
2024年遥感、测绘与图像处理国际学术会议(RSMIP2024) 2024 International Conference on Remote Sensing, Mapping and Image Processing 2024年遥感、测绘与图像处理国际学术会议(RSMIP2024)将于2024年1月19日-21日在中国厦门举行。会议主要围绕遥感、测绘与图像处理等研究领…...
MySQL 8 - 处理 NULL 值 - is null、=null、is not null、<> null 、!= null
处理 NULL 值: IS NULL:IS NULL 用于检查一个列是否为 NULL。例如,如果查找一个表中某一列的值为 NULL 的行,可以使用以下语法: SELECT * FROM table_name WHERE column_name IS NULL;IS NOT NULL:IS NOT N…...
高教社杯数模竞赛特辑论文篇-2018年C题:大型百货商场会员画像描述(附获奖论文及MATLAB代码实现)
目录 摘 要 一、问题重述 1.1 问题背景 1.2 问题提出 二、问题分析 2.1 问题一的分析...
#力扣:2315. 统计星号@FDDLC
2315. 统计星号 - 力扣(LeetCode) 一、Java class Solution {public int countAsterisks(String s) {int cnt 0;boolean flag true;for(char c: s.toCharArray()) {if(c |) flag !flag;else if(c * && flag) cnt;}return cnt;} }...
设计模式——单例模式详解
目录 设计模式类型单例模式单例模式方式饿汉式静态常量方式静态代码块形式 懒汉式线程不安全(不推荐)懒汉式优化(不推荐) 双重检查(推荐方式)静态内部类(推荐方式)枚举方式ÿ…...
一、W5100S/W5500+RP2040树莓派Pico<静态配置网络信息>
文章目录 1. 前言2. 相关网络信息2.1 简介2.2 优点2.3 应用 3. WIZnet以太网芯片4. 静态IP网络设置示例讲解以及使用4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 编译烧录 5. 注意事项6. 相关链接 1. 前言 从本章开始我们将用WIZnet的W5100S/W5500以太网芯片结合RP…...
【C++的OpenCV】第十四课-OpenCV基础强化(二):访问单通道Mat中的值
🎉🎉🎉 欢迎各位来到小白 p i a o 的学习空间! \color{red}{欢迎各位来到小白piao的学习空间!} 欢迎各位来到小白piao的学习空间!🎉🎉🎉 💖💖&…...
elementUI el-collapse 自定义折叠面板icon 和 样式 或文字展开收起
: :v-deep{.el-collapse-item__arrow {width: 40px;}.el-icon-arrow-right:before {content: "展开";font-size: 15px;font-family: heiti;color: #2295ff;font-weight: bold;}.el-collapse-item__arrow.is-active {transform: none;}.el-collapse-item__arrow.is-a…...
如何用个人数据Milvus Cloud知识库构建 RAG 聊天机器人?(上)
生成式人工智能时代,开发者可以借助大语言模型(LLM)开发更智能的应用程序。然而,由于有限的知识,LLM 非常容易出现幻觉。检索增强生成(RAG)https://zilliz.com/use-cases/llm-retrieval-augmented-generation 通过为 LLM 补充外部知识,有效地解决了这一问题。 在 Chat …...
从零到亿级调用量:电商客服Agent重构实录(含对话状态机+意图跳转图+人工接管SLA协议)
更多请点击: https://codechina.net 第一章:从零到亿级调用量:电商客服Agent重构实录(含对话状态机意图跳转图人工接管SLA协议) 面对日均峰值超1.2亿次的客服请求,原有基于规则匹配的客服Bot在大促期间频繁…...
2026年论文党必备:盘点2026年倾心之选的的降AIGC网站
轻松降低论文AI率在2026年已不再是天方夜谭。以下是2026年最炸裂、实测效果显著的降AIGC网站神器,覆盖AI痕迹消除、文本改写润色、降重优化、学术合规检测四大核心场景,帮你稳妥搞定毕业论文。 一、全流程王者:一站式搞定论文全链路 这类工具…...
为什么92%的Lindy自动化项目在第90天遭遇断崖式停滞?资深架构师紧急披露3个临界预警信号
更多请点击: https://intelliparadigm.com 第一章:为什么92%的Lindy自动化项目在第90天遭遇断崖式停滞?资深架构师紧急披露3个临界预警信号 当Lindy自动化项目运行至第90天左右,系统吞吐量骤降40%、任务积压率突破68%、人工干预频…...
大数据+大模型=乘法效应?6个场景告诉你,大模型如何让你的数据平台“活”起来!
本文探讨了大数据与大模型的关系,提出大模型是大数据平台的“发动机”。文章重点介绍了六个必须使用大模型才能解放双手的场景,包括数据血缘解析、Text2SQL、数据质量智能巡检、调度任务智能运维、元数据管理和报告自动生成。这些场景展示了大模型如何通…...
ThingsVis v1.1.15 版本更新:补齐嵌入与运维体验短板,多场景集成更可靠
ThingsVis v1.1.15:嵌入与运维体验的全面升级ThingsVis v1.1.15 版本以 ThingsVis 嵌入能力和设备详情页体验为核心进行更新。在 ThingsVis 嵌入方面,支持全屏、自动播放、剪贴板写入权限,修复 iframe 无法全屏问题;在设备详情页&…...
CANN算子开发调试实战:从“Segmentation Fault“到定位根因的完整流程
写Ascend C算子最怕的不是编译失败——编译失败有明确的错误信息。最怕的是运行时Segmentation Fault,什么都没告诉你,NPU直接挂了。没有堆栈、没有日志、只有一行"Killed"。 这篇整理了算子开发中常见的运行时错误、调试方法、以及定位根因的…...
2026年京东云OpenClaw/Hermes Agent配置Token Plan安装保姆级分享
2026年京东云OpenClaw/Hermes Agent配置Token Plan安装保姆级分享、OpenClaw是开源的个人AI助手,Hermes Agent则是一个能自我进化的AI智能体框架。阿里云提供计算巢、轻量服务器及无影云电脑三种部署OpenClaw 与 Hermes Agent的方案、百炼Token Plan兼容主流 AI 工具…...
【燃烧机】模拟了燃烧机的热力学循环分析活塞动力学以及温度和压力变化对发动机效率的影响【含Matlab源码 15557期】
💥💥💥💥💥💥💥💥💞💞💞💞💞💞💞💞💞Matlab武动乾坤博客之家💞…...
从‘相框’与‘相片’说起:彻底搞懂MFC文档/视图架构与消息路由(含实战避坑)
从相框到相片:深入解析MFC文档/视图架构的设计哲学与实战应用 在Windows桌面应用开发的历史长河中,MFC(Microsoft Foundation Classes)作为经典的C框架,其独特的文档/视图架构一直是开发者又爱又恨的设计。想象一下相框…...
别再被‘Requirement already satisfied’搞懵了!手把手教你用-m参数精准安装Python包
彻底解决Python包安装冲突:从报错到精通的完整指南 每次在命令行输入pip install后看到"Requirement already satisfied"的提示,是不是让你既困惑又沮丧?这背后往往隐藏着多Python环境冲突的问题。今天我们就来深入剖析这个常见痛点…...
