【图像处理OpenCV(C++版)】——4.5 全局直方图均衡化

news2025/6/8 13:45:27

前言

😊😊😊欢迎来到本博客😊😊😊

🌟🌟🌟 本专栏主要结合OpenCV和C++来实现一些基本的图像处理算法并详细解释各参数含义,适用于平时学习、工作快速查询等,随时更新。

😊😊😊 具体食用方式:可以点击本专栏【OpenCV快速查找(更新中)】–>搜索你要查询的算子名称或相关知识点,或者通过这篇博客👉通俗易懂OpenCV(C++版)详细教程——OpenCV函数快速查找(不断更新中)]查阅你想知道的知识,即可食用。

🎁🎁🎁支持:如果觉得博主的文章还不错或者您用得到的话,可以悄悄关注一下博主哈,如果三连收藏支持就更好啦!这就是给予我最大的支持!😙😙😙


文章目录

    • 学习目标
    • 一、概念及原理
      • 1.1 相关概念及原理
      • 1.2 实现步骤
      • 1.3 应用场景
    • 二、 代码实现
    • 三、 总结

学习目标

  • 熟悉全局直方图均衡化概念及原理
  • C++实现全局直方图均衡化案例

  上一节伽马变换在提升对比度上有比较好的效果,但是需要手动调节γ值这节将介绍更为方便的方法自动调节图像对比度——全局直方图均衡化

一、概念及原理

1.1 相关概念及原理

  假设输入图像为I,高为H、宽为W,histI 代表I的灰度直方图,histI (k)代表灰度值为k(0≤k≤255)的像素个数。全局直方图均衡化操作是对图像I进行改变,使得输出图像O的灰度直方图histO是“平”的,即每一个灰度级的像素点个数是“相等”的
  注意:其实这里的“相等”不是严格意义上的等于,而是约等于,比如高为100、宽为255的图像矩阵不可能出现每一个灰度级的像素点个数是严格相等的,即:

  对于任意的灰度级p,0≤p≤255,总能找到q,0≤q≤255,使得:

  也称为IO的累加直方图。因为:

  所以:
  即:

  上面给出了一个从亮度级为p的输入像素到亮度级为q的输出像素的映射,那么令

  其中I(r,c)I的第r行第c列的灰度值,O(r,c)是对应位置输出的灰度值,其中0≤r≤H,0≤c≤W这样就计算出了输出图像O的每一个位置的灰度值

1.2 实现步骤

  首先,直观感受直方图均衡化效果。左边是原始的直方图,右边是均衡化以后的结果。

  对于直方图均衡化的实现主要分四个步骤:

  第一步:计算图像的灰度直方图并归一化

第二步:计算灰度直方图的累加直方图。

第三步:根据累加直方图和直方图均衡化原理得到输入灰度级和输出灰度级之间的映射关系。

第四步:根据第三步得到的灰度级映射关系,循环得到输出图像的每一个像素的灰度级。

1.3 应用场景

  直方图均衡化的应用常见很广泛:医疗图像、人脸识别、车牌识别等等。直方图均衡化以后,色彩更丰富。看起来能够描述出更多的信息。否则图像过亮或者过暗或者色彩集中在某个区域,不好区分细节。
  比如一些CT的图像,过暗。车牌识别也是,在光线不好的地方,车牌特别暗。闪光灯抓拍的,又太亮了。人脸识别也一样。


二、 代码实现

  OpencvCV提供了实现的直方图均衡化函数equalizeHist(),具体如下:

void equalizeHist(InputArray src, OutputArray dst)

  src为要均衡的输入图像,必须是8bit单通道图像,即灰度图
  dst是原图像大小相等经过直方图均衡处理后的输出图像,参数dst可以不传入

  除了理解简单的函数,equalizeHist()函数原理我们应该也要简单熟悉一下:

#include <iostream>
#include <opencv2/opencv.hpp> 
# include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv ;

Mat equalHist (Mat image){
	CV_ Assert (image.type() == CV_8UC1) ;
	//获取图像宽高
	int rows = image.rows;
	int cols = image.cols;
	//第一步:计算图像灰度直方图
	Mat grayHist = calcGrayHist(image);
	//第二步:计算累加灰度直方图
	Mat zeroCumuMoment = Mat::zeros(Size(256, 1),CV_ 32SC1);

	for(intp=0;p<256;p++){
		if (p==0){
			zeroCumuMoment.at<int>(0, p) = grayHist.at<int>(0, 0);
		}
		else
			zeroCumuMoment.at<int>(0, p) = zeroCumuMoment.at<int>(0, p-1) + grayHist.at<int>(0, p);
	}
	
	//第三步:根据累加直方图和直方图均衡化原理得到输入灰度级和输出灰度级之间的映射关系
	Mat outPut_ q = Mat::zeros (Size(256, 1),CV_8UC1);
	float cofficient = 256 / (rows*cols) ;
	for (int p = 0; p < 256;p++){
		float q = cofficient*zeroCumuMoment.at<int>(0, p) - 1;
		if(q>0){
			outPut_ q.at<uchar>(0, p) = uchar(floor(q));
		}
		else
			outPut_ q.at<uchar>(0, p) = 0;
	}
	
	//第四步:得到直方图均衡化后的图像
	Mat equalHist Image= Mat::zeros (image.size(),CV_8UC1);
	for(intr=0;r<rows;r++){
		for(intC=0;C<cols;c++){
			int p = image.at<uchar>(r, c) ;
			equalHistImage.at<uchar>(r, c) = outPut_ q. at<uchar>(0, p);
		}
	}
	
	return equalHistImage;

}

  我们可以看下直方图均衡化的效果:

