Pre-ci test passed git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4000 818b1a75-f10b-46b9-bf7c-635c3b92a50f
147 lines
5.9 KiB
Matlab
147 lines
5.9 KiB
Matlab
%% Rice/Rician Distribution Demo
|
|
% Demonstrate ricernd, ricepdf, and ricestat, in the context of simulating
|
|
% Rician distributed noise for Magnetic Resonance Imaging magnitude data.
|
|
|
|
%% Example: Rician noise vs (additive) Gaussian noise
|
|
% "Rician noise" depends on the data itself, it is not additive, so to
|
|
% "add" Rician noise to data, what we really mean is make the data
|
|
% Rician distributed.
|
|
clear, close('all'), clc
|
|
data = load('mri'); % MRI dataset (magnitude image) distributed with MATLAB
|
|
im = double(data.D(:,:,1,16)); % (particular slice through the brain)
|
|
s=5; % noise level (NB actual Rician stdev depends on signal, see ricestat)
|
|
im_g = im + 5 * randn(size(im)); % *Add* Gaussian noise
|
|
im_r = ricernd(im, s); % "Add" Rician noise (make Rician distributed)
|
|
% Note that the Gaussian noise has made some data go negative.
|
|
min_o = round(min(im(:))); max_o = round(max(im(:)));
|
|
min_g = round(min(im_g(:))); max_g = round(max(im_g(:)));
|
|
min_r = round(min(im_r(:))); max_r = round(max(im_r(:)));
|
|
% Show each image with the same color scaling limits
|
|
clim = [min_g max(max_g, max_r)];
|
|
figure('Position', [30 500 800 300]); colormap(data.map);
|
|
subplot(1,3,1); imagesc(im, clim); axis image;
|
|
title('Original');
|
|
xlabel(['Range: (' num2str(min_o) ', ' num2str(max_o) ')'])
|
|
subplot(1,3,2); imagesc(im_g, clim); axis image;
|
|
title('Gaussian noise');
|
|
xlabel(['Range: (' num2str(min_g) ', ' num2str(max_g) ')'])
|
|
subplot(1,3,3); imagesc(im_r, clim); axis image;
|
|
title('Rician noise')
|
|
xlabel(['Range: (' num2str(min_r) ', ' num2str(max_r) ')'])
|
|
|
|
%% The Rician PDF
|
|
x = linspace(0, 8, 100);
|
|
figure;
|
|
subplot(3, 1, 1)
|
|
plot(x, ricepdf(x, 0, 1), x, ricepdf(x, 1, 1),...
|
|
x, ricepdf(x, 2, 1), x, ricepdf(x, 4, 1))
|
|
title('Rice PDF with s = 1')
|
|
legend('v=0', 'v=1', 'v=2', 'v=4')
|
|
subplot(3,1,2)
|
|
plot(x, ricepdf(x, 1, 0.25), x, ricepdf(x, 1, 0.50),...
|
|
x, ricepdf(x, 1, 1.00), x, ricepdf(x, 1, 2.00))
|
|
title('Rice PDF with v = 1')
|
|
legend('s=0.25', 's=0.50', 's=1.00', 's=2.00')
|
|
subplot(3,1,3)
|
|
plot(x, ricepdf(x, 0.5, 0.25), x, ricepdf(x, 1, 0.50),...
|
|
x, ricepdf(x, 2.0, 1.00), x, ricepdf(x, 4, 2.00))
|
|
title('Rice PDF with v/s = 2')
|
|
legend('s=0.25', 's=0.50', 's=1.00', 's=2.00')
|
|
|
|
%% Approximations to the Rician PDF
|
|
% At high SNR (e.g. v/s > 3), Rician data is approximately Gaussian, though
|
|
% note that v is not the mean of the Rician distribution, nor of the
|
|
% Gaussian approximation (though for very high SNR it tends towards it).
|
|
v = 1.75; s = 0.5; x = linspace(0, 4, 100);
|
|
mu1 = v;
|
|
gpdf1 = (2*pi*s^2)^(-0.5) * exp(-0.5*(x-mu1).^2/s^2);
|
|
mu2 = ricestat(v, s); % (mu2 is approximately sqrt(v^2 + s^2))
|
|
gpdf2 = (2*pi*s^2)^(-0.5) * exp(-0.5*(x-mu2).^2/s^2);
|
|
figure; plot(x, ricepdf(x, v, s), x, gpdf1, x, gpdf2);
|
|
title('High SNR');
|
|
legend('Rician', 'Gaussian, naive mean', 'Gaussian, corrected mean')
|
|
%%
|
|
% At very low SNR, Rician data is approximately Rayleigh distributed
|
|
% (with no signal, the distributions are exactly equivalent)
|
|
v = 0.25; s = 0.5; x = linspace(0, 3, 100);
|
|
raypdf = (x / s^2) .* exp(-x.^2 / (2*s^2));
|
|
figure; plot(x, ricepdf(x, v, s), x, raypdf);
|
|
title('Low SNR'); legend('Rician', 'Rayleigh')
|
|
%%
|
|
% At low-medium SNR, neither Gaussian nor Rayleigh is a great approximation
|
|
v = 0.75; s = 0.5; x = linspace(-1, 3, 100);
|
|
mu = ricestat(v, s);
|
|
gpdf = (2*pi*s^2)^(-0.5) * exp(-0.5*(x-mu).^2/s^2);
|
|
raypdf = (x / s^2) .* exp(-x.^2 / (2*s^2)); raypdf(x <= 0) = 0;
|
|
figure; plot(x, ricepdf(x, v, s), x, gpdf, x, raypdf);
|
|
title('Medium SNR'); legend('Rician', 'Gaussian', 'Rayleigh')
|
|
|
|
%% A pitfal: Adding approximate Rician noise
|
|
% Since the Rician distribution with zero signal is equivalent to the
|
|
% Rayleigh, and with high SNR is approximated by a Gaussian, it is
|
|
% tempting to add Rayleigh or Gaussian noise (depending on SNR) to existing
|
|
% data, to simulate Rician distributed data (aka "adding Rician noise").
|
|
v = 75; s = 50; % medium SNR => Add Rayleigh noise
|
|
% Generate Rayleigh samples
|
|
N = 10000;
|
|
gsamp = s * randn(2, N);
|
|
rsamp = sqrt(sum(gsamp .^ 2));
|
|
|
|
%%
|
|
% Compare data with added Rayleigh samples to expected Rician distribution
|
|
r = v + rsamp; % Add Rayleigh noise to (constant) signal
|
|
c = linspace(0, 250, 20);
|
|
w = c(2); % histogram bin-width
|
|
h = histc(r, c);
|
|
figure; hold on; bar(c, h, 'histc');
|
|
xl = xlim; x = linspace(xl(1), xl(2), 100);
|
|
yl = ylim; % (for second plot)
|
|
plot(x, N*w*ricepdf(x, v, s), 'r');
|
|
title('Histogram of data, vs desired Rician PDF')
|
|
legend('Data with added Rayleigh noise', 'Rician distribution')
|
|
%%
|
|
% Compare Rician samples to expected Rician distribution
|
|
r = ricernd(v*ones(1, N), s);
|
|
c = linspace(0, 250, 20);
|
|
w = c(2); % histogram bin-width
|
|
h = histc(r, c);
|
|
figure; hold on; bar(c, h, 'histc');
|
|
xl = xlim; x = linspace(xl(1), xl(2), 100);
|
|
ylim(yl);
|
|
plot(x, N*w*ricepdf(x, v, s), 'r');
|
|
title('Histogram of data, vs desired Rician PDF')
|
|
legend('Rician sampled data', 'Rician distribution')
|
|
%%
|
|
% We see that the additive Rayleigh result is very poor (with medium SNR).
|
|
%
|
|
% With high noise levels the appearance of results can differ dramatically:
|
|
s = 0.15 * max_o;
|
|
% Approximate additive Rayleigh/Gaussian noise:
|
|
im_r = im;
|
|
for i=1:numel(im_r)
|
|
if im_r(i) <= 3*s
|
|
im_r(i) = im_r(i) + s*norm(randn(2,1)); % Add Rayleigh noise
|
|
else
|
|
im_r(i) = im_r(i) + s*randn; % Add Gaussian noise
|
|
end
|
|
end
|
|
% "Add" Rician noise (make Rician distributed):
|
|
im_R = ricernd(im, s);
|
|
% Show each image with the same color scaling limits
|
|
min_r = round(min(im_r(:))); max_r = round(max(im_r(:)));
|
|
min_R = round(min(im_R(:))); max_R = round(max(im_R(:)));
|
|
clim = [min_r max(max_r, max_R)];
|
|
figure('Position', [30 500 800 300]); colormap(data.map);
|
|
subplot(1,3,1); imagesc(im, clim); axis image;
|
|
title('Original');
|
|
xlabel(['Range: (' num2str(min_o) ', ' num2str(max_o) ')'])
|
|
subplot(1,3,2); imagesc(im_r, clim); axis image;
|
|
title('Rayleigh/Gaussian noise')
|
|
xlabel(['Range: (' num2str(min_r) ', ' num2str(max_r) ')'])
|
|
subplot(1,3,3); imagesc(im_R, clim); axis image;
|
|
title('Rician data');
|
|
xlabel(['Range: (' num2str(min_R) ', ' num2str(max_R) ')'])
|
|
|
|
%%
|
|
% Copyright 2007 Ged Ridgway (Ged at cantab dot net)
|