图像处理之直方图均衡

news/2024/5/19 10:01:46/文章来源:https://blog.csdn.net/GrayOnDream/article/details/127021987

  直方图均衡是一种将图像中的灰度分布转换成均匀分布,从而增强图像的对比度的图像处理方法。直方图均衡可以将原本偏白或者偏黑的图像转换成对比度符合人眼视觉的图像。

1 原理

连续空间
  连续空间内的图像灰度r∈[0,L−1],L表示灰度级r\in[0,L-1],L表示灰度级r[0,L1]L表示灰度级,期望的均衡化转换函数为
s=T(r),0≤r≤L−1s=T(r),0\le r\le L-1 s=T(r),0rL1
  其中TTT为灰度变换函数,sss是经过变换后的灰度值,该变化函数满足两个条件:

  • T(r)T(r)T(r)在区间[0,L−1][0, L-1][0,L1]内是严格单调递增函数。保证转换是一一对应的避免出现二义性;
  • 0≤r≤L−10 \le r\le L - 10rL1时,0≤s≤L−10 \le s\le L - 10sL1。保证输入输出的灰度范围相同。

  我们期望的是将输入的灰度概率分布p(r)p(r)p(r)转换成输出的灰度概率分布p(s)=1L−1p(s)=\frac{1}{L - 1}p(s)=L11。这里选择下面的变换函数来证明这个函数是可行的:
s=T(r)=(L−1)∫0rpr(w)dw,w为积分的假变量s=T(r)=(L-1)\int_{0}^{r}p_r(w)dw,w为积分的假变量 s=T(r)=(L1)0rpr(w)dww为积分的假变量
  首先,∫0rpr(w)dw\int_{0}^{r}p_r(w)dw0rpr(w)dw的值域为[0,1][0,1][0,1]因此sss的值域为[0,L−1][0,L-1][0,L1];另外该函数也是严格单调递增的。基本条件满足。下面我们证明p(s)=1L−1p(s)=\frac{1}{L-1}p(s)=L11。因为
p(s)=pr(r)∣drds∣=pr(r)1dsdr=pr(r)1(L−1)ddr[∫0rpr(w)dw]=pr(r)1(L−1)pr(r)=1L−1\begin{equation} \begin{aligned} p(s)&=p_r(r)|\frac{dr}{ds}|\\ &=p_r(r)\frac{1}{\frac{ds}{dr}}\\ &=p_r(r)\frac{1}{(L-1)\frac{d}{dr}[\int_{0}^{r}p_r(w)dw]}\\ &=p_r(r)\frac{1}{(L-1)p_r(r)}\\ &=\frac{1}{L-1} \end{aligned} \end{equation} p(s)=pr(r)dsdr=pr(r)drds1=pr(r)(L1)drd[0rpr(w)dw]1=pr(r)(L1)pr(r)1=L11
  因此s=T(r)=(L−1)∫0rpr(w)dws=T(r)=(L-1)\int_{0}^{r}p_r(w)dws=T(r)=(L1)0rpr(w)dw可以作为均衡化变换函数。
离散空间
  而对于图像处理始终是离散空间,离散空间的灰度rk,k为灰度级,k∈[0,L−1]r_k,k为灰度级,k\in [0,L-1]rkk为灰度级,k[0,L1]的概率近似为
pr(rk)=nkMNp_r(r_k)=\frac{n_k}{MN} pr(rk)=MNnk
  其中k为灰度级,k∈[0,L−1]k为灰度级,k\in [0,L-1]k为灰度级,k[0,L1]MMMNNN分别为图像的宽高,nkn_knk为当前灰度级像素点的数量。则利用上面的变换函数得到的sks_ksk
sk=T(rk)=(L−1)∑j=0kpr(rj)=L−1MN∑j=0knjs_k=T(r_k)=(L-1)\sum_{j=0}^{k}p_r(r_j)=\frac{L-1}{MN}\sum_{j=0}^{k}{n_j} sk=T(rk)=(L1)j=0kpr(rj)=MNL1j=0knj
  另外利用上面的变化函数计算出来的灰度值可能是小数,因此需要最近取整。以及对于RGB图像分别对R、G、B三个通道的图像进行变换的话会出现色相问题,因此需要将图像转换成其他颜色空间比如YUV,只对Y做灰度变换。

2 实现

  实现比较简单,首先逐像素计算每个灰度级的数量,根据改数量计算出每个灰度级的概率,最后利用上面的公式计算出最终的颜色映射关系,最终将根据映射关系将原图中颜色进行映射。