#include <iostream>
#include <opencv2/opencv.hpp> 
# include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv ;

int main() {
	Mat src = imread(D:/VSCodeFile/0penCV_CSDN/image/logo.jpeg);
	//Mat src;
	if (src.empty() {
		cout<<“the image is empty!" << endl;
	imshow("image",src);
	
	Mat gray;
	cvtColor (src, gray, COLOR_BGR2GRAY);
	imshow("灰度图",gray);
	
	Mat dst;
	equalizeHist (gray, dst) ;
	imshow("直方图均衡化演示",dst) ;
	
	waitKey (0) ;
	return 0;
}

三、 总结

  最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。OpenCV是学习图像处理理论知识比较好的一个途径,大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,有什么问题希望大家可以积极评论交流,我也会及时更新,来督促自己学习进度。希望大家觉得不错的可以点赞、关注、收藏。


🚶🚶🚶 今天的文章就到这里啦~
喜欢的话,点赞👍、收藏⭐️、关注💟哦 ~

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

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

相关文章

Vue中路由缓存及activated与deactivated的详解

目录前言一&#xff0c;路由缓存1.1 引子1.2 路由缓存的方法1.2.1 keep-alive1.2.2 keep-alive标签中的include属性1.2.3 include中多组件的配置二&#xff0c;activated与deactivated2.1 引子2.2 介绍activated与deactivated2.3 解决需求三&#xff0c;整体代码总结前言 在Vu…

【C++】C++11语法 ~ lambda 表达式

&#x1f308;欢迎来到C专栏~~ lambda 表达式 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的一句鸡…

WPF常用UI库和图标库(MahApps、HandyControl、LiveCharts)

WPF常用UI库和图表库&#xff08;MahApps、HandyControl、LiveCharts&#xff09; WPF有很多开源免费的UI库&#xff0c;本文主要介绍常见的MahApps、HandyControl两个UI库&#xff1b;在开发过程中经常会涉及到图表的开发&#xff0c;本文主要介绍LiveCharts开源图表库。 UI…

Dell Precision T7910 工作站做RAID

1&#xff1a;开机根据提示按Ctrl-C 2&#xff1a;进入下面界面直接按回车。Adapter是LSISAS3008IR的卡。 3&#xff1a;回车来到下面的界面&#xff0c;我们选择RAID Propertie回车。 4&#xff1a;回车来到选择RAID级别的界面。根据自己的硬盘数量和需求进行选择。 5&#xf…

云原生丨Prometheus+Grafana监控 OpenGauss 数据库

文章目录前言一、Prometheus的介绍及安装1、Prometheus 介绍2、Prometheus 安装二、Grafana的介绍及安装1.Grafana 介绍2、Grafana 安装三、安装探针1、安装Node Exporter探针2.安装opengauss_exporter探针四、 访问Prometheus与Grafana1、 访问Prometheus2、 访问 Grafana五、…

React 组件性能优化

React 组件性能优化1. 组件卸载前进行清理操作2. PureComponent3. shouldComponentUpdate4. React.memo5. 使用组件懒加载6. 使用 Fragment 避免额外标记7. 不要使用内联函数定义8. 在构造函数中进行函数this绑定9. 类组件中的箭头函数10. 避免使用内联样式属性11. 优化条件渲染…

记录复现一下第一次awd

前言 之前没打过awd&#xff0c;这次学长组织了一场awd娱乐赛&#xff0c;两个web一个pwn&#xff0c;还有一个黑盒&#xff0c;只会web&#xff0c;第一次啥也不会瞎打&#xff0c;被打烂了&#xff0c;不会写脚本&#xff0c;手交flag的感觉真“不错”&#xff0c;感觉awd还…

NetIQ 高级认证框架

NetIQ 高级认证框架 NetIQ Advanced Authentication 提供无密码身份验证并提升安全访问&#xff0c;以满足这个可扩展的基于标准的身份验证框架的合规要求。 优点 1、灵活性不仅仅在于方法。平台和应用程序支持至关重要。将安全范围扩展到您的所有系统。 2、通过一套适合…

大数据技术之Hadoop(生产调优手册)

第1章 HDFS—核心参数 1.1 NameNode内存生产配置 1&#xff09;NameNode内存计算 每个文件块大概占用150byte&#xff0c;一台服务器128G内存为例&#xff0c;能存储多少文件块呢&#xff1f; 128 * 1024 * 1024 * 1024 / 150Byte ≈ 9.1亿 G MB KB Byte 2&#xff09;Hadoop…

百度笔记聚合怎么写

百度笔记聚合怎么写&#xff0c;#百度笔记聚合&#xff0c;#百度笔记优化&#xff0c;#百度笔记排名 小红书笔记收录大揭秘什么是笔记被收录&#xff1f; 你将你的笔记的标题复制&#xff0c;去搜索框搜索&#xff0c;如果能搜索到你的笔记出来&#xff0c;那就是被收录了。什…

C语言学习笔记-文件读写

C 文件读写 什么是文件&#xff1f; 文件是以计算机硬盘为载体存储在计算机上的信息集合。是数据源的一种&#xff0c;最主要的作用是保存数据。在程序设计中&#xff0c;我们可将文件分为两大类&#xff1a;程序文件和数据文件 &#xff08;1&#xff09;程序文件 包括源程…

浅谈前端安全和浏览器安全策略

前端安全 XSS(跨站脚本攻击) Cross-Site Scripting&#xff08;跨站脚本攻击&#xff09;简称 XSS&#xff0c;是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本&#xff0c;使之在用户的浏览器上运行。利用这些恶意脚本&#xff0c;攻击者可获取用户的敏感信息如 Co…

208:vue+openlayers 监听瓦片地图加载情况,200、403及其他状态码的处理示例

第208个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayer中加载XYZ地图,在load瓦片时,通过XMLHttpRequest进行捕捉,监听瓦片地址的loadend事件,针对不同的状态码,给出不同的处理结果。具体的方法参看源代码。 直接复制下面的 vue+openlayers源代码,操作2分钟即…

Conda安装到虚拟环境中的包在pycharm中不显示--pip下载的包都到了base环境中-Ubuntu20.04

问题 今天刚装了一个Ubuntu20.04系统&#xff0c;安装完Anaconda&#xff0c;虚拟环境的包也都下载好了&#xff0c;结果在pycharm中配置完解释器后&#xff0c;只有几个基础的包&#xff0c;切换到base环境后发现&#xff0c;这些包都被下载到了base环境中。 在网上查了各种…

《小猫猫大课堂》三轮5——动态内存管理(通讯录动态内存化)

宝子&#xff0c;你不点个赞吗&#xff1f;不评个论吗&#xff1f;不收个藏吗&#xff1f; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的很重…

seata分布式事务之AT模式实践代码

seata框架 AT模式&#xff1a; 先添加seata需要的数据库相关表&#xff0c;AT模式需要在每个业务所属库下建undo_log表&#xff0c;用来回滚的&#xff0c;出错seata就会从这个表生成反向sql回退数据 建表语句&#xff1a; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0; -…

持续集成Jenkins (四)Jenkins+git+maven项目构建、自动化部署

GIT配置1.1 前言&#xff1a;需要安装 git 客户端.yum install git1.2 Jenkins 配置插件 Git 在仪表盘选择Manage Jenkins>>Plugin Manager>>进入如下页面&#xff0c;可以选择可选的插件&#xff0c;安装完成后的插件在installed里面可以看到&#xff0c;我这里已…

DataFrame与Spark SQL的由来

文章目录DataFrame与Spark SQL的由来RDD 之殇&#xff1a;优化空间受限DataFrame 横空出世幕后英雄&#xff1a;Spark SQL基于 DataFrame&#xff0c;Spark SQL 是如何进行优化的Catalyst 优化器TungstenDataFrame与Spark SQL的由来 Spark 已经有了 RDD 这个开发入口&#xff…

市场最快图表:LightningChart .NET v.10.4.1 Crack

LightningChart .NET v.10.4.1 已经发布&#xff01; 新功能、新自定义控件和性能改进 DataCursor&#xff1a;图表中自动数据跟踪的新功能。 在以前的版本中&#xff0c;LightningChart .NET 提供了不同的工具来实现数据跟踪功能&#xff0c;但是这些需要用户进行一些额外的编…

Python-第一天 安装Python和PyCharm

Python-第一天 安装Python和PyCharm一、安装Python1. 下载2. 安装3.验证是否安装成功二、安装和配置PyCharm工具1.下载2.安装3.创建工程4.配置4.1 修改主题4.2 修改默认字体和大小4.3 通过快捷键快速设置字体大小4.4 汉化软件4.5 其它插件4.6 常用快捷建一、安装Python 1. 下载…