移动均值滤波与中值滤波

引言

基于MATLAB,使用中值滤波与均值滤波器进行滤波操作简单,原理也容易理解。好理解,也只针对于数据处在中间部分能够正好能够取到一个完整窗口,但是当数据恰巧在两端时,如何计算均值或者中值确是值得思考的问题。

均值滤波

均值滤波也称线性滤波,主要思想为邻域平均法,即用邻域的几个信号的平均值来代替相应位置的原值。

MATLAB中均值滤波只需要调用函数 smooth(y,span) ,其中 y 待滤波信号, span 为跨度,既窗口大小。举例说明均值滤波原理,尤其是在信号边缘处。从下面式子可以明白在边缘处均值滤波器是如何工作的。中值滤波器在边缘的处理可以说要复杂一些,在下一节中详细介绍。MATLAB均值滤波器默认窗口大小是3,下面式子以窗口大小为5进行说明。

yy(1) = y(1)
yy(2) = (y(1) + y(2) + y(3))/3
yy(3) = (y(1) + y(2) + y(3) + y(4) + y(5))/5
yy(4) = (y(2) + y(3) + y(4) + y(5) + y(6))/5
...

中值滤波器

中值滤波器是一种非线性数字滤波技术,通常用于去除图像或信号中的噪声。中值滤波器基于排序统计理论的一种能有效抑制噪声的非线性平滑滤波信号处理技术。中值滤波的特点即是首先确定一个以某个信号为中心点的邻域,一般为方形邻域(窗口),对于二维数据也可以为圆形、十字形等等,然后将邻域中各信号值排序,取其中间值(中值)作为中心信号的新值,这里邻域被称为窗口,当窗口移动时,利用中值滤波可以对信号进行平滑处理。

MATLAB中中值滤波器滤波函数为 y=medfilt1(x,n) ,其中 x 是待滤波的原始信号, n 为窗口大小。MATLAB的中值滤波原理为:

n 为奇数时, y(k)x(k(n1)/2:k+(n1)/2) 的中值;
n 为偶数时, y(k)x(kn/2:k+(n/2)1) 的中值;
medfilt1 函数将对这个链表进行排序,对中间的两个值取平均作为中值滤波结果。当n为偶数时,上面链表中数据个数为偶数,中间值有两个,中值结果为中间两个值的均值。
例1: 若 n=11,y(k)x(k5:k+5) 的中值;
例1: 若 n=12,y(k)x(k6:k+5)

问题来了,当 k 处于信号边缘处,该如何取中值呢?
MATLAB的方法是,在边缘处,无法取到窗口宽度情况下用0填充到序列为窗口窗口宽度,然后取中值。举例说明:
对序列,使用 medfilt1(x,n) 进行中值滤波,窗口 n=5
中值滤波前:

-7.9454   -5.8673   -7.2306   -6.7342   -7.9865   -6.3642   -5.8256   -7.3029

中值滤波后:

-5.8673   -6.7342   -7.2306   -6.7342   -6.7342   -6.7342   -6.3642   -5.8256

对于边缘信号第1个元素的中值滤波结果-5.8673=median(0 0 -7.9454 -5.8673 -7.2306), median 为取中值函数。
对于边缘信号第2个元素的中值滤波结果-6.7342=median(0 -7.9454 -5.8673 -7.2306 -6.7342)。
·······
对于边缘第8个元素的中值滤波结果-5.8256=median(-6.3642 -5.8256 -7.3029 0 0)。

采用这个过程进行中值滤波方法在边缘处会产生比较大的失真情况出现。在维基百科wiki中提供了另外一种解决思路可供参考。下面是wiki提供的中值滤波方法,在边缘也进行了填充,但是是通过填充边缘值而不是MATLAB中填充0。
x 是信号, y 是新产生的信号。

x = [2 80 6 3]

y[1] = Median[2 2 80] = 2
y[2] = Median[2 80 6] = Median[2 6 80] = 6
y[3] = Median[80 6 3] = Median[3 6 80] = 6
y[4] = Median[6 3 3] = Median[3 3 6] = 3

y = [2 6 6 3].

根据MATLAB中中值滤波原理代码实现

%% ymm 为滤波后结果,y是一维原始信号
n = 11 %这是窗口
if rem(n,2)==1
    right = (n-1)/2;
    left = (n-1)/2;
else
    right = n/2-1;
    left = n/2;
end
ymm = [];
for i = 1:l
    u = i+right;
    d = i-left;

    if d<1
        ymm =[ymm median([zeros(1,1-d) y(1:u)])];
    elseif d>=1&u<=l
        ymm =[ymm median(y(d:u))];
    elseif u>l
        ymm =[ymm median([y(d:l) zeros(1,u-l)])];
    end
end

通过上面的代码,将中值滤波修改为wiki中的边缘中值计算方法

n = 11
if rem(n,2)==1
    right = (n-1)/2;
    left = (n-1)/2;
else
    right = n/2-1;
    left = n/2;
end
ymm = [];
for i = 1:l
    u = i+right;
    d = i-left;

    if d<1
        zero = zeros(1,1-d);
        zero(:) = y(1);
        ymm =[ymm median([zero y(1:u)])];
    elseif d>=1&u<=l
        ymm =[ymm median(y(d:u))];
    elseif u>l
        zero = zeros(1,u-l);
        zero(:) = y(l);
        ymm =[ymm median([y(d:l) zero])];
    end
end

下图中,黑色曲线是原始信号真实值,绿色曲线是添加了高斯白噪声后的信号,蓝色和红色分别是均值和中值滤波效果。
下图中是MATLAB中的均值和中值滤波方法。在边缘处(两端),中值滤波结果有明显的失真现象。
这种边缘处理方式将很好的保留边缘值。


移动均值滤波与中值滤波_第1张图片

移动均值滤波与中值滤波_第2张图片

移动均值滤波与中值滤波_第3张图片

下面两幅图分别是wiki中提供的中值滤波的两端(边缘处)滤波失真情况减弱的效果。
红色是MATLAB提供的中值滤波方法滤波结果,在边缘处失真严重。青色为上面代码根据wiki的中值滤波方法,在边缘处与均值滤波效果一致。


移动均值滤波与中值滤波_第4张图片

移动均值滤波与中值滤波_第5张图片

参考

[1]https://en.wikipedia.org/wiki/Median_filter
[2]http://blog.sina.com.cn/s/blog_40a27f6a0101nq9x.html
[3]http://cn.mathworks.com/help/curvefit/smooth.html?searchHighlight=smooth&s_tid=doc_srchtitle
[4]http://cn.mathworks.com/help/signal/ref/medfilt1.html?searchHighlight=medfilt1&s_tid=doc_srchtitle

你可能感兴趣的:(算法/方法)