冈萨雷斯-数字图像处理笔记(一)

原创文章,转载请留言,注明出处

这学期正在修一门机器视觉的课,老师指定了一些参考书,我在图书馆找到了其中一本,便借来学习,到现在为止,已经自学完前三章。为了巩固习得的知识,我用MATLAB对其中一些重要的图像处理函数进行实现。

图像反转

对于灰度图像,将其每个像素点的灰度x变为255-x,有点像逻辑运算的取反。这种处理尤其适用于增强嵌入于图像暗色区域的白色或灰色细节,特别是当黑色面积占主导地位时。这个几乎算的上是白痴函数了,不过还是贴上,以免过后忘记。

function [ output_img ] = Reverse_img( input_img )        %图像反转

output_img(:,:) = 255 - input_img(:,:);

end

幂次变换

幂函数表达式为:y=c*x^a ,对不同的a图像的形状不同(见下图 c=1)

幂函数对图像进行变换可以将窄带暗值映射到宽带输出,也可以将宽带亮值映射到窄带输出,变换的具体类型和程度由a值决定。当 c=1 时,图像可以在0-255灰度之间直接转换,当c~=1 时,映射的结果应相对255做归一化处理。

用于图像获取,打印和显示的各种装置根据幂次规律产生响应,也就是说这图像经过这些装置后变为了原来的幂次。这一转换中的幂指数叫做伽马值,用于修正幂次响应现象的过程称为伽马校正。例如,阴极射线管装置的电压-强度响应是一个指数变化为1.8-2.5的幂函数,导致图像暗带拉伸,所以需要对这一结果进行伽马校正,即进行s=y^(1/2.5)的变换(假设伽马值为2.5)

代码很简单,如下:

function [ output_img ] = Power_img( input_img , Index )        %对图像进行幂次变换
output_img = (input_img/255).^Index;
end

直方图均衡化

通俗的说,直方图均衡化是将让灰度图像中的每一个灰度值在图像中以相同的概率出现,有效地用于图像增强。

实现的过程并不复杂,首先计算图像中每一个灰度数值的像素数目,然后根据这一结果对每一个灰度数组计算出不大于它本身的像素数目,最后将上一步的结果全都除以图像的像素总数,即得到double类型的灰度,再将原图像的灰度变为它对应的double型灰度即为所求结果。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function [ output_img ] = HisEqu_img( input_img )	%直方图均衡化
gray_rank=zeros(2,256);
x=size(input_img,1);
y=size(input_img,2);
for i=1:x
for j=1:y
gray_rank(1,input_img(i,j)+1)=gray_rank(1,input_img(i,j)+1)+1;
end
end
gray_rank(2,1)=gray_rank(1,1);
for i=2:256
gray_rank(2,i)=gray_rank(2,i-1)+gray_rank(1,i);
end
output_img=zeros(x,y);
gray_rank=double(gray_rank);
for i=1:x
for j=1:y
output_img(i,j)=gray_rank(2,input_img(i,j)+1)/x/y;
end
end
end

Note:2016-3-7

MATLAB提供了直方图均衡化的函数 histeq(img)以及显示图像直方图的函数imhist(img),下面显示了MATLAB帮助文档中处理前后的图像,明显能够看出,均衡化后的轮胎很多细节得到了增强。

图像局部增强

以上讨论的都是对作为一个整体的图像进行增强的方法,但是如果想对含有一部分不清晰的细节进行局部增强,单纯的使用直方图均衡化可能难以达到要求。

因此,下面介绍一种局部直方图增强的方法。

设想,一个图像的某一部分灰度值过于集中,但是却有不可忽略的细节,那么如果想筛选出这部分子图像,考虑图像的均值和方差(为什么考虑均值? 这里可以将待处理的部分分为黑背景,白细节和白背景,黑细节,第一节提到图像反转就可以将这两种情况归为一种,所以这里规定暗背景,浅细节)。若均值小,说明子图像可以作为增强的候选;若方差小(但大于某一阈值),说明子图像细节模糊,则确定应该对子图像进行增强,也就是上一节介绍的直方图均衡化。均值与方差的计算公式如下:

s为一确定大小的邻域,g为(x,y)处图像的灰度,p(g)为灰度值对应的领域直方图均衡化的分量

增强函数为:

D为全局标准差,M为全局灰度均值,k,E为自定义参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function [ output_img] = PartialImpro_img(input_img )	%局部图像增强
k0=0.4;
E=4;
k1=0.02;
k2=0.4;
output_img=input_img;
x1=size(input_img,1);
y1=size(input_img,2);
Mxy=zeros(x1,y1); %邻域均值
thegma=zeros(x1,y1); %邻域方差
near=int32((x1+y1)/200); %邻域正方形半径
aver_gray=sum(sum(input_img))/x1/y1; %全局平均灰度
Dg=0;
for i=1:x1
for j=1:y1
Dg=Dg+(input_img(i,j)-aver_gray)^2;
end
end %计算全局方差
Dg=sqrt(double(Dg));
temp1=zeros(2*near-1,2*near-1);
for i=near:2*near-1:x1-near+1
for j=near:2*near-1:y1-near+1
temp1=HisEqu_img(input_img(i-near+1:i+near-1,j-near+1:j+near-1));
temp2=double(temp1).*double(input_img(i-near+1:i+near-1,j-near+1:j+near-1));
Mxy(i,j)=sum(sum(temp2));
for k=i-near+1:i+near-1
for l=j-near+1:j+near-1
thegma(i,j)=thegma(i,j)+(input_img(k,l)-Mxy(i,j))^2*temp1(k-i+near,l-j+near);
end
end
if Mxy(i,j)<=aver_gray*k0 && sqrt(thegma(i,j))<=k2*Dg && sqrt(thegma(i,j))>=k1*Dg
output_img=E*input_img(i,j);
end
end
end
end

