⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wsmooth.m

📁 我认为很不错的语音处理的matlab源代码
💻 M
字号:
function [zs,L] = wsmooth(z,x,y,L)
%WSMOOTH   1D and 2D robust smoothing.
%   ZS = WSMOOTH(Z,X,L) smoothes the signal Z(X) using the smoothing
%   parameter L. Z and X must be vector arrays of same length. L must be a
%   negative or positive real scalar. The larger L is, the smoother the
%   output will be. Typical values for L are between 0 and 3.
%
%   ZS = WSMOOTH(Z,X,Y,L) smoothes the surface Z(X,Y). X and Y must be
%   vector arrays whose lengths match the size of matrix Z.
%
%   ZS = WSMOOTH(Z,L) uses unit spacings for X and/or Y.
%
%   ZS = WSMOOTH(Z,X,Y) or ZS = WSMOOTH(Z,X) or ZS = WSMOOTH(Z): if L is
%   omitted, it is automatically determined using an incremental process
%   based on an estimation of the output signal variance. The function
%   ESTIMATENOISE written by John D'Errico is required for this option
%   (http://www.mathworks.com/matlabcentral/files/16683/estimatenoise.m).
%   [ZS,L] = WSMOOTH(...) also returns the proposed value for L so that you
%   can fine-tune the smoothing subsequently if needed.
%   
%   Notes:
%   -----
%   Smoothing also works if some data are missing (see examples); data are
%   considered missing if they are not finite (NaN or Inf). WSMOOTH can
%   thus be used as an alternative to INPAINT_NANS (another John D'Errico's
%   function): Z = INPAINT_NANS(ZNAN) and Z = WSMOOTH(ZNAN,L) with L<=0
%   give nearly similar results. Smoothing level, however, can be adjusted
%   with WSMOOTH if necessary.
%
%   This program is based on the Whittaker's smoother. The 1D algorithm has
%   been well described by Eilers in Anal. Chem. 2003, 75, 3631-3636. This
%   algorithm has been here adapted to 2D. Note that a 3D update could be
%   easily written.
%   
%   Examples:
%   --------
%   % 1-D example
%   x = 1:100;
%   y = cos(x/10)+(x/50).^2;
%   yn = y + 0.2*randn(1,100);
%   ys = wsmooth(yn,2);
%   plot(x,yn,'.-',x,ys)
%
%   % 1-D example with missing data and non uniform grid
%   x = sort(rand(1,100)*99)+1;
%   y = cos(x/10)+(x/50).^2;
%   y(45:60) = NaN;
%   yn = y + 0.2*randn(1,100);
%   ys = wsmooth(yn,x);
%   plot(x,yn,'.-',x,ys)
%
%   % 2-D example
%   [xp,yp] = deal(0:.02:1);
%   [x,y] = meshgrid(xp,yp);
%   f = exp(x+y) + sin((x-2*y)*3);
%   fn = f + (rand(size(f))-0.5);
%   fs = wsmooth(fn);
%   subplot(121), surf(xp,yp,fn), zlim([0 8])
%   subplot(122), surf(xp,yp,fs), zlim([0 8])
%
%   % 2-D example with missing data and non-uniform grid
%   xp = [0 sort(rand(1,48)) 1]; yp = [0 sort(rand(1,48)) 1];
%   [x,y] = meshgrid(xp,yp);
%   f = exp(x+y) + sin((x-2*y)*3);
%   f(round(rand(1,100)*2500)) = NaN; f(20:30,20:40) = NaN;
%   fn = f + (rand(size(f))-0.5);
%   fs = wsmooth(fn,xp,yp,1.5);
%   subplot(121), surf(xp,yp,fn), zlim([0 8])
%   subplot(122), surf(xp,yp,fs), zlim([0 8])
%
%   % comparison with inpaint_nans when removing NaN
%   [x,y] = meshgrid(0:.02:1);
%   [znan,z0] = deal(exp(x+y));
%   znan(10:25,20:35) = NaN;
%   znan(15:45,2:5) = NaN;
%   znan(35:37,20:45) = NaN;
%   z1 = inpaint_nans(znan);
%   z2 = wsmooth(znan,0);
%   subplot(121), surf(znan), zlim([1 8])
%   subplot(122), surf(z2), zlim([1 8]), title('wsmooth')
%
%   See also SMOOTH, ESTIMATENOISE, INPAINT_NANS.
%
%   -- Damien Garcia -- 2008/03
%   -- Special thanks to John D'Errico (for ESTIMATENOISE)


% % Check input arguments
% ---
error(nargchk(1,4,nargin))

 if ndims(z)~=2
     error('MATLAB:wsmooth:WrongZArray',...
         'First input must be a vector or a matrix.')
 end

if nargin==1 % wsmooth(z)
    if isvector(z) % 1D
        z = z(:)';
        nx = length(z);
        x = 1:nx; y = 1;
    elseif ndims(z)==2 % 2D
        [ny,nx] = size(z);
        x = 1:nx; y = 1:ny;
    else
        error('MATLAB:wsmooth:WrongInputs',...
            'Wrong input arguments: type ''help wsmooth''.')
    end
elseif nargin==2
    if isscalar(x) && ~isvector(z) % wsmooth(z,L), 2D
        L = x;
        [ny,nx] = size(z);
        x = 1:nx; y = 1:ny;
    elseif isscalar(x) && isvector(x) % wsmooth(z,L), 1D
        L = x;
        z = z(:)';
        nx = length(z);
        x = 1:nx; y = 1;
    elseif isvector(x) && isvector(z) % wsmooth(z,x), 1D
        z = z(:)';
        y = 1;
    else
        error('MATLAB:wsmooth:WrongInputs',...
            'Wrong input arguments: type ''help wsmooth''.')
    end
elseif nargin==3
    if ~isvector(z) && isvector(x) && isvector(y) % wsmooth(z,x,y), 2D
        % Nothing to declare
    elseif isvector(z) && isvector(x) && isscalar(y) % wsmooth(z,x,L), 1D
        L = y;
        z = z(:)';
        y = 1;
    else
        error('MATLAB:wsmooth:WrongInputs',...
            'Wrong input arguments: type ''help wsmooth''.')
    end
else % wsmooth(z,x,y,L), 2D
    if isvector(z) || ~isvector(x) || ~isvector(y) || ~isscalar(L)
        error('MATLAB:wsmooth:WrongInputs',...
            'Wrong input arguments: type ''help wsmooth''.')   
    end
end

[ny,nx] = size(z);
if ~isequal(length(x),nx) || ~isequal(length(y),ny)
    error('MATLAB:wsmooth:XYLengthMismatch',...
        'Number of elements in X and/or Y is inadequate.')
elseif any(sign(diff(x))~=1) && any(sign(diff(x))~=-1)
    error('MATLAB:wsmooth:NonMonotonicX',...
        'X must be strictly monotonic.')
elseif ~isequal(y,1) && any(sign(diff(y))~=1) && any(sign(diff(y))~=-1)
    error('MATLAB:wsmooth:NonMonotonicY',...
        'Y must be strictly monotonic.')
end

if exist('L','var')
    L = 10^L;
elseif ~exist('estimatenoise','file')
    error('MATLAB:wsmooth:MissingFunction',...
        ['ESTIMATENOISE is required if the L parameter is not specified.'...
        '\nESTIMATENOISE can be downloaded from the Matlab FEX (file ID: 16683).'])
end

x = x(:);
y = y(:);
class0 = class(z);
z = double(z);

% % 1D
if isequal(y,1)
    % Create the X-difference matrix
    % FDM: 2nd derivative, X-central difference, 2nd order
    dx0 = x(2:end-1)-x(1:end-2);
    dx1 = x(3:end)-x(2:end-1);    
    D = spdiags([2./dx0./(dx0+dx1) -2./dx0./dx1 2./dx1./(dx0+dx1)],...
        [0 1 2],nx-2,nx)*mean(dx0.^2);
    
    % Weight function (0 for NaN/Inf data, 1 otherwise)
    I = isfinite(z);
    z(~I) = 0;
    W = spdiags(double(I(:)),0,nx,nx);
    
    % Solve the linear system
    if exist('L','var')
        zs = (W + L*D'*D)\z(:);
    else
        amp = max(z(I))-min(z(I));
        noisevar = Inf;
        L = -1/3;
        while sqrt(noisevar)/amp > 1e-4
            L = L+1/3;
            zs = (W + 10^L*D'*D)\z(:);
            noisevar = estimatenoise(zs,x);
        end
    end
    zs = reshape(zs,size(z));

% % 2D
else
    % -----
    % The Whittaker's method is adapted to 2D. We solve:
    %   (I + lambda(Dx' Dx + Dy' Dy))zs = z,
    % where Dx and Dy are the difference matrices related to x- and y-
    % direction, respectively.
    % -----
    
    % Create the X-Difference matrix
    % FDM: 2nd derivative, X-central difference, 2nd order
    n = (nx-2)*ny;
    Id = repmat((1:n),[3 1]);
    [Jd,Dx] = deal(zeros(3,n));

    zI = true(ny,nx);
    zI(:,[1 nx]) = false;
    [I,J] = find(zI);

    Jd(1,:) = I+(J-2)*ny;
    Jd(2,:) = I+(J-1)*ny;
    Jd(3,:) = I+J*ny;
        
    dx0 = x(J)-x(J-1);
    dx1 = x(J+1)-x(J);
    Dx(1,:) = 2./dx0./(dx0+dx1);
    Dx(2,:) = -2./dx0./dx1;
    Dx(3,:) = 2./dx1./(dx0+dx1);
    Dx = sparse(Id,Jd,Dx,n,nx*ny)*mean(dx0.^2);

    % Create the Y-Difference matrix
    % FDM: 2nd derivative, Y-central difference, 2nd order
    n = nx*(ny-2);
    Id = repmat((1:n),[3 1]);
    [Jd,Dy] = deal(zeros(3,n));

    zI = true(ny,nx);
    zI([1 ny],:) = false;
    [I,J] = find(zI);

    Jd(1,:) = I-1+(J-1)*ny;
    Jd(2,:) = I+(J-1)*ny;
    Jd(3,:) = I+1+(J-1)*ny;

    dy0 = y(I)-y(I-1);
    dy1 = y(I+1)-y(I);
    Dy(1,:) = 2./dy0./(dy0+dy1);
    Dy(2,:) = -2./dy0./dy1;
    Dy(3,:) = 2./dy1./(dy0+dy1);
    Dy = sparse(Id,Jd,Dy,n,nx*ny)*mean(dy0.^2);
    
    % Weight function (0 for NaN/Inf data, 1 otherwise)
    I = isfinite(z);
    z(~I) = 0;
    W = spdiags(double(I(:)),0,nx*ny,nx*ny);

    % Solve the linear system
    if exist('L','var')
        zs = (W + L*Dx'*Dx + L*Dy'*Dy)\z(:);
        zs = reshape(zs,ny,nx);
    else
        amp = max(z(I))-min(z(I));
        noisevar = Inf;
        L = -1/3;
        while sqrt(noisevar)/amp > 1e-4
            L = L+1/3;
            zs = (W + 10^L*Dx'*Dx + 10^L*Dy'*Dy)\z(:);
            zs = reshape(zs,ny,nx);
            noisevar = estimatenoise(zs,x,2);
        end
    end
end

zs = cast(zs,class0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -