LPFTVD_Example_1

This example illustrates the LPF/TVD algorithm: simultaneous low-pass filtering (LPF) and total variation denoising (TVD). The algorithm is based on majorization-minimization and fast solvers for banded linear systems.

Ivan Selesnick
Polytechnic Institute of NYU
2012

Contents

Start

clear
% close all

printme = @(filename) print('-dpdf', sprintf('figures/LPFTVD_Example_1_%s', filename));

Create test signal

N = 300;                                    % N : length of signal
n = (1:N)';

s1 = 2*(n < 0.3*N) + 1*(n > 0.6*N);         % s1 : step function
s2 = sin(0.021*pi*n);                       % s2 : smooth function
s = s1 + s2;                                % s : total signal

ax = [0 N -1.5 3.5];                        % ax : axis for plots

figure(1)
clf

subplot(2, 1, 1)
plot(s1)
axis(ax)
title('TV component')

subplot(2, 1, 2)
plot(s2)
axis(ax)
title('Low-pass component')

Create noisy signal

sigma = 0.3;                            % sigma : standard deviation of noise

randn('state', 0);                     % Set state so example is reproducible
noise = sigma*randn(N, 1);             % noise : white zero-mean Gaussian

y = s + noise;                          % y : noisy data

figure(1)
clf

subplot(2, 1, 1)
plot(y)
axis(ax)
title('Data');
printme('data')

Define high-pass filter H

The high-pass filter is H = A\B where A and B are banded matrices (sparse data type in MATLAB).

% Set filter parameters (fc, d)

d = 2;           % d : filter order parameter (d = 1, 2, or 3)

fc = 0.022;       % fc : cut-off frequency (cycles/sample) (0 < fc < 0.5);

[A, B, B1] = ABfilt(d, fc, N);

LPF/TVD algorithm

Run the LPF/TVD algorithm to perform simultaneous low-pass filtering (LPF) and total-variation denoising (TVD).

lam = 0.8;                              % lam : regularization parameter

Nit = 30;                               % Nit : number of iterations

[x, f, cost] = lpftvd(y, d, fc, lam, Nit);          % Run LPF/TVD algorithm
% x : TVD component
% f : LPF component

txt_params = sprintf('d = %d, fc = %.3f, \\lambda = %.2f', d, fc, lam);

err = s - x - f;
err = err(d+1:N-d);   % truncate NaNs.
rmse = sqrt(mean(err.^2));

fprintf('LPF/TVD (RMSE = %.3f)\n', rmse);


% txt = sprintf('LPF/TVD (RMSE = %.3f)', rmse);
% disp(txt)
LPF/TVD (RMSE = 0.081)

Cost function history

Show the cost function history to verify the convergence of the algorithm.

figure(1)
clf
plot(cost)
title('Cost function history');
xlabel('Iteration')

printme('cost')

Display output of LPF/TVD algorithm

Set mean of x to zero for convenience of plotting

mx = mean(x);
x = x - mx;
f = f + mx;

Display LPF/TVD output

figure(2)
clf

subplot(2, 1, 1)
plot(x + f)
axis(ax)
str = sprintf('Denoised signal [Output of LPF/TVD] (RMSE = %.3f)', rmse);
title(str)
xlabel(txt_params)
printme('lpftvd')

Display the two components separately (low-pass and sparse derivative)

figure(2)
clf

subplot(2, 1, 1)
plot(x)
axis(ax)
title('TVD component [Output of LPF/TVD]');

subplot(2, 1, 2)
plot(f)
axis(ax)
title('LPF component [Output of LPF/TVD]');
xlabel(txt_params)

printme('lpftvd_components')

Verify optimality condition

Verify that the result obtained from lpftvd function satisfies the optimality conditions. (The scatter points should lie on the 'sign' function.)

AAT = A*A';
g = B1'*(AAT\(B*(y - x)));                      % same as S'H'H(y - x)

m = max(abs(diff(x)));

figure(1)
clf
line([-m 0 0 m]*1.2, [-1 -1 1 1]*lam, 'color', 0.5*[1 1 1])   % sign function
line(diff(x), g, 'marker', '.', 'linestyle', 'none', 'markersize', 10);  % scatter points
xlim([-1 1]*1.2*m)
ylim([-1 1]*1.5*lam)
ylabel('g = S H^T H(y - x)')
xlabel('u = diff(x)')
title('Optimality condition')

printme('optimality')