news 2026/11/4 5:58:55

[数字图像处理]灰度变换——直方图处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[数字图像处理]灰度变换——直方图处理

【修订版】本文已整理到我的个人博客,订正了原文的几处错误:讲均衡目标时引错了配图,另有拼写和公式记号的问题。CSDN 这一版保留原样,之后的勘误与更新只在博客进行:Histogram Processing : 直方图处理 | Finn's blog

直方图均衡

一副图像的直方图,表示了其灰度分布的特性。对于数字图像来说,假设灰度值k出现了次,那么其概率密度函数如下所示。

这个式子,表示了像素的灰度值为k概率。其中,M与N为图像的尺寸。

对于一幅动态范围较窄的图像,其归一化灰度直方图如下所示。

对于此类图像,使用灰度拉伸,也能使其的动态范围得到改善,增强图像对比度。但是,灰度拉伸从本质上来讲,是很暧昧的,灰度拉伸没有什么明确的目的,只是依靠某个函数的做了灰度变换,使得图像的在灰度直方图的分布范围扩大。灰度拉伸对于结果没有严格的要求,因此根据变换函数的不同,灰度拉伸有无数种结果。

与灰度拉伸不同的是,直方图均衡的目的就比较明确,使用某个特殊的函数,使原图像的灰度分布平均化。为了将其平均化,这里需要用到累积分布函数(Probability Density Function)的概念。

所谓的平均化,直方图均衡的目的是将一幅图的累积分布的曲线(下图左),变为下图右的分布形式。

(左)原图的累积分布曲线 (右)理想化直方图均衡后的累积分布曲线

从右图中可以看出,为了保证直方图均衡后的累积分布曲线是一条倾角为45°的直线,那么,变换后的函数的概率密度函数应与输入值无关,且保持一个常量。输入r与输出s有如下关系,

将变换关系

带入上式子,可得

将其带入输入r与输出s关系,可得到

到此,已经可以看出,输出的概率密度函数,与s的取值无关。很明显,这个分布是绝对平均的。

但是,事实上,上面的式子均是在连续的情况下的。在数字图像的领域,我们必须将其离散化,才能使用。离散的情况下,其累计分布函数如下所示。

至此,直方图均衡就完成了。

为了验证结果,其直方图均衡后的图像与灰度直方图如下所示。

结果就是这样了。但是,呃!!!!问题来了,这是直方图均衡么?这跟灰度拉升有何区别,而且其均衡后的图像的直方图也不是一个很平均的值,和我们的构想有很大区别。这个结果真的没问么?为了回答这个问题,将其原图像的累积分布函数与直方均衡后的累积分布函数画出来,如下。

(左)原图的累积分布曲线 (右)直方图均衡后的累积分布曲线

从累积分布曲线中,我们可以看到,直方图均衡后的曲线,确实跟我们设想的理想曲线很接近!由于我们证明的时候,是在连续的情况下去思考的,所以,将其离散之后,多少是有不理想的情况发生的。均衡后的累积分布曲线确实是一个不错的结果。这样看来,我们才能看清楚直方图均衡的本质。若不是这样,还真不知道直方均衡与灰度拉伸的区别。

为此,直方图均衡成功,Matlab代码如下。

close all; clear all; %% -------------Histogram Equalization----------------- close all; clear all; f = imread('washed_out_pollen_image.tif'); f = mat2gray(f,[0 255]); [M,N] = size(f); g = zeros(M,N); r = imhist(f)/(M*N); %(500*500 is size of image) s = zeros(256,1); for k = 1:1:256 for j = 1:1:k s(k,1) = s(k,1) + r(j); end end for x = 1:1:M %(500*500 is size of image) for y = 1:1:N g(x,y) = s(uint8(f(x,y)*255)+1,1); end end figure(); subplot(2,2,1); imshow(f); xlabel('a).Original Image'); subplot(2,2,2); h = imhist(f)/(M*N); bar(0:1/255:1,h); axis([0 1 0 0.1]),grid; %axis square; xlabel('b).The Histogram of a'); ylabel('Number of pixels'); subplot(2,2,3); imshow(g); xlabel('c).Histogram Equalization'); subplot(2,2,4); h = imhist(g)/(M*N); bar(0:1/255:1,h); axis([0 1 0 0.1]),grid; %axis square; xlabel('d).The Histogram of c'); ylabel('Number of pixels'); figure(); x=0:1/255:1; plot(x,s); axis([0,1,0,1]),grid; axis square; xlabel('intensity level of r'); ylabel('P_{r}(r)'); r = imhist(g)/(M*N); s = zeros(256,1); for k = 1:1:256 for j = 1:1:k s(k,1) = s(k,1) + r(j); end end figure(); x=0:1/255:1; plot(x,s); axis([0,1,0,1]),grid; axis square; xlabel('intensity level of s'); ylabel('P_{s}(s)');

