DSPRelated.com
Forums

Smoothing Filter

Started by Craig Doolittle December 18, 2002
Hello All,

I am interested in "smoothing" data. I know this is a very simple filter,
but it is quick and dirty. For a 5 point smoothing function, I would like
to return Y of data X where:
Y(n) = { X(n-2) + X(n-1) + X(n) + X(n+1) + X(n+2) } * 1/5

I can do this with a for loop (First method below). This method
"correctly" handles the boundary conditions in that the end points are not
moved, and the 2nd point is averaged with the one point before and after, etc.

Using filter is much faster than the for loop. However, filter apparently
only takes previous data.

One method (second method below) is to use filter and get
F(n) = { X(n-2) + X(n-1) + X(n) } * 1/3
B(n) = { X(n) + X(n+1) + X(n+2) } * 1/3
Y(n) = { F(n) + B(n) - X(n)/3 } * (3/5)

Unfortunately, this does not "correctly" handle the boundary conditions as
shown in the plots.

Is it possible to use something like: filter([1 1 1 1 1]),5,X)
and use the data in front of X(n) (i.e. X(n-2) + X(n-1) + X(n) + X(n+1) +
X(n+2) )?

Thanks for any help provided.

Simplified Test Code:

L000;
X=rand(L,1);

% First Method, For Loop
No_smooth=5;
tic
New_Smoothed=zeros(L,1);
% First boundary condition points
for ind=1:floor(No_smooth/2)
New_Smoothed(ind)=sum(X(1:ind+(ind-1)))/(ind+(ind-1));
end
% Middle condition points
for indl(No_smooth/2):L-floor(No_smooth/2)

New_Smoothed(ind)=sum(X(ind-floor(No_smooth/2):ind+floor(No_smooth/2)))/No_smoot\
h;
end
% Last boundary condition points
for ind=L-floor(No_smooth/2)+1:L
New_Smoothed(ind)=sum(X(ind-(L-ind):L))/(2*(L-ind)+1);
end
toc

No_smooth=3;

% Second Method, Filter, Filter backwards, and combine
tic
Forward=filter(ones(1,No_smooth),No_smooth,X);
Backward=filter(ones(1,No_smooth),No_smooth,X(L:-1:1));
Smoothed=(Forward - X/No_smooth + Backward(L:-1:1)) *
No_smooth/(2*No_smooth-1);
toc subplot(1,2,1)
plot(X(1:2*No_smooth), ':b')
hold, plot(Smoothed(1:2*No_smooth), '-r')
plot(New_Smoothed(1:2*No_smooth), '--m')
subplot(1,2,2)
plot(X(L-2*No_smooth:L), ':b')
hold, plot(Smoothed(L-2*No_smooth:L), '-r')
plot(New_Smoothed(L-2*No_smooth:L), '--m') Craig Doolittle
Senior Engineer
Applied Research Associates, Inc.
4300 San Mateo Blvd, NE, Suite A-220
Albuquerque, NM, USA 87110-1260
toll free: (800) 858-5494
tel: (505) 883-3636
fax: (505) 872-0794
E-mail:
http://www.ara.com



Hi Craig,

Why not use filter command as you said
filter([1 1 1 1 1]),5,X) and then compute just the
boundary points. I guess for this case you will have
to remove two values in the front, then replace the
next two values with your calculation and then add two
boundary value calculation at the end. A visual
inspection of the values of two methods may help.

Navan

--- Craig Doolittle <> wrote:
> Hello All,
>
> I am interested in "smoothing" data. I know this is
> a very simple filter,
> but it is quick and dirty. For a 5 point smoothing
> function, I would like
> to return Y of data X where:
> Y(n) = { X(n-2) + X(n-1) + X(n) + X(n+1) + X(n+2) }
> * 1/5
>
> I can do this with a for loop (First method below).
> This method
> "correctly" handles the boundary conditions in that
> the end points are not
> moved, and the 2nd point is averaged with the one
> point before and after, etc.
>
> Using filter is much faster than the for loop.
> However, filter apparently
> only takes previous data.
>
> One method (second method below) is to use filter
> and get
> F(n) = { X(n-2) + X(n-1) + X(n) } * 1/3
> B(n) = { X(n) + X(n+1) + X(n+2) } * 1/3
> Y(n) = { F(n) + B(n) - X(n)/3 } * (3/5)
>
> Unfortunately, this does not "correctly" handle the
> boundary conditions as
> shown in the plots.
>
> Is it possible to use something like: filter([1 1 1
> 1 1]),5,X)
> and use the data in front of X(n) (i.e. X(n-2) +
> X(n-1) + X(n) + X(n+1) +
> X(n+2) )?
>
> Thanks for any help provided.
>
> Simplified Test Code:
>
> L000;
> X=rand(L,1);
>
> % First Method, For Loop
> No_smooth=5;
> tic
> New_Smoothed=zeros(L,1);
> % First boundary condition points
> for ind=1:floor(No_smooth/2)
New_Smoothed(ind)=sum(X(1:ind+(ind-1)))/(ind+(ind-1));
> end
> % Middle condition points
> for indl(No_smooth/2):L-floor(No_smooth/2)
New_Smoothed(ind)=sum(X(ind-floor(No_smooth/2):ind+floor(No_smooth/2)))/No_smoot\
h;
> end
> % Last boundary condition points
> for ind=L-floor(No_smooth/2)+1:L
New_Smoothed(ind)=sum(X(ind-(L-ind):L))/(2*(L-ind)+1);
> end
> toc
>
> No_smooth=3;
>
> % Second Method, Filter, Filter backwards, and
> combine
> tic
> Forward=filter(ones(1,No_smooth),No_smooth,X);
>
Backward=filter(ones(1,No_smooth),No_smooth,X(L:-1:1));
> Smoothed=(Forward - X/No_smooth + Backward(L:-1:1))
> *
> No_smooth/(2*No_smooth-1);
> toc > subplot(1,2,1)
> plot(X(1:2*No_smooth), ':b')
> hold, plot(Smoothed(1:2*No_smooth), '-r')
> plot(New_Smoothed(1:2*No_smooth), '--m')
> subplot(1,2,2)
> plot(X(L-2*No_smooth:L), ':b')
> hold, plot(Smoothed(L-2*No_smooth:L), '-r')
> plot(New_Smoothed(L-2*No_smooth:L), '--m') > Craig Doolittle
> Senior Engineer
> Applied Research Associates, Inc.
> 4300 San Mateo Blvd, NE, Suite A-220
> Albuquerque, NM, USA 87110-1260
> toll free: (800) 858-5494
> tel: (505) 883-3636
> fax: (505) 872-0794
> E-mail:
> http://www.ara.com


