16.直方图均衡化

数字图像处理(17): 直方图均衡化处理

简介

  直方图均衡化是一种简单有效的图像增强技术,通过改变图像的直方图来改变图像中各像素的灰度,主要用于增强动态范围偏小的图像的对比度。当原始图像的灰度分布较为集中的时候,可能造成图像不够清晰,图像会过曝或者过暗。采用直方图均衡化,可以将原本较为集中的灰度分布变换成较为均匀的形式,增加了图像的灰度之间的动态范围,从而增加了图像的对比度。直方图均衡化的主要思想就是对图像灰度较为集中的地方进行拉伸展宽,对图像中像素较少的灰度值进行归并。

直方图均衡化理论基础

  严格来说,图像的灰度直方图是一个一维的离散函数,可以写成:
h ( k ) = n k k = 0 , 1 , 2 , 3 , . . . , L − 1 (1) h(k)=nk \,\,\,\,\,\,\,\,\,k=0,1,2,3,...,L-1\tag{1} h(k)=nkk=0,1,2,3,...,L1(1)
  公式中 n k nk nk是图像 f ( x , y ) f(x,y) f(x,y)中灰度级为 k k k的像素的个数。直方图的每一列的高度对应 n k nk nk。直方图提供了原图中各种灰度值分布的情况,在直方图的基础上,进一步定义归一化的直方图为灰度级出现的相对频率 P r ( k ) P_r(k) Pr(k),即:
P r ( k ) = n k N (2) P_r(k)=\frac{nk}{N}\tag{2} Pr(k)=Nnk(2)
  式中, N N N表示图像 f ( x , y ) 的像素的总数 f(x,y)的像素的总数 f(x,y)的像素的总数 n k nk nk是图像 f ( x , y ) f(x,y) f(x,y)中灰度级为 k k k的像素的个数。
  得到直方图的相对频率后就可以按照需求对直方图进行拉伸和映射。
  为了方便讨论,以 r r r s s s分别表示归一化了的原图像灰度和经直方图均衡化后的灰度,因为归一化了,所以r和s的取值范围都在0到1之间。所谓的直方图均衡化,就是根据直方图对像素点的灰度值进行变换,属于点操作范围。换而言之,即:已知r,求相应的s。
  在[0:1]区间内任意一个r,经变换函数 T ( r ) T(r) T(r)都可以产生一个对应的s,且
s = T ( r ) (3) s=T(r)\tag{3} s=T(r)(3)
  式中, T ( r ) T(r) T(r)应当满足以下两个条件:
  (1)在 0 ≤ r ≤ 1 0\leq r \leq 1 0r1内, T ( r ) T(r) T(r)为单调递增函数;
  (1)在 0 ≤ r ≤ 1 0\leq r \leq 1 0r1内有 0 ≤ T ( r ) ≤ 1 0\leq T(r) \leq 1 0T(r)1

直方图均衡化的实际运算过程

  (1)首先遍历图像,统计出每个灰度值各有多少个像素。
  (2)统计每个灰度值的像素各占一整幅图的多少百分比。以及累计直方图。
  (3)将累计直方图百分比进行区间映射(也就是乘以像素级255)得到像素级的映射关系。
  (4)根据映射关系对像素进行重新分配。

MATLAB实现

clear;
clc;
close all;a = imread('../img/pre_hist_rq.bmp');imshow(a);
[row,col] = size(a);hist_lut = zeros(1,256);
lut_add = zeros(1,256);result = zeros(row,col);%Statistical gray value   计算一副图像的灰度值分布数量
for i = 1:rowfor j = 1:colhist_lut(a(i,j)+1) = hist_lut(a(i,j)+1)+1;end
end%Cumulative histogram     统计累计直方图
for i=1:256if(i==1)lut_add(i) = hist_lut(i);else lut_add(i) = lut_add(i - 1) + hist_lut(i);end
end %累计直方图归一化与重映射
for i = 1:rowfor j=1:colresult(i,j) = lut_add(a(i,j)+1) * 255/(row*col);end
endmatlab_hist_eq = uint8(floor(result));hist_lut1 = zeros(1,256);
%图像灰度重映射
for i = 1:rowfor j = 1:colhist_lut1(matlab_hist_eq(i,j)+1) = hist_lut1(matlab_hist_eq(i,j)+1) + 1;end 
endsubplot(2,2,1);
imshow(uint8(a));subplot(2,2,2);
bar(hist_lut);subplot(2,2,3);
imshow(uint8(result));subplot(2,2,4);
bar(hist_lut1);

