-
Notifications
You must be signed in to change notification settings - Fork 14
/
savitzkyGolayFilt.m
95 lines (80 loc) · 3.63 KB
/
savitzkyGolayFilt.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
function y=savitzkyGolayFilt(x,N,DN,F,W,DIM)
%savitzkyGolayFilt Savitzky-Golay Filtering.
% savitzkyGolayFilt(X,N,DN,F) filters the signal X using a Savitzky-Golay
% (polynomial) filter. The polynomial order, N, must be less than the
% frame size, F, and F must be odd. DN specifies the differentiation
% order (DN=0 is smoothing). For a DN higher than zero, you'll have to
% scale the output by 1/T^DN to acquire the DNth smoothed derivative of
% input X, where T is the sampling interval. The length of the input X
% must be >= F. If X is a matrix, the filtering is done on the columns
% of X.
%
% Note that if the polynomial order N equals F-1, no smoothing
% will occur.
%
% savitzkyGolayFilt(X,N,DN,F,W) specifies a weighting vector W with
% length F containing real, positive valued weights employed during the
% least-squares minimization. If not specified, or if specified as
% empty, W defaults to an identity matrix.
%
% savitzkyGolayFilt(X,N,DN,F,[],DIM) or savitzkyGolayFilt(X,N,DN,F,W,DIM)
% operates along the dimension DIM.
%
% See also savitzkyGolay, FILTER, sgolayfilt
% References:
% [1] Sophocles J. Orfanidis, INTRODUCTION TO SIGNAL PROCESSING,
% Prentice-Hall, 1995, Chapter 8.
% Author(s): R. Losada
% Copyright 1988-2004 The MathWorks, Inc.
% $Revision: 1.11.4.4 $ $Date: 2009/08/11 15:47:54 $
error(nargchk(4,6,nargin,'struct'));
% Check if the input arguments are valid
if round(F) ~= F, error(generatemsgid('MustBeInteger'),'Frame length must be an integer.'), end
if rem(F,2) ~= 1, error(generatemsgid('SignalErr'),'Frame length must be odd.'), end
if round(N) ~= N, error(generatemsgid('MustBeInteger'),'Polynomial order must be an integer.'), end
if N > F-1, error(generatemsgid('InvalidRange'),'The Polynomial order must be less than the frame length.'), end
if DN > N, error(generatemsgid('InvalidRange'),'The Differentiation order must be less than or equal to the Polynomial order.'), end
if nargin < 5 || isempty(W)
% No weighting matrix, make W an identity
W = ones(F,1);
else
% Check for right length of W
if length(W) ~= F, error(generatemsgid('InvalidDimensions'),'The weight vector must be of the same length as the frame length.'),end
% Check to see if all elements are positive
if min(W) <= 0, error(generatemsgid('InvalidRange'),'All the elements of the weight vector must be greater than zero.'), end
end
if nargin < 6, DIM = []; end
% Compute the projection matrix B
pp = fix(-F./2):fix(F./2);
B = savitzkyGolay(pp,N,DN,pp,W);
if ~isempty(DIM) && DIM > ndims(x)
error(generatemsgid('InvalidDimensions'),'Dimension specified exceeds the dimensions of X.')
end
% Reshape X into the right dimension.
if isempty(DIM)
% Work along the first non-singleton dimension
[x, nshifts] = shiftdim(x);
else
% Put DIM in the first dimension (this matches the order
% that the built-in filter function uses)
perm = [DIM,1:DIM-1,DIM+1:ndims(x)];
x = permute(x,perm);
end
if size(x,1) < F, error(generatemsgid('InvalidDimensions'),'The length of the input must be >= frame length.'), end
% Preallocate output
y = zeros(size(x));
% Compute the transient on (note, this is different than in sgolayfilt,
% they had an optimization leaving out some transposes that is only valid
% for DN==0)
y(1:(F+1)/2-1,:) = fliplr(B(:,(F-1)/2+2:end)).'*flipud(x(1:F,:));
% Compute the steady state output
ytemp = filter(B(:,(F-1)./2+1),1,x);
y((F+1)/2:end-(F+1)/2+1,:) = ytemp(F:end,:);
% Compute the transient off
y(end-(F+1)/2+2:end,:) = fliplr(B(:,1:(F-1)/2)).'*flipud(x(end-(F-1):end,:));
% Convert Y to the original shape of X
if isempty(DIM)
y = shiftdim(y, -nshifts);
else
y = ipermute(y,perm);
end