邻域处理包含以下过程:
移动中心点会产生新的邻域,每个邻域对应输入图像上的一个像素。用来区别这种处理的两个主要术语为邻域处理和空间滤波,后者更为普遍。若对邻域中像素的计算为线性的,则运算称为线性空间滤波(也使用术语“空间卷积”;否则称此运算为非线性空间滤波。
线性空间滤波的机理:在图像/中逐点移动滤波模板w的中心点。 在每个点(x,y)处,滤波器在该点处的响应是由滤波模板限定的相应邻域像素与滤波器系数的乘积结果的累加和。
在执行线性空间滤波时,我们必须清晰地理解两个意义相近的概念。一个是相关;另一个是卷积。相关是指模板按图2.-1所示的方式进行图像数组f的处理。原理上,卷积是相同的过程,只不过在 w通过f之前先将它旋转 180°。
上面是课本给的解释,图不是很清晰,下面我们来举个例子深入理解:
公式:
操作步骤:
操作图解:
这样结果w(x,y)f(x,y)中的第一个元素值(1,1)=1x0+2x0+3x0+4x0+5x1+6x1+7x0+8x2+9x1=36。以此类推。
最终结果:
公式:
操作步骤:
操作图解:
1 卷积核翻转180o
2 a.
这样结果w(x,y)f(x,y)中的第一个元素值(1,1)=9x1+8x1+7x2+6x2+5x1+4x2+3x1+2x3+1x2 =67 以此类推。
最终结果:
b.
由于卷积操作会导致图像变小(损失图像边缘),所以为了保证卷积后图像大小与原图一致,经常的一种做法是人为的在卷积操作之前对图像边缘进行填充。
这样结果w(x,y)f(x,y)中的第一个元素值(1,1)=9x0+8x0+7x0+6x0+5x1+4x1+3x0+2x2+1x1 =14 以此类推。
最终结果:
工具箱使用函数 imfilter 来实现线性空间滤波,该函数的语法如下:
g = imfilter( f, w, filtering_mode, boundary_options, size options)
函数解释:
f 是输入图像,w 为滤波模板,g 为滤波结果;对于相关, 将 Filtering_mode 指定为 ‘corr’(这是默认值);对于卷积,将它指定为 ‘conv’, boundary_options 用于处理边界填充问题,边界的大小由滤波器的大小确定。 size_options 可以是’same’ 或’full’。具体解释参考下面表格:
选项 | 说明 |
---|---|
滤波横式 | |
corr | 滤波通过使用相关来完成,这是默认值 |
conv | 滤波通过使用卷积来完成 |
边界选项 | |
P | 输入图像的边界通过用值P填充来扩展(没有任何引用);P的默认值是0 |
replicate | 图像大小通过复制外边界的值来扩展 |
symmetric | 图像大小通过沿自身的边界进行镜像映射扩展 |
circular | 图像大小通过将图像作为二维周期函数的一个周期来扩展 |
大小选项 | |
full | 输出图像的大小与被扩展(填充)图像的大小相同 |
same | 输出图像的大小与输入图像的大小相同,这可通过将滤波模板的中心点的偏移限制为原始图像中包含的点来实现,这是默认值 |
函数imfilter应用:
代码编写:
g = imread('D:\数字图像处理\第二章学习\dog2.jpg');
I = rgb2gray(g); %把图像变为灰度图像
f = im2double(I); %把图像变为double类型图像
w = ones(31); % 31x31 的滤波器
gd=imfilter(f,w); %实现线性空间滤波
figure;
subplot(1, 2, 1), imshow(g), title('原图像');
subplot(1, 2, 2), imshow(gd,[]), title('31x31的滤波器处理后图像');
代码运行如下:
用滤波器 w 对图像进行卷积以产生模糊结果。因为滤波器是对称的,所以可以使用默认的 imfilter做相关操作。在这里我们使用默认的边界选项,用 0值对图像边界进行填充。就像我们期望的那样,滤 波后,图像中的黑白边缘被模糊了,但只是出现在图像较亮的部分以及边缘之间的边上。当然, 原因是填充的边界为黑色。我们可以通过使用 replicate选项来解决这个困难:
代码编写:
g = imread('D:\数字图像处理\第二章学习\dog2.jpg');
I = rgb2gray(g); %把图像变为灰度图像
f = im2double(I); %把图像变为double类型图像
w = ones(31); % 31x31 的滤波器
gd=imfilter(f,w,'replicate'); %实现线性空间滤波,图像大小通过复制外边界的值来扩展。
figure;
subplot(1, 2, 1), imshow(g), title('原图像');
subplot(1, 2, 2), imshow(gd,[]), title('使用replicate后图像');
代码运行如下:
滤波后,图像的边界正如我们料想的那样。在这种情况下,相同的结果可以通过选项 symmetric 获得:
代码编写:
g = imread('D:\数字图像处理\第二章学习\dog2.jpg');
I = rgb2gray(g); %把图像变为灰度图像
f = im2double(I); %把图像变为double类型图像
w = ones(31); % 31x31 的滤波器
gd=imfilter(f,w,'symmetric'); %实现线性空间滤波,图像大小通过沿自身的边界进行镜像映射扩展。
figure;
subplot(1, 2, 1), imshow(g), title('原图像');
subplot(1, 2, 2), imshow(gd,[]), title('使用symmetric后图像');
运行状态如下:
显示确实结果相同。然而,使用 circular 选项:
代码编写:
g = imread('D:\数字图像处理\第二章学习\dog2.jpg');
I = rgb2gray(g); %把图像变为灰度图像
f = im2double(I); %把图像变为double类型图像
w = ones(31); % 31x31 的滤波器
gd=imfilter(f,w,'circular'); %实现线性空间滤波,图像大小通过沿自身的边界进行镜像映射扩展。
figure;
subplot(1, 2, 1), imshow(g), title('原图像');
subplot(1, 2, 2), imshow(gd,[]), title('使用circular后图像');
代码运行如下:
显示出了与使用 0填充同样的问题。这也是我们料想到的, 因为周期性的使用使得图像的黑暗部分邻近光亮区域。最后,使用 imfilter 产生与输入相同类型的结果,如果处理不当,将会产生很大的问题:
编写代码:
g = imread('D:\数字图像处理\第二章学习\dog2.jpg');
I = rgb2gray(g); %把图像变为灰度图像
f = double(f); %把图像变为double类型图像
f8 = uint8(f); %把图像变为uint8类型图像
w = ones(31); % 31x31 的滤波器
g8r=imfilter(f8,w,'replicate'); %实现线性空间滤波,图像大小通过复制外边界的值来扩展。
figure;
subplot(1, 2, 1), imshow(g), title('原图像');
subplot(1, 2, 2), imshow(g8r,[]), title('转换为uint8类并使用replicate后图像');
代码运行如下:
在这种情况下,当输出通过 imfilter 转换为与输入相同的类型(uint8) 时,由于裁剪会引起数据丢失。原因是模板的系数不是在范围[0,1]内求和, 从而引起滤波后的结果超过范围[0,255]。
非线性空间滤波也基于邻域操作。然而,线性空间滤波基于计算乘积和(即线性操作),顾名思义, 而非线性空间滤波基于涉及邻域像素内的非线性操作。另一个基本的区别是:模板的概念在非线性处理 中不是那么普遍。滤波的概念仍然是存在的,但是“滤波器”应想象为邻域像素操作的非线性函数,这些响应构成了非线性操作的结果。
为了执行通常的非线性滤波操作,工具箱提供了两个函数:nlfilter 和 colfilt。nlfilter 直接执行二维操作,而 colfilt 按列组织数据。虽然 colfilt 需要占用更多的内存,但是执行起来要比 nlfilter 快得多。在大多数图像处理应用中,速度是最重要的因素。 因此,在执行通常的非线性空间滤波时,更多的是采用 colfilt 而不是 nlfilter。
函数 colfilt 的语法如下:
g = colfilt(f, [m,n], 'sliding', fun) %m 和 n 表示的是滤波区域的维数,sliding表明处理过程是mxn区域在输入图像 f中逐像素进行滑动,fun 是函数句柄。
然而,当使用 colfilt 时,在进行滤波之前,输入图像必须被很清楚地进行填充。 为此,我们使用函数 padarray, 对于二维函数,语法为:
fp = padarray(f, [r c], method, direction) %f为输入图像,fp 为填充后的图像,[r c]表示用于填充f的行数和列数
如果在参数中不包括 direction, 那么默认值为 both。如果不包含 method,将默认用0填充。
编写代码:
g = imread('D:\数字图像处理\第二章学习\dog2.jpg');
g1 = uint8(colfilt(I,[5 5],'sliding',@mean)); %使用mean函数(求均值)
subplot(1, 2, 1), imshow(g), title('原图像');
subplot(1, 2, 2), imshow(g1), title(' 函数colfilt实现非线性空间滤波 ');
代码运行状态如下:
现在,函数 coifilt 仍然是进行非线性滤波操作最好的选择,还没有可以替换的函数。
工具箱支持一些预定义的二维线性空间滤波器,可通过函数 fspecial 实现,该函数生成滤波模板w, 函数语法为:
w = fspecial(type, parameters) % type表示滤波器的类型,parameters进一步定义指定的滤波器。
我们应用拉普拉斯滤波器对图像进行增强处理,在这种情况下,对图像的增强包括使图像锐化,同时要尽可能保留图像的灰度层次。
代码编写:
f = imread('D:\数字图像处理\第二章学习\dog2.jpg');
figure;
subplot(2, 2, 1), imshow(f), title('原图像');
w=fspecial('laplacian',0); %生成并显示拉普拉斯滤波器
g1=imfilter(f,w,'replicate'); %用 W 处理输入图像 f, f 属于 Uint8 类
subplot(2, 2, 2), imshow(g1), title('拉普拉斯滤波(uint8)');
f2=im2double(f); %在滤波前将 f 转换为浮点数
g2=imfilter(f2,w,'replicate'); %用 W 处理输入图像 f2, f 2属于double 类
subplot(2, 2, 3), imshow(g2), title('拉普拉斯滤波(double)');
g=f2-g2; %从原始图像中减去拉普拉斯图像以恢复失去的灰度层次
subplot(2, 2, 4), imshow(g), title('增强后的结果');
代码分析:
开始用 W 处理输入图像 f, f 属于 Uint8 类,显示了结果图像(左上图)。这个结果看起来是合理的,但存在如下问题:所有像素都是正的。因为滤波器的中心参数为负,所以通常我们希望得到带有正值和负值的拉普拉斯图像。 然而在这种情况下,f 属于 uint8 类,imfilter 给出了与输入图像类型相同的输出,所以负值将被截掉(右上图)。可以通过在滤波前将 f 转换为浮点数来解决这个困难(左下图),显示的是拉普拉斯图像的典型外观,最后,我们从原始图像中减去拉普拉斯图像以恢复失去的灰度层次(因为中心参数为负值) ,显示的结果(右下图)比原始图像要清晰。
代码运行如下:
人工规定的滤波器与增强技术的比较
增强问题常常需要从工具箱中指定可用的滤波器。拉普拉斯滤波器就是很好的例子#,工具 箱支持中心为-4的 3x3拉普拉斯滤波器。通常使用中心为-8、 周围的值都为 1 的 3x3拉普拉 斯滤波器以得到更尖锐的图像。这个例子的目的是手工实现这个滤波器,并比较这两种方式得到的结果。
代码编写:
f = imread('D:\数字图像处理\第二章学习\dog2.jpg');
w4=fspecial('laplacian',0)
w8=[1 1 1;1 -8 1;1 1 1]
figure;
g4 =f - imfilter(f, w4, 'replicate'); %从原始图像中减去拉普拉斯图像以恢复失去的灰度层次
g8 =f - imfilter(f, w8, 'replicate'); %从原始图像中减去中心为-8拉普拉斯滤波器图像以得到更尖锐的图像
subplot(1,3,1),imshow(f);title('原图');
subplot(1,3,2),imshow(g4),title('g4');
subplot(1,3,3),imshow(g8),title('g8');
正如我们预期的那样,g8图比g4图清晰得多。
非线性空间滤波器,它们的响应基于图像邻域中的像素序列, 并且邻域中心像素的值被由邻域序列的排序结果决定的值代替。
本段我想主要介绍利用函数 medfilt2 的中值滤波 ,中值滤波是减少图像中椒盐嗓声的有用工具。
代码编写:
f = rgb2gray(imread('D:\数字图像处理\第二章学习\dog2.jpg'));
figure;
subplot(2, 2, 1), imshow(f), title('原图像');
fn=imnoise(f,'salt & pepper',0.2);
subplot(2, 2, 2), imshow(fn), title('由椒盐噪声污染的图像');
gm = medfilt2(fn); %对带噪图像进行中值滤波处理
subplot(2, 2, 3), imshow(gm), title('非线性滤波降噪');
gms = medfilt2(fn,'symmetric'); %通过 symmetric 减弱黑点
subplot(2, 2, 4), imshow(gms), title('非线性滤波降噪的强化');
代码运行状态如下:
分析:
中值滤波采用默认值设置就可以很好地削弱噪声,但是小狗图像边缘还是有很多黑点,symmetric 选项可以减弱,使黑色边缘效应不是那么明显。