FPGA实现

module hist_eq#(parameter 	ROW 	= 	1920 		,parameter 	COL 	= 	1080 
)(input 	wire  			clk  		,input 	wire  			pre_vs 		,input 	wire  			pre_de 		,input 	wire  	[7:0] 	pre_data	,output 	wire   			post_vs 	,output 	wire  			post_de 	,output 	wire  	[7:0] 	post_data 
);reg  	[31:0] 	hist_lut 	[255:0] 	; 	 	//存放图像的灰度分布情况integer 	i;initial beginfor(i=0;i<256;i++)beginhist_lut[i] = 32'd0;end
endreg  			pre_vs_r 	;wire  			vs_pose 	;
wire  			ext_vs_pose ;reg  			rst_n 		;reg  	[15:0] 	hcnt 		;
reg  	[15:0] 	vcnt 		;reg  			inter_de 	;
reg  	[7:0] 	inter_cnt 	;reg  			clc_de 		;
reg  	[7:0] 	clc_cnt 	;wire  	[31:0] 	hist_sum 	;always @(posedge clk)pre_vs_r 	<= 	pre_vs 	;assign 	vs_pose 	<= 	~pre_vs_r && pre_vs ;data_sync_ext   u1_data_sync_ext(.clka           (clk        ),.rst_n          (1'b1       ),.pulse_a        (vs_pose    ),.ext_pulse_a    (ext_vs_pose) 
);/***********************行列计数*************************************/
always @(posedge clk)rst_n <=    ~ext_vs_pose ;always @(posedge clk)if(rst_n == 0)hcnt    <=  0;else if(hcnt == COL - 1 && pre_de == 1'b1)hcnt    <=  0;else if(pre_de == 1'b1)hcnt    <=  hcnt+1;else hcnt    <=  hcnt;always @(posedge clk)if(rst_n == 0)vcnt    <=  0;else if(hcnt == COL - 1 && vcnt == ROW - 1 && pre_de == 1'b1)vcnt    <=  0;else if(hcnt == COL - 1)vcnt    <=  vcnt + 1;else vcnt    <=  vcnt    ; //当数据到来时相应的灰度值数量+1  当数据结束时依次清除数据
always @(posedge clk)if(clc_de)hist_lut[clc_cnt] <= 32'd0;else if(pre_de==1)hist_lut[pre_data] <= hist_lut[pre_data] + 1;//当一帧数据结束后,开始统计直方图使能
always @(posedge clk)beginif(!rst_n)begininter_de 	<= 	0 ;endelse if(inter_cnt == 8'd255)begininter_de 	<= 	0;endelse if(hcnt == COL -1 && vcnt == ROW - 1)begininter_de 	<= 	1'b1;endelse begininter_de 	<= 	inter_de ;end
end//依次统计直方图的灰度
always @(posedge clk)beginif(!rst_n)begininter_cnt 	<= 0;endelse if(inter_cnt == 8'd255)begininter_cnt 	<= 0;endelse if(inter_de == 1)begininter_cnt 	<= inter_cnt + 1'b1;endelse begininter_cnt 	<= inter_cnt;end
end//依次统计直方图灰度
always @(posedge clk)if(rst_n == 0)lut_add 	<= 	0;else if(inter_de)lut_add 	<= 	lut_add 	+ 	hist_lut[inter_cnt];else lut_add 	<= 	'd0;//ram写使能拉高
always @(posedge clk )if(rst_n == 0)wea 	<= 	1'b0;else wea 	<= 	inter_de;//ram写地址
always @(posedge clk)if(rst_n == 0)addra 	<= 'd0 ;else if(addra == 8'd255)addra 	<= 	'd0;else if(wea == 1'd1)addra 	<= 	addra + 1'b1;else addra 	<= 	addra ;//统计完成后清除灰度直方图数据
always @(posedge clk)if(rst_n == 0)clc_de 	<= 	1'b0;else clc_de 	<= 	inter_de ;always @(posedge clk)if(rst_n == 0)clc_cnt 	<= 0;else clc_cnt 	<= 	inter_cnt ;//存储灰度直方图的ram
hist_ram u1_hist_ram (.clka		(clk			),  	.wea		(wea			),   	.addra		(addra			), 	.dina		(lut_add		),  	.douta		(				), 	.clkb		(clk			),  	.web		(1'b0			),   	.addrb		(pre_data		), 	.dinb		(32'd0			),  	.doutb		(hist_sum		)  	
);reg  [0:1]	pre_de_r 	;reg  	[63:0] 	mult 	;localparam 	[63:0]  	coe 	= 	(2**25)*255/(COL*ROW) ; //累计直方图归一化以及重映射需要乘以的数据   乘数是累计直方图的灰度值always @(posedge clk)if(rst_n == 0)pre_de_r 	<= 	0;else pre_de_r 	<= 	{pre_de_r[0],pre_de};//图像的数据进行重映射
always @(posedge clk)if(rst_n == 0)mult 	<= 	0;else if(pre_de_r[0] == 1'b1)mult 	<= 	hist_sum * coe;else mult 	<= 	'd0;always @(posedge clk)if(rst_n == 0)post_de 	<= 	1'b0;else post_de 	<= 	pre_de_r[1];//图像数据的位截取
always @(posedge clk)if(rst_n == 0)post_data 	<= 	1'b0;else if(pre_de_r[1] == 1'b1)post_data 	<= 	mult[25+7:25];else post_data 	<= 	'd0;

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

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

相关文章

如何高效率阅读文献

很多导师曾说&#xff0c;不应该花费超过30分钟阅读一篇论文&#xff0c;在某些特殊的时间段&#xff0c;30分钟甚至可能都算是太多的时间&#xff0c;比如&#xff1a;你正准备毕业论文或者想要发表论文的时候…… 文献阅读为何如此重要&#xff1f;又该如何有效快速的阅读&a…

C++基础与深度解析 | 什么是C++ | C++开发环境与相关工具 | C++编译/链接模型

文章目录 一、什么是C二、C的开发环境与相关工具三、C的编译/链接模型 一、什么是C C是一门比较流行的编程语言&#xff08;高级语言&#xff09;&#xff0c;同时也是一门复杂的语言。从TIOBE 编程社区指数中可以看出&#xff1a;在2024.04中&#xff0c;其编程语言受欢迎程度…

HCIP【BGP综合实验】

目录 一、实验拓扑图&#xff1a; 二、实验要求&#xff1a; 三、实验思路&#xff1a; 四、实验步骤&#xff1a; 1、进行网段的子网划分&#xff08;整个实验总共有19条网段&#xff09;&#xff1a; (1)首先&#xff0c;根据实验要求&#xff0c;将172.16.0.0/16全部划…

2024湖南理工学院程序设计竞赛(同步赛) G. 区间递减(思维题 分类讨论 ST表)

题目 https://ac.nowcoder.com/acm/contest/82672/G 思路来源 出题人 涼風青葉7代码 题解 注意到三种情况即可&#xff0c; 第一种情况&#xff0c;10 9 8 1 2&#xff0c;保留1 第二种情况&#xff0c;6 5 10 9 4 4&#xff0c;保留5 4 4 第三种情况&#xff0c;6 5 4&…

基于STM32单片机的二轮平衡小车

设计一个基于STM32单片机的二轮平衡小车是一个涉及硬件选择、软件编程、控制算法和机械设计的复杂项目。这里我可以给你一个大致的项目概述和一些基础的代码示例&#xff0c;但请注意&#xff0c;完整的项目设计和实现将需要更详细的规划和大量的调试工作。 1. 项目概述 二轮…

SpringBoot使用腾讯云实现短信功能

引入依赖 <!-- 腾讯云依赖 --> <dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java</artifactId><version>3.1.270</version> </dependency>配置文件 # 腾讯云短信配置 sms:tence…

jdk8的新特征

1&#xff1a; jdk8中新增的方法 在jdk8中对接口进行了增强&#xff0c;在jdk8之前 interface 接口名{ 静态常量&#xff1a; 抽象方法&#xff1a; } 在jdk8之后 interface 接口名{ 静态常量&#xff1a; 抽象方法&#xff1a; 默认方法&#xff1a; 静态方法&#xff1a; } 2…

linux使用/etc/hosts.deny拒绝恶意ssh到本机

一、目标 在某些特殊情况下&#xff0c;服务器有很多恶意暴力ssh破解的攻击。解决的办法有很多&#xff0c;这里用/etc/hosts.deny增加黑名单的方式来简单阻止一下。 二、前言 /etc/hosts.allow 优先于 /etc/hosts.deny。 如果在allow和deny文件中都有某个ip&#xff0c;那…

JAVA基础--IO

IO 什么是IO 任何事物提到分类都必须有一个分类的标准&#xff0c;例如人&#xff0c;按照肤色可分为&#xff1a;黄的&#xff0c;白的&#xff0c;黑的&#xff1b;按照性别可分为&#xff1a;男&#xff0c;女&#xff0c;人妖。IO流的常见分类标准是按照*流动方向*和*操作…

人形机器人的组成原理、相关技术和行业应用

人形机器人的部件和工作原理 人形机器人的部件通常包括机身、关节、传感器、驱动器、控制器等。其工作原理是通过传感器收集环境信息&#xff0c;控制器根据预设的算法和程序生成动作指令&#xff0c;驱动器驱动关节运动&#xff0c;从而实现机器人的各种动作。 人形机器人主要…

Google与哈佛大学的科学家团队共同创造了一张人脑中一个极小部分的精细地图

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

插件:Best HTTP

一、简介 WebSocket WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据。在WebSocket API中&#xff0c;浏览器和服务器只需要完成一次握手&#xff0c;两者之间就直接可以创建持久性的连接&#xff0c;并进行双向数据传输。…

【SRC实战】无法支付的修改金额支付漏洞

挖个洞先 https://mp.weixin.qq.com/s/F4f8R4uKN0Q9BnTmjDMleg “ 以下漏洞均为实验靶场&#xff0c;如有雷同&#xff0c;纯属巧合 ” 01 — 漏洞证明 一、企业用户&#xff0c;标准商品 “ 支付订单需要公对公银行卡转账&#xff0c;如何绕过&#xff1f;” 1、点击任意…

bert 的MLM框架任务-梯度累积

参考&#xff1a;BEHRT/task/MLM.ipynb at ca0163faf5ec09e5b31b064b20085f6608c2b6d1 deepmedicine/BEHRT GitHub class BertConfig(Bert.modeling.BertConfig):def __init__(self, config):super(BertConfig, self).__init__(vocab_size_or_config_json_fileconfig.get(vo…

java入门-面向对象的三大特性

面向对象三大特性 封装 什么是封装 封装 是将代码及其处理的数据绑定在一起的一种编程机制&#xff0c;该机制保证了程序和数据都不受外部干扰且不被误用。 封装的作用 访问控制符 方法传参-值传递 传参类型是基本类型 程序案例&#xff1a; public static void main(St…

C++笔记(体系结构与内核分析)

1.OOP面向对象编程 vs. GP泛型编程 OOP将data和method放在一起&#xff0c;目的是通过封装、继承、多态提高软件的可维护性和可扩展性GP将data和method分开&#xff0c;可以将任何容器与任何算法结合使用&#xff0c;只要容器满足塞饭所需的迭代器类型 2.算法与仿函数的区别 …

Flutter 中的 Column 小部件:全面指南

Flutter 中的 Column 小部件&#xff1a;全面指南 在 Flutter 中&#xff0c;Column 是一个垂直布局的小部件&#xff0c;用于将子控件沿着垂直轴排列。Column 与 Row 相对&#xff0c;Row 是水平布局&#xff0c;而 Column 则是垂直布局。它非常适合用来创建列式布局&#xf…

AJAX前端与后端交互技术知识点以及案例

Promise promise对象用于表示一个异步操作的最终完成&#xff08;或失败&#xff09;及其结果值 好处&#xff1a; 逻辑更清晰了解axios函数内部运作机制成功和失败状态&#xff0c;可以关联对应处理程序能解决回调函数地狱问题 /*** 目标&#xff1a;使用Promise管理异步任…

Linux-02

Linux常用命令&#xff1a; ls: 列出目录touch: 创建文件 touch test.txt echo:往文件写内容echo "i love linux" >>test.txtcd&#xff1a;切换目录pwd&#xff1a;显示目前的目录mkdir&#xff1a;创建一个新的目录 mkdir dai:创建目录dai mkdir -p test1/t…

基于springboot的物业服务平台的设计与实现

基于springboot的物业服务平台的设计与实现 摘 要:本文针对社区物业服务管理现状,采用B/S系统架构并选择MySQL数据库作为系统的数据存储系统,设计并实现一个以Spring Boot为后端框架、Vue为前端框架的社区物业服务管理平台。与传统的物业服务管理方式相比,该系统取代了传统…