2
votes

I have a noise-free image I. I want to simulate the additive Gaussian noise (zero mean, and variation v) n added to the image. The output of the model is:

Z = I + n

To simulate it, we have two ways:

  1. create a gaussian noise and add it to image,
  2. use imnoise function in MATLAB.

I used both ways, but they gave different results. Could you determine which one is correct? Why aren't they equivalent? In my knowledge, I think imnoise is correct one.

In my simulation, I use a definition of noise percent as

The "percent noise" number represents the percent ratio of the standard deviation of the Gaussian noise versus the signal for whole image.

I = imread('eight.tif');
[rows cols]=size(I);
I = double(I);
I = I - min(I(:));
I = I / max(I(:));
%% Percentage ratio
noise_per=0.4; %40 percent noise
%% Add noise to image
v = (noise_per*std(I(:)))^2 %// Option #2
%% Add noise by manual way
n=normrnd(0,v,[rows cols]);
I_noise1=I+n;
%% Add noise by imnoise func.
I_noise2 = imnoise(I, 'gaussian', 0, v);

subplot(131);imshow(n,[]);title('Gaussian noise');
subplot(132);imshow(I_noise1,[]);title('Add Gaussian noise #1');
subplot(133);imshow(I_noise2,[]);title('Add Gaussian noise #2');

output

2
I tested your code and got an error in line "I_noise1=I+n;". It says Matrix dimensions must agree. I don't have the original "eight.tif" so I had to use another imageVMMF
@VMMF: code above assume a grayscale image (wrong size computed if image was RGB)Amro

2 Answers

2
votes

Apart from the fact that normrnd takes standard deviation as input while imnoise expects variance (as noted by @mainactual), there is also the issue of data type and the range of values.

There is a note in imnoise documentation:

Note: The mean and variance parameters for 'gaussian' noise type is always specified as if the image were of class double in the range [0, 1]. If the input image is of class uint8, the imnoise function converts the image to double, adds noise according to the specified type and parameters, and then converts the noisy image back to the same class as the input.

In your case where the input image is already double in [0,1] range, this means clipping the output values to [0,1] range after adding the noise.

Also normrnd in this case can be replaced with a simple call to randn.

Example:

% input image
I = imread('eight.tif');
I = im2double(I);  % convert to double in [0,1] range

% noise mean/variance
m = 0;
v = (0.4 * std(I(:)))^2;

% normrnd
noise1 = normrnd(m, sqrt(v), size(I));
I1 = I + noise1;
I1 = max(0, min(I1, 1));  % clip to [0,1] range

% randn
noise2 = randn(size(I))*sqrt(v) + m;
I2 = I + noise2;
I2 = max(0, min(I2, 1));  % clip to [0,1] range

% imnoise
I3 = imnoise(I, 'gaussian', m, v);

% compare
subplot(221), imshow(I),  title('original')
subplot(222), imshow(I1), title('normrnd')
subplot(223), imshow(I2), title('randn')
subplot(224), imshow(I3), title('imnoise')

image-gaussian-noise

1
votes

I bolded the essential:

J = imnoise(I,'gaussian',M,V) adds Gaussian white noise of mean m and variance v to the image I. The default is zero mean noise with 0.01 variance. http://se.mathworks.com/help/images/ref/imnoise.html

and

R = normrnd(mu,sigma) generates random numbers from the normal distribution with mean parameter mu and standard deviation parameter sigma. http://se.mathworks.com/help/stats/normrnd.html

I think the both ways should be pretty equal and equally correct for your task and any other after the variance is corrected, that is, after

I_noise2 = imnoise( I, `gaussian`, 0, v^2 ); % orr sqrt(v) depends...