Why does imnoise add different noise than randn?
5 views (last 30 days)
Show older comments
Jonathan Sullivan
on 8 Feb 2023
Commented: Jonathan Sullivan
on 8 Feb 2023
I don't understand what imnoise is doing differently than when you add noise to an image with randn. Here is my code
I create an 8bit image with 8bit pixel depth. Then add gaussian noise manually and with imnoise. I remove the pixel values from the noisy images and use fitdist to find sigma. I also have a control where I use imnoise on zeros. I'd expect the noise added from all methods to have the same mu and sigma.
What's happening here?
EDIT: for typos
clear;
n=256;
mu=0;
sigma=2;
var=sigma^2;
% 8bit image with 8bit pixel depth.
sample = randsample(n,n*n,true);
I = reshape(sample,n,n);
% add gaussian noise
A = I + sigma*randn(n,n)+mu;
B = imnoise(rescale(I),"gaussian",mu,var);
C = imnoise(zeros(n,n),"gaussian",mu,var);
% fit to normal distribution
A_dist = fitdist(reshape(A-I,n*n,1),'normal');
B_dist = fitdist(reshape(B-I,n*n,1),'normal');
B_dist_prime = fitdist(reshape(B,n*n,1),'normal');
C_dist = fitdist(reshape(C,n*n,1),'normal');
A_dist.sigma
A_dist.mu
B_dist.sigma
B_dist.mu
B_dist_prime.sigma
B_dist_prime.mu
C_dist.sigma
C_dist.mu
0 Comments
Accepted Answer
DGM
on 8 Feb 2023
Edited: DGM
on 8 Feb 2023
You're seeing two things.
First, your image is improperly-scaled for its class (1-256 for class 'double'), but the image you're feeding to imnoise() is forced to unit scale. All floating point images fed to imnoise() are assumed to be unit-scale, so B and C are also unit-scale. B-I will result in nonsense.
Second, the distributions are all appearing wonky because you're seeing severe truncation. Internally, we're working in unit-scale. You're specifying gaussian noise with a sigma of 2, so a lot of that noise pushes data outside that interval. In the case of a null image, at least half the pixels are pushed outside [0 1]. The last thing that happens is the image is clamped to unit-scale and then cast/rescaled back to the input class.
If we stick with unit-scale and use moderate variance, the results are more comparable. Consider the example.
n=256;
mu=0;
gauvar = 0.01;
sigma = sqrt(gauvar)
% an image which is scaled properly for its class
I = rand(n,n);
% add gaussian noise
noise = sigma*randn(n,n)+mu;
A = imclamp(I + noise); % the output is clamped!
B = imnoise(rescale(I),"gaussian",mu,gauvar);
C = imnoise(zeros(n,n),"gaussian",mu,gauvar); % truncation is heavily asymmetric
% fit to normal distribution
ndist = fitdist(reshape(noise,n*n,1),'normal');
A_dist = fitdist(reshape(A-I,n*n,1),'normal');
B_dist = fitdist(reshape(B-I,n*n,1),'normal');
C_dist = fitdist(reshape(C,n*n,1),'normal');
[ndist.sigma ndist.mu]
[A_dist.sigma A_dist.mu]
[B_dist.sigma B_dist.mu]
[C_dist.sigma C_dist.mu] % still heavily truncated on one side
If you want to see exactly what's going on, you can check toolbox/images/images/+images/+internal/algimnoise.m, but that's basically it.
More Answers (0)
See Also
Categories
Find more on Image Processing Toolbox in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!