(作者注:其实,直方图均衡有直接的函数,这里只是想按照自己理解的方法去做个均衡出来看看,所以高级一点的库函数基本没有,都用循环来的)

直方图匹配

前面,我们说了直方图的均衡,直方均衡可以得到一个灰度直方图分布平均的图像。但是有一些问题,直方图均衡的结果是唯一的。这是其优点,也是其缺点。优点在于,无需多余的参数,就可以实现对比度的增强。缺点在于,没有参数,对于结果无法调整。举个栗子(输入法君卖萌了╭(╯3╰)╮),一幅很黑的图像,使用直方图均衡的话,这幅图像的直方均衡结果,将使得图像偏白。使用《Digital Image Processing》 Rafael C. Gonzalez / Richard E. Woods 的例子来说,看下图。

如上图所示,直方均衡的结果不是很理想。由直方均衡的结果看来,我们能看到,其实对比原图,原图一些细节已经显露出来了,只要稍加修改,就可以得到很理想的增强结果。为此,直觉告诉我们(不要吐槽这句话,有时候直觉就是那么简单。\(≧▽≦)/),只需要将原图的灰度直方图稍微左移一些即可。但是,直方均衡却是不可调整的,为此,就有了直方图匹配。

对于原图像,其概率分布函数是

其输出也就是直方均衡的结果。为了实现直方图匹配,我们还需要一个函数,也就是我们所期待的概率分布函数。这个概率分布函数的概率分布函数如下所示。

其中,z代表了期望的分布。我们假设如下关系成立。

也就是,我们所期待的直方图分布的概率分布函数与原图像的直方图概率分布函数相等。那么,我们可以利用G()的反函数,我们也就可以得到我们所期待的直方图。

上面的描述可能太过拖沓,我们采用简洁一点的描述。

一. 将原图进行直方图均衡。

二. 假设我们期待的分布,直方均衡的结果与原图直方图均衡的结果一致。利用反函数,还原成我们期待的分布。

所实现的直方图均衡结果如下所示。

根据直方图匹配的结果,我们可以看出,所得出的结果和我们所期待的分布很接近。其结果也和我们的初衷一样,使得原图的直方图稍微左移了一些。所得到的结果比起直方均衡要好得多。

其Matlab代码如下。