static vector<float> countGrayProp(const Mat &img) {assert(img.channels() == 1);double pixelProp = 1.0 / (img.rows * img.cols);vector<float> ret(GRAPH_GRAY_LAYER_NUM, 0.0);for (int i = 0; i < img.rows; i++) {for (int j = 0; j < img.cols; j++) {ret[static_cast<int>(img.at<uchar>(i, j))] += pixelProp;}}return ret;
}
/** @brief 均衡化灰度图*/
static Mat avgGrayHistogram(const Mat &img) {assert(img.channels() == 1);vector<float> props = countGrayProp(img);vector<float> propSum(GRAPH_GRAY_LAYER_NUM, 0.0);for (int i = 0; i < GRAPH_GRAY_LAYER_NUM;i ++) {if (i == 0) {propSum[i] = props[i];}else {propSum[i] = (props[i] + propSum[i - 1]);}}Mat ret(img.rows, img.cols, CV_8UC1);for (int i = 0; i < img.rows; i++) {for (int j = 0; j < img.cols; j++) {int value = static_cast<int>(img.at<uchar>(i, j));ret.at<uchar>(i, j) = int((GRAPH_GRAY_LAYER_NUM - 1) * propSum[value]);}}return ret;
}Mat avgHistogram(const Mat &img) {if (img.channels() == 1) {return avgGrayHistogram(img);}else if (img.channels() == 3) {Mat yuvImg;cvtColor(img, yuvImg, COLOR_BGR2YUV);std::vector<Mat> yuvImgs;split(yuvImg, yuvImgs);yuvImgs[0] = avgGrayHistogram(yuvImgs[0]);Mat proYUV, ret;merge(yuvImgs, proYUV);cv::cvtColor(proYUV, ret, COLOR_YUV2BGR);return ret;}return img;
}

  对于单通道的灰度图效果如下,能够看到均衡化后的灰度直方图中灰度更加均匀:
在这里插入图片描述
在这里插入图片描述

  如果直接对rgb三个通道做均衡化会出现下面的情况(1,2,3,4四张图中1和3为处理前的图,34为处理后的)
在这里插入图片描述

  首先将图像转换到其他颜色空间比如YUV,只对Y分量进行均衡化就不会有明显的的色差和奇异点。
在这里插入图片描述

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

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

相关文章

上线记 | 人大金仓助力东莞卫生健康领域核心系统改造升级

随着人工智能、云计算、大数据、机器学习等新兴技术在医疗信息化建设中不断深入&#xff0c;以患者为中心、构建智慧医院、提升医院信息智能化问题迫在眉睫。为进一步深化医改工作&#xff0c;加强妇幼卫生信息管理&#xff0c;东莞市卫生健康局对东莞妇幼卫生信息平台进行了国…

[leetcode top100] 0923 多数元素,反转链表,翻转二叉树,回文链表,移动零

目录 169. 多数元素 - 力扣&#xff08;LeetCode&#xff09; 206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 226. 翻转二叉树 - 力扣&#xff08;LeetCode&#xff09; 234. 回文链表 - 力扣&#xff08;LeetCode&#xff09; 283. 移动零 - 力扣&#xff08;Le…

2106. 摘水果(每日一难phase-day22)

2106. 摘水果 在一个无限的 x 坐标轴上&#xff0c;有许多水果分布在其中某些位置。给你一个二维整数数组 fruits &#xff0c;其中 fruits[i] [positioni, amounti] 表示共有 amounti 个水果放置在 positioni 上。fruits 已经按 positioni 升序排列 &#xff0c;每个 positi…

3. 链表

链表是一种通过指针串联在一起的线性结构,每一个结点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个结点的指针域指向null(空指针的意思)。  1. 链表基础单链表:指针域只指向结点的下一个结点。双链表:每一结点有两个指针域,一个指向下…

记批处理修改计算机名一次蠢操作造成电脑指定的域不存在或无法联系

近日,公司电脑需要修改计算机名(无域控),随意在网上找了一篇修改代码,正常操作右击脚本管理员运行,输入计算机名可正常修改,但是如果运行后不输入计算机名直接点确认,则会造成计算机重启后无法登陆,提示指定的域不存在或无法联系,刚好公司也有这种坑货的存在。虽然不…

java基于ssm 的留学资讯申请网的设计与实现

随着计算机信息化的深入&#xff0c;越来越多的行业使用管理系统来进行管理。出国留学逐渐成为许多大学生的热门选择&#xff0c;但是国外学校多&#xff0c;选择性大&#xff0c;如果从这些信息中&#xff0c;挑选符合自己的学校是非常重要的事情。基于此&#xff0c;开发”萨…

C#基础--集合

文章目录集合集合接口和类型列表创建列表集合初始值设定项添加元素插入元素访问元素删除元素搜索元素排序队列栈链表有序列表字典字典初始化器键的类型Lookup 类有序字典集性能集合 集合接口和类型 大多数集合类都可在System.Collections和System.Collections.Generic名称空间…

河北稳控科技手持VH501TC混合传感器信号采集读数仪工程监测仪器介绍

河北稳控科技手持VH501TC混合传感器信号采集读数仪工程监测VH501TC手持采集读数仪,设备是专用的多类型传感器手持式读数仪,主测传感类型为单弦式振弦传感器,辅测传感类型为电压、电流传感。采用 32 位 ARM 处理器和大尺寸全彩屏、阵列按键设计,彩屏,不受阳光影响,清楚明了…