__________________________________________________


Craig-

What you are doing is a running sum, sometimes called a "boxcar filter". Try
this:

for i=1:L

sum = 0;

for i=1:M % M is running sum length

sum = sum + X(i+M/2) - X(i-M/2); % M/2 integer division

end

Y(i) = sum / M;

end

I didn't deal carefully with endpoints or out-of-range indexes, but it should be
faster because it avoids the redundant additions in your code.

Jeff Brower
DSP sw/hw engineer
Signalogic Craig Doolittle wrote:
>
> Hello All,
>
> I am interested in "smoothing" data. I know this is a very simple filter,
> but it is quick and dirty. For a 5 point smoothing function, I would like
> to return Y of data X where:
> Y(n) = { X(n-2) + X(n-1) + X(n) + X(n+1) + X(n+2) } * 1/5
>
> I can do this with a for loop (First method below). This method
> "correctly" handles the boundary conditions in that the end points are not
> moved, and the 2nd point is averaged with the one point before and after, etc.
>
> Using filter is much faster than the for loop. However, filter apparently
> only takes previous data.
>
> One method (second method below) is to use filter and get
> F(n) = { X(n-2) + X(n-1) + X(n) } * 1/3
> B(n) = { X(n) + X(n+1) + X(n+2) } * 1/3
> Y(n) = { F(n) + B(n) - X(n)/3 } * (3/5)
>
> Unfortunately, this does not "correctly" handle the boundary conditions as
> shown in the plots.
>
> Is it possible to use something like: filter([1 1 1 1 1]),5,X)
> and use the data in front of X(n) (i.e. X(n-2) + X(n-1) + X(n) + X(n+1) +
> X(n+2) )?
>
> Thanks for any help provided.
>
> Simplified Test Code:
>
> L000;
> X=rand(L,1);
>
> % First Method, For Loop
> No_smooth=5;
> tic
> New_Smoothed=zeros(L,1);
> % First boundary condition points
> for ind=1:floor(No_smooth/2)
> New_Smoothed(ind)=sum(X(1:ind+(ind-1)))/(ind+(ind-1));
> end
> % Middle condition points
> for indl(No_smooth/2):L-floor(No_smooth/2)
>
New_Smoothed(ind)=sum(X(ind-floor(No_smooth/2):ind+floor(No_smooth/2)))/No_smoot\
h;
> end
> % Last boundary condition points
> for ind=L-floor(No_smooth/2)+1:L
> New_Smoothed(ind)=sum(X(ind-(L-ind):L))/(2*(L-ind)+1);
> end
> toc
>
> No_smooth=3;
>
> % Second Method, Filter, Filter backwards, and combine
> tic
> Forward=filter(ones(1,No_smooth),No_smooth,X);
> Backward=filter(ones(1,No_smooth),No_smooth,X(L:-1:1));
> Smoothed=(Forward - X/No_smooth + Backward(L:-1:1)) *
> No_smooth/(2*No_smooth-1);
> toc
>
> subplot(1,2,1)
> plot(X(1:2*No_smooth), ':b')
> hold, plot(Smoothed(1:2*No_smooth), '-r')
> plot(New_Smoothed(1:2*No_smooth), '--m')
> subplot(1,2,2)
> plot(X(L-2*No_smooth:L), ':b')
> hold, plot(Smoothed(L-2*No_smooth:L), '-r')
> plot(New_Smoothed(L-2*No_smooth:L), '--m')
>
> Craig Doolittle
> Senior Engineer
> Applied Research Associates, Inc.
> 4300 San Mateo Blvd, NE, Suite A-220
> Albuquerque, NM, USA 87110-1260
> toll free: (800) 858-5494
> tel: (505) 883-3636
> fax: (505) 872-0794
> E-mail:
> http://www.ara.com