%% -------------Histogram Matching----------------- close all; clear all; f = imread('mars_moon_phobos.tif'); f = mat2gray(f,[0 255]); [M,N] = size(f); g = zeros(M,N); r = imhist(f)/(M*N); s = zeros(256,1); for k = 1:1:256 for j = 1:1:k s(k,1) = s(k,1) + r(j); end end for x = 1:1:M for y = 1:1:N g(x,y) = s(uint8(f(x,y)*255)+1,1); end end figure(); subplot(2,2,1); imshow(f); xlabel('a).Original Image'); subplot(2,2,2); h = imhist(f)/(M*N); bar(0:1/255:1,h); axis([0 1 0 0.1]),grid; xlabel('b).The Histogram of a'); subplot(2,2,3); imshow(g); xlabel('c).Histogram Equalization'); subplot(2,2,4); h = imhist(g)/(M*N); bar(0:1/255:1,h); axis([0 1 0 0.1]),grid; xlabel('d).The Histogram of c'); %---------------pz----------------------- r = r'; p = [0:r(1,1)/15:r(1,1) 17*r(1,2:241)]; %p = [0:r(1,1)/15:r(1,1) r(1,2:241)]; %p = [0:55:255 , 255:-25:24 , 24:-0.14:0 , 0:1:15 , 15:-0.285:0]; p = (p/sum(p)); p = p'; r = r'; G = zeros(256,1); for k = 1:1:256 for j = 1:1:k G(k,1) = G(k,1) + p(j); end end G_Negatives = zeros(256,1); Flag = 0; for k = 1:1:256 for j = 1:1:256 if(uint8(G(j,1)*255) == k) G_Negatives(k,1) = (j-1)/255; Flag = 1; end end if(Flag == 0) if(k == 1) G_Negatives(k,1) = 0; else G_Negatives(k,1) = G_Negatives(k-1,1); end end Flag = 0; end z = zeros(M,N); for x = 1:1:M for y = 1:1:N z(x,y) = G_Negatives(uint8(g(x,y)*255)+1,1); end end figure(); subplot(2,2,1); imshow(z); xlabel('a).Histogram Matching'); subplot(2,2,2); h = imhist(z)/(M*N); bar(0:1/255:1,h); axis([0 1 0 .1]),grid; xlabel('b).The Histogram of a'); subplot(2,2,3); x=0:1/255:1; plot(x,p); axis([0,1,0,.1]),grid; xlabel('c).Specifieds Histogram (Normalized)'); subplot(2,2,4); x=0:1/255:1; plot(x,G,x,G_Negatives); axis([0,1,0,1]),grid; axis square; xlabel('Input intensity level'); ylabel('Onput intensity level');

博客地址:zhoufan900428-CSDN博客

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/4 5:58:31

AI如何重塑科研全流程:从文献挖掘到实验优化

1. 项目背景与核心价值实验室里的显微镜旁堆着三摞实验记录本,这是我十年前刚入行时的常态。如今再看同事的工位,取而代之的是一块实时显示实验数据的屏幕和几个正在自动运行的算法模型。这个转变背后,正是AI技术对自然科学研究的重塑——它不…

作者头像 李华
网站建设 2026/11/4 5:58:31

eCAL嵌入式实时通信原理与毫秒级延迟优化实战

1. 项目概述:为什么在嵌入式Linux上较真“毫秒级通信”这件事,真不是炫技你有没有遇到过这样的场景:在某高校实验室调试一个双目视觉IMU融合的移动机器人小车,ROS 2的/camera/image_raw话题一发出来,端到端延迟就飙到8…

作者头像 李华
网站建设 2026/11/4 5:58:21

金融数据服务从零搭建:分层解耦架构与工程实践指南

1. 金融数据服务从零搭建的完整思路1.1 这个项目到底在做什么“financial-services”这个标题看起来很大,实际上它指向的是一个非常具体的工程问题:把分散在各处的金融数据(行情、财报、宏观指标、汇率、利率等)统一采集、清洗、存…

作者头像 李华
网站建设 2026/11/4 5:57:47

Superpowers能力插件框架实战:从安装配置到动态加载与分布式扩展

1. 从“superpowers”这个标题说起:它到底是什么第一次看到“superpowers”这个词,很多人脑子里蹦出来的可能是超级英雄电影里的超能力,或者某个游戏里的技能系统。但如果你是在技术社区、开发者群或者代码托管平台上反复刷到这个词&#xff…

作者头像 李华
网站建设 2026/11/4 5:57:46

CLI-Anything:一种命令行原生的AI智能体交互范式

1. 项目概述:CLI-Anything 不是命令行工具,而是一套“命令行原生”的智能体交互范式你第一次看到CLI-Anything这个名字时,大概率会下意识把它当成一个新出的命令行工具——比如像curl、jq或fzf那样,装完就能用、敲几行命令就出结果…

作者头像 李华
网站建设 2026/11/4 5:57:31

职场女性专题策划:从内容制作到传播的全流程指南

1. 项目背景与核心价值"她力量"是当代社会发展中不可忽视的重要推动力。这个项目旨在通过特定形式,向各行各业的女性从业者致敬,展现她们在不同领域的专业贡献与独特魅力。作为一位长期关注职场发展的观察者,我注意到现代女性在平衡…

作者头像 李华