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 |
|
Smoothing Filter
Started by ●December 18, 2002
Reply by ●December 19, 20022002-12-19
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 __________________________________________________ |
Reply by ●December 19, 20022002-12-19
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 |