【数字图像处理】(二)全面! 图像的点运算

图像的点运算

对于一个数字图像处理系统来说,一般可以将处理流程分为3个阶段。在获取原始图像后,首先是图像预处理阶段,第二是特征抽取阶段,最后才是识别分析阶段。预处理阶段尤为重要,这个阶段处理不好则后面的工作根本无法展开。

点运算指的是对图像中的每个像素依次进行同样的灰度变换运算。设r和s分别是输入图像 f ( x , y ) f(x,y) f(x,y)和输出图像 g ( x , y ) g(x,y) g(x,y)在任一点 ( x , y ) (x,y) (x,y)的灰度值,则点运算可以使用下式定义。
在这里插入图片描述
其中, T T T为采用的点运算算子,表示了在原始图像和输出图像之间的某种灰度级映射关系。

点运算常常用于改变图像的灰度范围及分布,是图像数字化及图像显示时常常需要的工具。点运算因其作用的性质有时也被称为对比度增强、对比度拉伸或灰度变换

1 灰度直方图

灰度直方图描述了一幅图像的灰度级统计信息,主要应用于图像分割和图像灰度变换等处理过程中。

1.1 理论基础

从数学上来说,图像直方图描述的是图像的各个灰度级的统计特性,它是图像灰度值的函数,统计一幅图像中各个灰度级出现的次数或概率。有一种特殊的直方图叫作归一化直方图,可以直接反映不同灰度级出现的比率

从图形上来说,灰度直方图是一个二维图,横坐标为图像中各个像素点的灰度级别,纵坐标表示具有各个灰度级别的像素在图像中出现的次数或概率。

灰度直方图的计算是根据其统计定义进行的。图像的灰度直方图是一个离散函数,它表示图像每一灰度级与该灰度级出现频率的对应关系。假设一幅图像的像素总数为 N N N,灰度级总数为 L L L,其中灰度级为 g g g的像素总数为 N g N_g Ng,则这幅数字图像的灰度直方图横坐标即为灰度 g ( 0 ≤ g ≤ L − 1 ) g(0≤g≤L-1) g0gL1,纵坐标则为灰度值出现的次数 N g N_g Ng。实际上,用像素总数N去除以各个灰度值出现的次数 N g N_g Ng即得到各个灰度级出现的概率 P g = N g / N = N g / Σ N g P_g=N_g/N=N_g/ΣN_g Pg=Ng/N=Ng/ΣNg,从而得到归一化的灰度直方图,其纵坐标为概率 P g P_g Pg

1.2 MATLAB实现

MATLAB中的imhist函数可以进行图像的灰度直方图运算,调用语法如下:

imhist(I)
imhist(I,n)
[counts,x]=imhist(...)

参数说明:

  • I为需要计算灰度直方图的图像;
  • n为指定的灰度级数目,如果指定参数n,则会将所有的灰度级均匀分布在n个小区间内,而不是将所有的灰度级全部分开。

返回值:

  • counts为直方图数据向量,counts(i)表示第i个灰度区间中的像素数目;
  • x是保存了对应的灰度小区间的向量。

若调用时不接收这个函数的返回值,则直接显示直方图;在得到这些返回数据之后,也可以使用stem(x, counts)来手工绘制直方图。

(1)一般直方图
下面使用了MATLAB中的一张内置示例图片演示灰度直方图的生成与显示,程序如下。

I=imread('pout.tif');     % 读取图像pout.tif
figure                    % 打开新窗口
imshow(I);title('Source');% 显示原图像
figure                    % 打开新窗口
imhist(I);title('Graph')  % 显示直方图

运行结果:

示例图片 灰度直方图
在这里插入图片描述 在这里插入图片描述

上图为未经归一化的灰度直方图,纵轴表示图像中所有像素取到某一特定灰度值的次数;横轴对应从0到255的所有灰度值,覆盖了uint8存储格式的灰度图像中的所有可能取值

因为相近的灰度值所具有的含义往往是相似的,所以常常没有必要在每个灰度级上都进行统计。下面的命令将0~255总共256个灰度级平均划分为64个长度为4的灰度区间,此时纵轴分别统计每个灰度区间中的像素在图像中的出现次数。其编程代码如下。

imhist(I,64)   % 生成有64个小区间的灰度直方图

运行结果:
在这里插入图片描述

由于要统计落入每个灰度区间内的像素数目,灰度区间常常被形象地称为“收集箱”。在上图所示的直方图中,由于减少了收集箱的数目,使得落入每个收集箱的像素数目有所增加,从而使直方图更具统计特性。收集箱的数目一般设为2的整数次幂,以保证可以无需圆整。