SpringCloud使用注解+AOP+MQ来实现日志管理模块

简介 无论在什么系统中,日志管理模块都属于十分重要的部分,接下来会通过注解+AOP+MQ的方式实现一个简易的日志管理系统 思路 注解: 标记需要记录日志的方法 AOP: 通过AOP增强代码,利用后置/异常通知的方式获取相关日志信息,最后使用MQ将日志信息发送到专门处理日志的系…

【Python初级人工智能精讲】用Paddlehub给一段没有标点符号的文字加上合适的标点符号

Python初级人工智能精讲 文章目录Python初级人工智能精讲一、写在前面二、七步精讲三、模型介绍四、进入实战1.源代码2.运行效果(1) cmd方面(2) txt文件运行前后对比五、休吃霸王餐六、每日一句一、写在前面 今天给分享的程序是&#xff1a;给一段文字自动加上合适的标点符号&…

【图像重建】基于极限学习机实现图像重建附matlab代码

1 内容介绍 本文采用 ELM 网络求解 ECT 非线性正问题&#xff0c;以提高求解精度&#xff0c;再将其与传统 Landweber 迭代算法相结合&#xff0c;进行图像重建&#xff0c;算法原理框图如图 3 所示&#xff0c;为叙述方便&#xff0c;将该方法记为 ELM-Landweber 算法。 2 部…

卡尔曼滤波(Kalman Filter)设计与应用

估计离散时间或连续时间线性系统的状态。 卡尔曼滤波&#xff08;Kalman filter&#xff09;是一种高效率的递归滤波器&#xff08;自回归滤波器&#xff09;&#xff0c;它能够从一系列的不完全及包含噪声的测量中&#xff0c;估计动态系统的状态。卡尔曼滤波会根据各测量量在…

最新 Hi3861开发环境搭建

Hi3861开发环境 最好参考官方文档&#xff1a; Hi3861开发环境 这里做下记录 &#xff08;1&#xff09;安装编译依赖基础软件&#xff08;仅Ubuntu 20需要&#xff09; 执行以下命令进行安装&#xff1a; sudo apt-get install build-essential gcc g make zlib* libffi-de…

最大子数组和-前缀和/动态规划/分治/暴力-Java/c++

一、题目描述 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 二、思路解析 1.前缀和 2.动态规划思想 题目只是要求一个结果&#xff…

非零基础自学Java (老师:韩顺平) 第21章 网络编程 21.1 网络的相关概念

非零基础自学Java (老师&#xff1a;韩顺平) ✈【【零基础 快速学Java】韩顺平 零基础30天学会Java】 第21章 网络编程 文章目录非零基础自学Java (老师&#xff1a;韩顺平)第21章 网络编程21.1 网络的相关概念21.1.1 网络通信21.1.2 网络21.1.3 ip 地址21.1.4 ipv4 地址分类…

C++ STL新特性:not1 not2 mem_fun mem_fun_ref mem_fn等函数(详解+示例代码)

文章目录谓词not1函数指定类型***继承标准库not2函数指定类型***继承标准库mem_fun函数mem_fun_ref函数mem_fn函数函数绑定示例建议先补充基础知识&#xff0c;否则生啃本节可能会有一定难度&#xff1a; CSTL&#xff1a;仿函数 CSTL&#xff1a; bind函数绑定 谓词 首先来解…

C++类和对象详解(上篇)

文章目录1.1&#xff1a;类的定义方式1.1.1&#xff1a;声明和定义放在类中1.1.2&#xff1a;声明定义分离1.1.3&#xff1a;成员变量命名规则1.1.4&#xff1a;访问限定符1.2&#xff1a;类的作用域1.3&#xff1a;类的实例化1.4&#xff1a;类对象模型1.4.1&#xff1a;如何计…

修改openLDAP管理员密码(docker-compose非容器方式/容器化方式/docker-compose)

文章目录1. 非容器化方式1.1 查看管理员信息1.2 获取密码的加密字串1.3 生成密码修改文件1.4 修改密码1.5 问题2. 容器化方式1. 非容器化方式 非容器化ldap更改管理员密码 1.1 查看管理员信息 命令 ldapsearch -H ldapi:// -LLL -Q -Y EXTERNAL -b "cnconfig" &quo…

Flink 容错机制 Checkpoint 生成与恢复流程

传送门:Flink 系统性学习笔记 Flink 是一个分布式数据处理系统,因此必须有一套机制处理各种故障,例如进程被强制杀掉、机器故障和网络连接中断。任务都是在本地维护状态,所以 Flink 要确保状态不丢以及不错。 在本节中,我们将介绍 Flink 的检查点是如何恢复和生成的,看它…

AutoAugment 学习

非官方项目地址&#xff1a;Github项目 官方文章&#xff1a;文章连接 关于图片地深度学习有时会需要大量的图片&#xff0c;因此&#xff0c;为了获得更多的图片&#xff0c;对已经获取的图片进行扩展就是一个必要地手段&#xff0c;简单来说&#xff0c;针对图片地数据增强就…