空间滤波

要想搞清楚滤波的原理,首先要从理解卷积开始。简而言之,卷积反映的是一个函数在另一个函数上移动时重叠部分的量。 在图像处理中,卷积用求和来代替积分,我们把这种对图像进行卷积的过程称为滤波,连续函数卷积的激励函数在图像处理中对应为‘掩模’,即33 或 55 之类的矩阵。对图像进行滤波的操作是,对整个图像进行遍历,每次将掩模矩阵与等大的像素矩阵对应元素相乘,将所得矩阵加和即得每个位置的灰度值。

MATLAB提供了二维卷积的函数

p = conv2(A,B); % B为卷积矩阵,A为待卷积矩阵,注意数据类型必须为double或single

平滑空间滤波

平滑滤波器用于模糊处理和减小噪声,下面介绍其中两种滤波器。

平滑线性滤波器

顾名思义,平滑线性滤波器是对图像的每个像素点自身及周围灰度进行加权平均的过程,常见的掩模有:

[1 1 1;1 1 1;1 1 1]/9

[1 2 1;2 4 2;1 2 1]/16

对于不同的图像可以自定义掩模,但是必须满足所有掩模的所有元素和为1。掩模的尺寸也可以各异,尺寸越大,处理后的图像越模糊。

在图像预处理中,用于平滑和降噪的的高斯滤波是最常用的,MATLAB提供了fspecial()函数用于生成各种滤波掩模。

1
2
3
4
h = fspecial(type, parameters);   % 通用函数
h1 = fspecial('guassian',hsize,sigma); %生成大小为hsize*hsize的高斯卷积核,标准差为sigma
h2 = fspecial('laplacian',alpha); %拉普拉斯掩模,下面会提到
h3 = fspecial('average',hsize); %均值滤波

下图是MATLAB提供的所有掩模类型

统计排序滤波器

统计排序滤波器是一种非线性的滤波器,它不需要掩模,只根据图像滤波器包围的区域中像素的排序,然后用统计排序的结果决定的值代替中心像素的值。最常见的是中值滤波器,它采用统计排序得到的中值作为中心像素的值。中值滤波器对处理脉冲噪声(椒盐噪声)非常有效,处理随机噪声也比线性滤波器的模糊程度要低。

锐化空间滤波

锐化的目的是突出图像中的细节,同时对增强边缘有显著效果。下面介绍一种基于二阶微分算子的锐化空间滤波器。

对于二元函数的拉普拉斯算子: ,我们需要的是拉普拉斯算子的离散变换,因此定义离散的二阶偏微分:

得到

这个公式可以用[0 -1 0;-1 4 -1;0 -1 0]掩模来实现,同时可以看出,它符合90°旋转的各向同性。也可以对它进行改进,添加对角线两个个方向的偏微分,把[-1 -1 -1;-1 8 -1;-1 -1 -1]作为掩模。

由于拉普拉斯算子是一种微分算子,它强调了图像中灰度的突变同时降低灰度变换缓慢的区域,将通过拉普拉斯变换的掩模处理后的图像与原图像叠加就可以使得突变的位置得到强化。最终得到滤波器的掩模为[0 -1 0;-1 5 -1;0 -1 0] ,处理后图像的细节部分得到增强,并良好保留了图像的背景色调。

实验表明,经过包含对角分量的掩模进行处理的结果一般要比上句所表示的掩模所得结果锐化程度更强。

以上多种滤波方法都涉及到了掩模滤波,下面给出对给定掩模进行滤波的代码:

1
2
3
4
5
6
7
8
9
10
11
12
function [ output_img ] = Filter_img( input_img, mask, n )	%对给定掩膜进行滤波 mask为掩模矩阵,n为矩阵维数
output_img=input_img;
t=(n-1)/2;
p=sum(sum(mask));
mask=mask/p;
for i=2:size(input_img,1)-1
for j=2:size(input_img,2)-1
temp=mask.*double(input_img(i-t:i+t,j-t:j+t));
output_img(i,j)=sum(sum(temp));
end
end
end

然而,MATLAB已经提供了滤波的函数

B = imfilter(A,h,options...)   %  A表示原图像,h代表滤波掩模    

这里的options是可选参数,包括对边界处理方式的选择,滤波后图像的尺寸,以及相关(correlation)和卷积(convolution)的选择。边界处理option有:X表示增加的边界像素值(默认为0),’symmetric’ 表示边界部分补充的像素是对原图进行镜像处理得到的, ‘replicate’表示边界重复原图边界的像素, ‘circular’表示将原图紧贴着平铺得到的边界。滤波后图像尺寸option分为’same’显示的图像与原图等大,’full’表示滤波得到的实际结果,要比原图像大。imfilter默认选择correlation,因此若要使用卷积滤波,需要显示添加参数’conv’.

未完待续~~~

Thanks!