(2)归一化直方图
在imhist函数的返回值中,counts保存了落入每个区间的像素的个数,通过计算counts与图像中像素总数的商可以得到归一化的直方图。

I=imread('pout.tif');        % 读取图像pout.tif
figure                       % 打开新窗口
[M,N]=size(I);               % 图像大小
[counts,x]=imhist(I,32);     % 32个小区间的灰度直方图
counts=counts/(M*N);         % 计算归一化灰度直方图各区间的值
stem(x,counts);              % 绘制归一化直方图

在这里插入图片描述

分析图像的灰度直方图往往可以得到很多有效的信息。下面一系列灰度直方图上,可以很直观地看出图像的亮度和对比度特征。实际上,直方图的峰值位置说明了图像总体上的亮暗:如果图像较亮,则直方图的峰值出现在直方图的较右部分;如果图像较暗,则直方图的峰值出现在直方图的较左部分,从而造成暗部细节难以分辨。如果直方图中只有中间某一小段非零值,则这张图像的对比度较低;反之,如果直方图的非零值分布很宽而且比较均匀,则图像的对比度较高

在这里插入图片描述 在这里插入图片描述
在这里插入图片描述 在这里插入图片描述

2 灰度的线性变换

2.1 理论基础

线性灰度变换函数 f ( x ) f(x) f(x)是一个一维线性函数。
在这里插入图片描述

式中,参数 f A f_A fA为线性函数的斜率, f B f_B fB为线性函数在 y y y轴的截距, D A D_A DA表示输入图像的灰度, D B D_B DB表示输出图像的灰度。

  • f A > 1 f_A>1 fA1时,输出图像的对比度将增大;当 f A < 1 f_A<1 fA1时,输出图像的对比度将减小。

  • f A = 1 f_A=1 fA=1 f B ≠ 0 f_B≠0 fB=0时,操作仅使所有的像素的灰度值上移或下移,其效果是使整个图像更暗或更亮;如 f A < 0 f_A<0 fA0,暗区域将变亮,亮区域将变暗。这种线性改变亮度的变换可能由于像素亮度达到饱和(小于0或超过255)从而丢失一部分细节。

  • 特殊情况下,当 f A = 1 , f B = 0 f_A=1, f_B=0 fA=1,fB=0时,输出图像与输入图像相同;当 f A = − 1 , f B = 255 f_A=-1,f_B=255 fA=1,fB=255时,输出图像的灰度正好反转。灰度反转处理适用于增强暗色图像中的亮度较大的细节部分,这也是由人的视觉特性决定的。

线性变换的示意图如下图所示
在这里插入图片描述

2.2 MATLAB程序的实现

用MATLAB对图像执行线性变换无需专门的函数:

I=imread('coins.png');
I=im2double(I);          % 转换数据类型
[M,N]=size(I);
%% 原图像
figure(1)
imshow(I)
title('原图像')
figure(2)
[H,x]=imhist(O,64);
stem(x,(H/(M*N)), '.');        % 显示原图像直方图
title('原图像')
%% 增加对比度
Fa=2;Fb=-55;
O=Fa.*I+Fb/255;
figure(3)
subplot(2,2,1);
imshow(O);
title('Fa=2 Fb=-55 增加对比度');
figure(4)
subplot(2,2,1);
[H,x]=imhist(O,64);
stem(x,(H/(M*N)), '.');   
title('Fa=2 Fb=-55 增加对比度');
%% 减小对比度
Fa=0.5;Fb=-55;
O=Fa.*I+Fb/255;
figure(3)
subplot(2,2,2)
imshow(O)
title('Fa=0.5 Fb=-55 减小对比度')
figure(4)
subplot(2,2,2)
[H,x]=imhist(O,64);
stem(x,(H/(M*N)), '.');  
title('Fa=0.5 Fb=-55 减小对比度')
%% 线性增加亮度
Fa=1;Fb=55;
O=Fa.*I+Fb/255;
figure(3)
subplot(2,2,3)
imshow(O)
title('Fa=1 Fb=55 线性平移增加亮度')
figure(4)
subplot(2,2,3)
[H,x]=imhist(O,64);
stem(x,(H/(M*N)),'.');
title('Fa=1 Fb=55 线性平移增加亮度')
%% 线性增加亮度
Fa=-1;Fb=255;
O=Fa.*I+Fb/255;
figure(3)
subplot(2,2,4)
imshow(O)
title('Fa=-1 Fb=255 反相显示')
figure(4)
subplot(2,2,4)
[H,x]=imhist(O,64);
stem(x,(H/(M*N)),'.');
title('Fa=-1 Fb=255 反相显示')
原图像 归一化直方图
在这里插入图片描述 在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

