天天看点

图像处理系列-均值滤波和中值滤波图像处理系列-均值滤波和中值滤波

图像处理系列-均值滤波和中值滤波

1.均值滤波与中值滤波介绍

在经典书籍《数字图像处理第三版-冈萨雷斯》中介绍了滤波相关概念,并详细讲解了均值滤波与中值滤波的原理。如果本文有不详尽之处,可查阅本书P93平滑空间滤波部分。

宏观上,让我们了解均值滤波和中值滤波在图像处理中的位置。在数字图像处理中,滤波是很重要的一部分,均值滤波和中值滤波是都属于空间滤波(对于某一像素点,以该点为中心,通过对该像素点邻域部分的像素进行处理,得到中心替代像素点的滤波方法)中的平滑滤波方法(还有锐化滤波等)。进一步,平滑滤波分为平滑线性滤波器和平滑非线性滤波器,而均值滤波属于前者,中值滤波属于后者。

应用上,均值滤波处理高斯噪声效果较好,中值滤波处理椒盐噪声比较好,原因点击查看。

2.原理说明

对于通用的加权平滑滤波器,计算公式由下式给出:

f ( x , y ) = ∑ s = − a a ∑ − b b w ( s , t ) f ( x + s , y + t ) ∑ s = − 1 a ∑ s = − b b w ( s , t ) f(x,y)=\frac{\sum_{s=-a}^{a}\sum_{-b}^{b} w(s,t)f(x+s,y+t)}{\sum_{s=-1}^{a}\sum_{s=-b}^{b}w(s,t)} f(x,y)=∑s=−1a​∑s=−bb​w(s,t)∑s=−aa​∑−bb​w(s,t)f(x+s,y+t)​

其中f(x,y)为图像上坐标为(x,y)的点的灰度值,a与b为以(x,y)为中心的矩形(窗口)的半长与半宽,w(s,t)为给点(s,t)所加的权重。

对于窗口大小为3的均值滤波器,化简公式如下:

f ( x , y ) = 1 9 ∑ i = 1 9 Z i f(x,y)=\frac{1}{9}\sum_{i=1}^{9}Z_{i} f(x,y)=91​i=1∑9​Zi​

其中,Zi为以点(x,y)为中心,3×3的正方形中的九个点的灰度值。同理,窗口大小为n时,正方形的边长随之改变为n。可以看出,如果噪声为高斯噪声,测量值在真实值周围波动,取得平均之后会得到相对准确的值。

对于窗口大小为3的中值滤波器,f(x,y)的值应为Zi组成的数列(长度为9)的中值。可以看出,如果噪声为椒盐噪声,像素会出现剧烈跳动,而中值对极大值和极小值不敏感,取中值后可以很好过滤掉此类噪声。

3.图像边界处理

由于在窗口滑动的过程中,图像的边界不能作为小窗口的中心,故需要对图像边界进行一些人为处理。常见的处理方法如下。

  • 不做处理咳咳咳。
  • 忽略掉图像边界点,输出图像的尺寸会减小。
  • 忽略掉图像边界点,滤波计算完成后裁剪掉未滤波的像素点,再将裁剪后的图像放大到原图大小。
  • 根据窗口大小,想边界外填补一些像素,填充的像素灰度值与最近像素灰度值相同。

本文代码才用的是第三个处理方案,使用双线性插值法来放大。

4.效果

图像处理系列-均值滤波和中值滤波图像处理系列-均值滤波和中值滤波

5.代码

github仓库

clc;clear;
%% 参数输入区,在此选择窗口大小和滤波方式
filterSize = 7;
% filterMode = 'median';
filterMode = 'average';
I=imread('./circuit.jpg');
%% 开始运行
I = rgb2gray(I);

%%边界,数据格式(图像uint8,默认类型转换)

switch filterMode
    case 'average'
        [h,w] = size(I);
        imageOut = zeros(h, w);%为了扩充图像而创建的临时图像
        stepRange = (filterSize-1)/2;
        %%外层两个for循环用来定位窗口中心,内层两个for用来窗口滤波计算
        for pointRow = 1+stepRange : h-stepRange
            for pointCol = 1+stepRange : w-stepRange
                pixelSum = 0;
                for i = pointRow-stepRange:pointRow+stepRange
                    for j = pointCol-stepRange:pointCol+stepRange
                        pixelSum = pixelSum + double(I(i, j));
                    end
                end
                pixelValue = pixelSum/filterSize^2;
                imageOut(pointRow, pointCol) = uint8(pixelValue);
            end
        end
        imageOut = uint8(imageOut); %double转化为uint8格式
        imageOut = imcrop(imageOut,[1+stepRange,1+stepRange,w-2*stepRange-1,h-2*stepRange-1]);
        imageOut = imresize(imageOut, [h, w], 'bilinear');
        
    case 'median'
        [h,w] = size(I);
        imageOut = zeros(h, w);%为了扩充图像而创建的临时图像
        stepRange = (filterSize-1)/2;
        %%外层两个for循环用来定位窗口中心,内层两个for用来窗口滤波计算
        for pointRow = 1+stepRange : h-stepRange
            for pointCol = 1+stepRange : w-stepRange
                pixelArray = zeros(1, filterSize^2);
                ptrPA = 1;
                for i = pointRow-stepRange:pointRow+stepRange
                    for j = pointCol-stepRange:pointCol+stepRange
                        pixelArray(ptrPA) = double(I(i, j));
                        ptrPA = ptrPA + 1;
                    end
                end
                imageOut(pointRow, pointCol) = uint8(median(pixelArray));
            end
        end
        imageOut = uint8(imageOut); %double转化为uint8格式
        imageOut = imcrop(imageOut,[1+stepRange,1+stepRange,w-2*stepRange-1,h-2*stepRange-1]);
        imageOut = imresize(imageOut, [h, w], 'bilinear');
end

subplot(121),imshow(I);
subplot(122),imshow(imageOut);
impixelinfo;
           

继续阅读