从结果图可以看到,改变图像的对比度是对直方图的缩放与平移,改变图像的亮度则只是平移直方图在横轴上的位置,而反相则是将直方图水平镜像。

3 灰度对数变换

3.1 理论基础

对数变换的一般表达式如下

在这里插入图片描述
其中, c c c为尺度比例常数, s s s为源灰度值, t t t为变换后的目标灰度值。在如图3.8所示的对数曲线上,函数自变量为低值时,曲线的斜率很高;自变量为高值时,曲线斜率变小。
在这里插入图片描述

由对数函数曲线可知,这种变换可以增强一幅图像中较暗部分的细节,从而可用来扩展被压缩的高值图像中的较暗像素,因此对数变换被广泛地应用于频谱图像的显示中。一个典型的应用是傅里叶频谱(,其动态范围可能宽达 0 ~ 1 0 6 0~10^6 0106。直接显示频谱时,图像显示设备的动态范围往往不能满足要求,从而丢失了大量的暗部细节。而在使用对数变换之后,图像的动态范围被合理地非线性压缩,从而可以清晰地显示。

3.2 MATLAB实现

对数变换不需要专门的图像处理函数,可以使用如下数学函数实现对图像I的对数变换
在这里插入图片描述

下面的程序比较了对傅里叶频谱图像进行对数变换前后的效果(不必关注代码中生成傅里叶频谱的部分)

I=imread('coins.png');
F=fft2(im2double(I));  % 计算频谱
F=fftshift(F);
F=abs(F);
T=log(F+1);
subplot(1,2,1);
imshow(F,[]);
title('未经变换的频谱')
subplot(1,2,2)
imshow(T,[])
title('对数变换后')

结果:
在这里插入图片描述

在结果图中未经变换的频谱可见,图像中心绝对高灰度值的存在压缩了低灰度部分的动态范围,从而无法在显示时表现出细节;而经过对数灰度处理的图像,其低灰度区域对比度将会增加,暗部细节被增强。

4 伽玛变换

伽玛变换又名指数变换或幂次变换,是另一种常用的灰度非线性变换。

4.1 理论基础

伽玛变换的一般表达式如下
在这里插入图片描述

其中, x x x与y的取值范围均为 [ 0 , 1 ] [0,1] [0,1], e s p esp esp为补偿系数, γ γ γ则为伽玛系数。与对数变换不同,伽玛变换可以根据 γ γ γ不同取值选择性地增强低灰度区域的对比度或是高灰度区域的对比度

γ γ γ是图像灰度校正中非常重要的一个参数,其取值决定了输入图像和输出图像之间的灰度映射方式,即决定了是增强低灰度(阴影区域)还是增强高灰度(高亮区域)。

  • γ > 1 γ>1 γ1时,图像的高灰度区域对比度得到增强。
  • γ < 1 γ<1 γ1时,图像的低灰度区域对比度得到增强。
  • γ = 1 γ=1 γ=1时,这一灰度变换是线性的,即不改变原图像。

伽玛变换的映射关系如图3.10所示。在进行变换时,通常需要将0~255的灰度动态范围首先变换到0~1的动态范围,执行伽玛变换后再恢复原动态范围。
在这里插入图片描述

4.2 MATLAB编程实现

MATLAB中为使用者提供了实现灰度变换的基本工具imadjust,它有着非常广泛的用途,其调用的一般语法如下
在这里插入图片描述
该函数将输入图像 I I I中从low_inhigh_in之间的值映射到输出图像J的low_outhigh_out之间的值,low_in以下和high_in以上的值则被裁减掉。

参数说明:

  • [low_in, high_in]和[low_out, high_out]确定源灰度范围到目标灰度范围的映射,在给定[low_in, high_in][low_out, high_out]时,需要按照double类型给定,即取值范围在0~1之间;
  • 使[low_in, high_in][low_out, high_out]为空([ ]),相当于默认值[0 1],若high_out小于low_out,则输出图像 J J J的亮度将会反转;
  • 参数gamma指定了变换曲线的形状(类似于图3.10中的形状),其默认值为1,表示线性映射。若gamma<1,则映射被加权至更高的输出值;若gamma>1,则映射被加权至更低的输出值;
  • gamma取1时,通过设定合适的[low_in,high_in][low_out, high_out]的取值,imadjust函数可以实现灰度线性变换;
  • 而当[low_in, high_in][low_out,high_out]的取值均为[0, 1]时,以不同的gamma调用imadjust函数则可以实现图3.10中所示的各种伽玛变换。
  • I I I为输入图像,可以是uint8, uint16或者double类型。

返回值:

  • J J J为经过处理的图像,与I具有同样的类型。

imadjust函数用于Gamma变换的调用语法如下。
在这里插入图片描述
gamma分别取不同值时的伽玛变换的程序实现

I=imread('pout.tif');
%gamma取0.75
subplot(1,4,1)
imshow(imadjust(I,[],[],0.75));
title('gamma:0.75')
%gamma取1
subplot(1,4,2)
imshow(imadjust(I,[],[],1));
title('gamma:1')
%gamma取1.5
subplot(1,4,3)
imshow(imadjust(I,[],[],1.5));
title('gamma:1.5')
%原图像
subplot(1,4,4)
imshow(I);
title('原图像')

运行结果

在这里插入图片描述

可以看出不同伽玛因子给图像的整体明暗程度带来的变化,以及对图像暗部和亮部细节清晰度的影响。当伽玛因子取1的时候,图像没有任何改变。

下面的程序生成了各个图像的灰度直方图。

I=imread('pout.tif');
%gamma取0.75
subplot(1,4,1)
imhist(imadjust(I,[],[],0.75));
title('gamma:0.75')
%gamma取1
subplot(1,4,2)
imhist(imadjust(I,[],[],1));
title('gamma:1')
%gamma取1.5
subplot(1,4,3)
imhist(imadjust(I,[],[],1.5));
title('gamma:1.5')
%原图像
subplot(1,4,4)
imhist(I);
title('原图像')

结果:
在这里插入图片描述

注意图中直方图非零区间位置的变化,以及这些变化给图像带来的影响。由于伽玛变换并不是线性变换,所以它不仅可以改变图像的对比度,还能够增强细节,从而带来整体图像效果的增强和改善。

5 灰度阈值变换

灰度阈值变换可以将一幅灰度图像转换成黑白的二值图像。用户指定一个起到分界线作用的灰度值,如果图像中某像素的灰度值小于该灰度值,则将该像素的灰度值设置为0,否则设置为255,这个起到分界线作用的灰度值称为阈值,灰度的阈值变换也常被称为阈值化或二值化。

5.1 理论基础

灰度阈值变换的函数表达式如下
在这里插入图片描述
其中, T T T为指定的阈值。

灰度阈值变换的示意图如下
在这里插入图片描述
灰度阈值变换的用途和可扩展性都非常广泛。通过将一幅灰度图像转为二值图像,可以将图像内容直接划分为读者关心的和不关心的两个部分,从而在复杂背景中直接提取出感兴趣的目标。因此它是图像分割的重要手段之一

5.2 MATLAB编程实现

MATLAB中和阈值变换有关的函数主要有两个——im2bwgraythresh
1.函数im2bw可用于实现阈值变换,调用语法如下。
在这里插入图片描述
参数说明:

  • 参数I为需要二值化的输入图像;
  • 参数level给出了具体的变换阈值,它是一个0~1之间的双精度浮点数,例如输入图像I为灰度范围在0~255之间的uint8图像,如果level=0.5则对应于分割阈值为128。

返回值:

  • BW为二值化后的图像。

2.函数graythresh可以自适应地确定变换所用的“最优”阈值,调用形式如下。
在这里插入图片描述
参数说明:

  • 参数I为需要计算阈值的输入图像。

返回值:

  • thresh是计算得到的最优化阈值

灰度阈值level既可以由经验确定,也可以使用graythresh()函数来自适应地确定。
下面的程序分别展示了如何利用graythresh函数获得的阈值和自行设定的阈值进行阈值变换

I=imread('rice.png');
thresh=graythresh(I);    % 自适应确定阈值
bw1=im2bw(I,thresh);     % 二值化
bw2=im2bw(I,130/255);    %130为阈值实现二值化,注意要将此阈值转换至[0,1]之间
subplot(1,3,1);imshow(I);title('原图像')
subplot(1,3,2);imshow(bw1);title('自适应选择阈值')
subplot(1,3,3);imshow(bw2);title('阈值130')

结果:
在这里插入图片描述

6 分段线性变换

6.1 理论基础

利用分段线性变换函数来增强图像对比度的方法实际上是增强原图各部分的反差,即增强输入图像中感兴趣的灰度区域,相对抑制那些不感兴趣的灰度区域。分段线性函数的主要优势在于它的形式可任意合成,而其缺点是需要更多的用户输入。
分段线性变换的函数形式如下
在这里插入图片描述
式中最重要的参数是[x1, x2][y1, y2]。根据算法函数的描述,读者可以发现,其中x1x2是给出需要转换的灰度范围,y1y2参数决定线性变换的斜率。

x1, x2, y1, y2分别取不同的值的组合时,可得到不同的变换效果。例如以下情况。

  • 如果 x 1 = y 1 , x 2 = y 2 x_1=y_1, x_2=y_2 x1=y1,x2=y2,则 f ( x ) f(x) f(x)为1条斜率为1的直线,增强图像将和原图像相同。
  • 如果 x 1 = x 2 , y 1 = 0 , y 2 = 255 x_1=x_2, y_1=0, y_2=255 x1=x2,y1=0,y2=255,则增强图像只剩下2个灰度等级,分段线性变换起到了阈值化的效果,此时的对比度最大,但是细节丢失最多。
  • x 1 、 x 2 、 y 1 、 y 2 x_1、x_2、y_1、y_2 x1x2y1y2取一般值时的分段线性变换函数的图形如下图所示。

在这里插入图片描述

分段的灰度拉伸可以更加灵活地控制输出灰度直方图的分布,可以有选择地拉伸某段灰度区间,以改善输出图像。如果一幅图像灰度集中在较暗的区域而导致图像偏暗,可以用灰度拉伸功能来扩展(斜率>1)物体的灰度区间以改善图像;同样,如果图像灰度集中在较亮的区域而导致图像偏亮,也可以用灰度拉伸功能来压缩(斜率<1)物体灰度区间以改善图像质量

灰度拉伸是通过控制输出图像中灰度级的展开程度来达到控制对比度的效果的。一般情况下都限制 x 1 < x 2 , y 1 < y 2 x_1<x_2, y_1<y_2 x1x2,y1y2,从而保证函数是单调递增的,以避免造成处理过的图像中灰度级发生颠倒。

6.2 MATLAB编程实现

使用作者自己编写的MATLAB图像处理函数,imgrayscaling()imgrayscaling()具有很好的兼容性,它可以处理灰度、彩色、索引等不同类型,以及double、uint8等不同存储方式的图像。

(1)输入的处理
为了可以使用可变个数的参数,imgrayscaling()函数中使用了细胞数组,将函数的输入参数整体看作一个细胞数组。为此需要编写一个parse_inputs()函数来解析该细胞数组的内容,该函数的返回值为imgrayscaling()中所有可能由用户初始化的参数值。
parse_inputs()函数的完整实现如下,其中对未知个数的输入使用了参数varargin来表示。

function [A,map,x1,x2,y1,y2] = parse_inputs(varargin)
% 分析输入参数个数和有效性的函数
% A 输入图像,RGB图(3D),灰度图(2D),或者索引图(X)
% map 索引图调色板(:,3% [x1,x2]参数组1,曲线中两个转折点的横坐标
% [y1,y2]参数组2,曲线中两个转折点的纵坐标
% 首先建立一个空的map变量,以免后面调用isempty(map)时出错
map=[];
% IPTCHECKNARGIN(LOW,HIGH,NUM_INPUTS,FUNC_NAME)检查输入参数
%是否在LOW和HIGH所指定的范围内,如果不再范围内,则此函数给出一
%个格式化的错误信息
iptchecknargin(3,4,nargin,mfilename);
% IPTCHECKINPUT(A,CLASSES,ATTRIBUTES,FUNC_NAME,VAR_NAME,ARG_POS)
% 检查给定矩阵A中的元素是否属于给定的类型列表。如果存在元素不属于给定
% 类型,则给出一个错误的信息
iptcheckinput(varargin{
    
    1},{
    
    'uint8','uint16','int16','double'},...
 {
    
    'real','nonsparse'},mfilename,'I,X or RGB',1);
switch nargin
    case 3  % 可能是imgrayscaling(I,[x1,x2],[y1,y2])imgrayscaling(RGB,[x1,x2],[y1,y2]) 
        A=varargin{
    
    1};
        x1=varargin{
    
    2}(1);
        x2=varargin{
    
    2}(2);
        y1=varargin{
    
    3}(1);
        y2=varargin{
    
    3}(2);
    case 4  % imgrayscaling(X,map,[x1,x2],[y1,y2])
        A=varargin{
    
    1};
        map=varargin{
    
    2};
        x1=varargin{
    
    2}(1);
        x2=varargin{
    
    2}(2);
        y1=varargin{
    
    3}(1);
        y2=varargin{
    
    3}(2);
end
% 检查输入参数的有效性
% 检查RGB数组
if(ndims(A)==3) && (size(A,3)~=3)
    msg=sprintf('%s:真彩色图像应当使用一个M-N-3维度的数组',upper(mfilename));
    eid=sprint('Images:%s:true Color RGB Image Must Be M by N by 3',mfilename);
    error(eid,'%s',msg);
end
if ~isempty(map)
    if (size(map,2)~=3) || ndims(map)>2
        msg1 = sprintf('%s:matix',...
            upper(mfilename));
        msg2 = 'three 3 parallel';
        eid = sprintf('Images:%s:inColormapMustBe2Dwith3Cols',mfilename);
        error(eid,'%s %s',msg1,msg2);
    elseif (min(map(:))<0) || (max(map(:))>1)
        msg1 = sprintf('%s',upper(mfilename));
        msg2 = 'between 0 and 1';
        eid = sprintf('Images:%s:colormapValsMustBe0tol',mfilename);
        error(eid,'%s %s',msg1,msg2);
    end
end
if isa(A,'int16')
    A = int16tounit16(A);
end
end
function  out = imgrayscaling(varargin)
% 执行灰度拉伸功能
% 语法:
% out=imgrayscaling(I,[x1,x2],[y1,y2]);
% out=imgrayscaling(X,map,[x1,x2],[y1,y2]);
% out=imgrayscaling(RGB,[x1,x2],[y1,y2]);
% 这个函数提供灰度拉伸功能,输入图像应当是灰度图像,但
% 如果提供的不是灰度图像的话,函数会自动将图像转化为灰度图像
% x1,x2,y1,y2应当使用双精度
% 类型存储,图像矩阵可以使用任何MATLAVB支持的类型存储
[ A, map, x1, x2, y1, y2 ]= parse_inputs(varargin{
    
    :});
range = getrangefromclass(A);
range = range(2);
%判断图像是RGB还是GRAY灰度图,如果不是灰度图,则需要执行转换
if  ndims(A)==3                        %A矩阵为3维,则是RGB图像
       A = rgb2gray(A);
elseif   ~isempty(map)                 %map变量为非空,则索引图像
       A = ind2gray(A,map);
end                                   %对灰度图无需转换
[M,N]=size(A);
Img= im2double(A);
out=zeros(M,N);
for i=1:M
   for j=1:N
        if Img(i,j)<x1
             out(i,j)=y1 * Img(i,j) / x1;
        elseif Img(i,j)>x2
              out(i,j)=(Img(i,j)-x2) * (range-y2) / (range-x2) + y2;
        else
              out(i,j)=(Img(i,j)-x1) * (y2-y1) / (x2-x1) + y1;
        end
   end
end
if isa(A,'uint8')             %将输出图像的格式转化为与输入图像相同
     out = im2uint8(out);
elseif isa(A,'uint16')
     out = im2uint16(out);    %其他情况,就双精度浮点型图像
end
%输出
if nargout==0                    %如果没有提供参数接受返回值
     imshow(out);
     return;
end
I = imread('coins.png');
J1 = imgrayscaling(I,[0.3,0.7],[0.15,0.85]);
figure(1)
subplot(1,3,1)
imshow(J1,[]);
title('[x1,x2]=[0.3,0.7] [y1,y2]=[0.15,0.85]')
J2 = imgrayscaling(I,[0.15,0.85],[0.3,0.7]);
figure(1)
subplot(1,3,2)
imshow(J2,[]);
title('[x1,x2]=[0.15,0.85] [y1,y2]=[0.3,0.7]')
subplot(1,3,3)
imshow(I,[]);
title('原图像')

结果:
在这里插入图片描述

I = imread('coins.png');
J1 = imgrayscaling(I,[0.3,0.7],[0.15,0.85]);
figure(1)
subplot(1,3,1)
imhist(J1);
title('[x1,x2]=[0.3,0.7] [y1,y2]=[0.15,0.85]')
J2 = imgrayscaling(I,[0.15,0.85],[0.3,0.7]);
figure(1)
subplot(1,3,2)
imhist(J2);
title('[x1,x2]=[0.15,0.85] [y1,y2]=[0.3,0.7]')
subplot(1,3,3)
imhist(I);
title('原图像')

结果:
在这里插入图片描述

从图中可以看到第一组参数让图像灰度直方图上的非零区域扩展,而第二组参数让图像的灰度直方图非零区域压缩,这给目标图像带来了截然不同的效果。第一幅图像中的细节更加清晰,而第二幅图像更加柔和。

7 直方图均衡化

7.1 理论基础

直方图均衡化又称为灰度均衡化,是指通过某种灰度映射使输入图像转换为在每一灰度级上都有近似相同的像素点数的输出图像(即输出的直方图是均匀的)。在经过均衡化处理后的图像中,像素将占有尽可能多的灰度级并且分布均匀。因此,这样的图像将具有较高的对比度和较大的动态范围。

为了便于分析,首先考虑灰度范围为0~1且连续的情况。此时图像的归一化直方图即为概率密度函数(PDF)。
在这里插入图片描述
由概率密度函数的性质,有以下关系
在这里插入图片描述
设转换前图像的概率密度函数为 p r ( r ) p_r(r) pr(r),转换后图像的概率密度函数为 p s ( s ) p_s(s) ps(s),转换函数(灰度映射关系)为 s = f ( r ) s=f(r) s=f(r)。由概率论知识可得下式
在这里插入图片描述

这样,如果想使转换后图像的概率密度函数: p s ( S ) = 1 , 0 ≤ S ≤ 1 p_s(S)=1,0≤S≤1 ps(S)=1,0S1(即直方图为均匀的),则必须满足下式
在这里插入图片描述

等式两边对r积分,可得下式
在这里插入图片描述

该式称为图像的累积分布函数(CDF)。该式是在灰度取值在[0, 1]范围内的情况下推导出来的,对于[0,255]的情况,只要乘以最大灰度值 D m a x D_{max} Dmax(对于灰度图就是255)即可。此时灰度均衡的转换公式如下
在这里插入图片描述
其中, D B D_B DB为转换后的灰度值, D A D_A DA为转换前的灰度值。
而对于离散灰度级,相应的转换公式应如下
在这里插入图片描述

式中 H i H_i Hi为第 i i i级灰度的像素个数, A 0 A_0 A0为图像的面积,即像素总数。

式中的变换函数 f f f是一个单调增加的函数,这保证了在输出图像中不会出现灰度反转的情况(变换后相对灰度不变),从而能够防止在变换中改变图像的实质,以至于影响对图像的识别和判读。
这里还需要说明一点,对于上式的离散变换,通常无法再像连续变换时那样可以得到严格的均匀概率密度函数 ( p s ( S ) = 1 , 0 ≤ S ≤ 1 ) (p_s(S)=1,0≤S≤1) ps(S)=1,0S1。但无论如何,该式的应用有展开输入图像直方图的一般趋势,可使得均衡化过的图像灰度级具有更大的范围,从而得到近似均匀的直方图。

7.2 MATLAB编程实现

MATLAB图像处理工具箱提供了用于直方图均衡化的函数histeq(),调用语法如下
在这里插入图片描述
参数说明:

  • I是原始图像

返回值:

  • J是经过直方图均衡化的输出图像;
  • T是变换矩阵

图像易受光照、视角、方位、噪声等的影响。在这些因素的作用下,同一类图像的不同变形体之间的差距有时大于该类图像与另一类图像之间的差距,这就给图像识别/分类带来了困扰。图像归一化就是将图像转换成唯一的标准形式以抵抗各种变换,从而可消除同类图像不同变形体之间的外观差异。

当图像归一化用于消除灰度因素(光照等)造成的图像外观变化时,称为(图像)灰度归一化。下面将利用直方图均衡化技术实现图像的灰度归一化。

I=imread('pout.tif');
I=im2double(I);
%% 对于对比度变大的图像
I1=2*I-55/255;
subplot(4,4,1);
imshow(I1);
title('对比度变大的图像')
subplot(4,4,2)
imhist(I1);
subplot(4,4,3)
imshow(histeq(I1));
subplot(4,4,4)
imhist(histeq(I1));
%% 对于对比度变小的图像
I2=0.5*I+55/255;
subplot(4,4,5);
imshow(I2);
title('对比度变小的图像')
subplot(4,4,6)
imhist(I2);
subplot(4,4,7)
imshow(histeq(I2));
subplot(4,4,8)
imhist(histeq(I2));
%% 对于线性增加亮度的图像
I3=I+55/255;
subplot(4,4,9);
imshow(I3);
title('线性增加亮度的图像')
subplot(4,4,10)
imhist(I3);
subplot(4,4,11)
imshow(histeq(I3));
subplot(4,4,12)
imhist(histeq(I3));
%% 对于线性减少亮度的图像
I4=I-55/255;
subplot(4,4,13);
imshow(I4);
title('线性减少亮度的图像')
subplot(4,4,14)
imhist(I4);
subplot(4,4,15)
imshow(histeq(I4));
subplot(4,4,16)
imhist(histeq(I4));

结果:

在这里插入图片描述

从图中可以发现,将直方图均衡化算法应用于左侧的亮度、对比度不同的各个图像后,得到了右侧直方图大致相同的图像,这体现了直方图均衡化作为强大自适应性的增强工具的作用。当原始图像的直方图不同而图像结构性内容相同时,直方图均衡化所得到的结果在视觉上几乎是完全一致的。这对于在进行图像分析和比较之前将图像转化为统一的形式是十分有益的。

从灰度直方图的意义上说,如果一幅图像的直方图非零范围占有所有可能的灰度级并且在这些灰度级上均匀分布,那么这幅图像的对比度较高,而且灰度色调较为丰富,从而易于进行判读。直方图均衡化算法恰恰能满足这一要求。

8 直方图规定化(匹配)

直方图均衡化算法可以自动确定灰度变换函数,从而获得具有均匀直方图的输出图像。它主要用于增强动态范围偏小的图像对比度,丰富图像的灰度级。这种方法的优点是操作简单,且结果可以预知,当图像需要自动增强时是一种不错的选择。

但有时我们希望可以对变换过程加以控制,如能够人为地修正直方图的形状,或者说是获得具有指定直方图的输出图像,这样就可以有选择地增强某个灰度范围内的对比度或使图像灰度值满足某种特定的分布。这种用于产生具有特定直方图的图像的方法叫作直方图规定化,或直方图匹配。

8.1 理论基础

直方图规定化是在运用均衡化原理的基础上,通过建立原始图像和期望图像(待匹配直方图的图像)之间的关系,使原始图像的直方图匹配特定的形状,从而弥补了直方图均衡化不具备交互作用的特性。
其匹配原理是先对原始的图像均衡化,转换公式如下
在这里插入图片描述
同时对待匹配直方图的图像进行均衡化处理,公式如下
在这里插入图片描述
由于都是均衡化,故可令 s ≈ v s\approx v sv,则有如下关系
在这里插入图片描述

于是可以按照如下的步骤由输入图像得到一个具有规定概率密度函数的图像。
(1) 根据式
在这里插入图片描述
得到变换关系 f ( r ) f(r) f(r)

(2) 根据式
在这里插入图片描述
得到变换关系 g ( z ) g(z) g(z)

(3) 求得反变换函数 g − 1 ( s ) g^{-1}(s) g1(s)
(4) 对输入图像所有像素应用式
在这里插入图片描述

中的变换,从而得到输出图像。

当然,在实际计算中利用的是上述公式的离散形式,这样就不必去关心函数 f ( r ) 、 g ( z ) f(r)、g(z) f(r)g(z)以及反变换函数 g − 1 ( s ) g^{-1}(s) g1(s)具体的解析形式,而可以直接将它们作为映射表处理了。其中, f ( r ) f(r) f(r)为输入图像均衡化的离散灰度级映射关系, g ( z ) g(z) g(z)为标准图像均衡化的离散灰度级映射关系,而 g − 1 ( s ) g^{-1}(s) g1(s)则是标准图像均衡化的逆映射关系,它给出了从经过均衡化处理的标准化图像到原标准图像的离散灰度映射,相当于均衡化处理的逆过程。

8.2 MATLAB编程实现

Histeq()函数不仅可以用于直方图均衡化,也可以用于直方图规定化,此时需要提供可选参数hgram。调用语法如下
在这里插入图片描述
函数会将原始图像I处理成一幅以用户指定向量hgram作为直方图的图像。
参数hgram的分量数目即为直方图的收集箱数目。对于double型图像,hgram的元素取值范围是[0,1];对于uint8型图像取值范围为[0, 255];对于uint16型图像取值范围则为[0, 65535]。其他参数的意义与在直方图均衡化中的相同

例子:

I=imread('pout.tif'); % 原图像
I1=imread('coins.png');  % 要匹配直方图的图像
I2=imread('circuit.tif');  % 要匹配直方图的图像
% 计算直方图
[hgram1,x]=imhist(I1);
[hgram2,x]=imhist(I2);
% 执行直方图均衡化
J1=histeq(I,hgram1);
J2=histeq(I,hgram2);
subplot(2,3,1)
imshow(I),title('原图')
subplot(2,3,2)
imshow(I1),title('标准图1')
subplot(2,3,3)
imshow(I2),title('标准图2')
subplot(2,3,5)
imshow(J1),title('规定化到1')
subplot(2,3,6)
imshow(J2),title('规定化到2')
figure;
subplot(2,3,1)
imhist(I),title('原图')
subplot(2,3,2)
imhist(I1),title('标准图1')
subplot(2,3,3)
imhist(I2),title('标准图2')
subplot(2,3,5)
imhist(J1),title('规定化到1')
subplot(2,3,6)
imhist(J2),title('规定化到2')

结果:

在这里插入图片描述

在这里插入图片描述

直方图规定化本质上是一种拟合过程,因此变换得到的直方图与标准目标图像的直方图并不会完全一致。然而即使只是相似的拟合,仍然使规定化的图像在亮度与对比度上具有类似标准图像的特性,这正是直方图规定化的目的所在

内容来源:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44378835/article/details/108940192