Using imnoise to add gaussian noise to an image - matlab

How do I add white Gaussian noise with SNR=5dB to an image using imnoise?
I know that the syntax is:
J = imnoise(I,type,parameters)
and:
SNR = 10log10[var(image)/var(error image)]
How do I use this SNR value to add noise to the image?

Let's start by seeing how the SNR relates to the noise. Your error image is the difference between the original image and the noisy image, meaning that the error image is the noise itself. Therefore, the SNR is actually:
SNR = 10log10[var(image)/var(noise)]
For a given image and SNR=5db, the variance of the noise would be:
var(noise) = var(image)/10SNR/10 = var(image)/sqrt(10)
Now let's translate all of this into MATLAB code. To add white Gaussian noise to an image (denote it I) using the imnoise command, the syntax is:
I_noisy = imnoise(I, 'gaussian', m, v)
where m is the mean noise and v is its variance. It is also important to note that imnoise assumes that the intensities in image I range from 0 to 1.
In our case, we'll add zero-mean noise and its variance is v = var(I(:))/sqrt(10). The complete code is:
%// Adjust intensities in image I to range from 0 to 1
I = I - min(I(:));
I = I / max(I(:));
%// Add noise to image
v = var(I(:)) / sqrt(10);
I_noisy = imnoise(I, 'gaussian', 0, v);
Clarification: we use var(I(:)) to treat compute the variance of all samples in image I (instead of var(I), which computes variance along columns).
Hope this helps!
Example
I = imread('eight.tif');
I = double(I);
%// Adjust intensities in image I to range from 0 to 1
I = I - min(I(:));
I = I / max(I(:));
%// Add noise to image
v = var(I(:)) / sqrt(10);
I_noisy = imnoise(I, 'gaussian', 0, v);
%// Show images
figure
subplot(1, 2, 1), imshow(I), title('Original image')
subplot(1, 2, 2), imshow(I_noisy), title('Noisy image, SNR=5db')
Here's the result:

Related

How to produce Cauchy noise when the image intensity range is [0,255]?

I have written the following code to produce Cauchy noise for an image when the image intensity range is [0,1]:
refimg = im2double(((imread('parrot.png')))); % original image
img_height = size(refimg,1);
img_width = size(refimg,2);
r1 = random('Normal',0, 1,[img_height img_width]);
r2 = random('Normal',0, 1,[img_height img_width]);
n = 0.04; % the noise level
u0 = refimg + n.*(r1./r2);
figure(1); imshow(u0);
And this is the result that I obtained:
Now I want to change the intensity range of my reference image to [0,255] and produce the noisy image corrupted by the Cauchy noise. For this purpose, I changed the first line to
refimg = im2double(((imread('parrot.png')))).*255; % original image
and the last line to:
figure(1); imshow(u0,[]);
But this is the output:
I appreciate it if someone could please help me to find the problem with my code when the image intensity range is [0,255].
To create the output the noise can be scaled by 255 and casted as a uint8 after being added to the reference image refimg to match the reference image, refimg. This results in an image that seems to replicate the image you had when it was handled as a double ranging from 0 to 1.
refimg = 255.*im2double(imread('tire.tif'));
img_height = size(refimg,1);
img_width = size(refimg,2);
r1 = random('Normal',0, 1,[img_height img_width]);
r2 = random('Normal',0, 1,[img_height img_width]);
n = 0.04; %the noise level%
Noise = 255.*n.*(r1./r2);
%Casting the noise as uint8 type and multiplying by 255%
u0 = uint8(refimg + Noise);
figure(1);
subplot(1,3,1); imshow(uint8(refimg));
subplot(1,3,2); imshow(uint8(Noise));
subplot(1,3,3); imshow(u0);

Manual Fourier transform to blur images with Gaussian PSF giving inverted result

I am trying to blur an image with Gaussian PSF. Instead of inbuilt convolution in MATLAB, I need to use a manual Fourier transformation to perform the convolution.I use the DFT matrix given as:
W = exp(1j*2*pi*[0:n-1]'*[0:n-1]/n)
I get the blurred image as the output but inverted.the code is as follows:
%%%blur a given input using Gaussian PSF and Fourier transform based
%%%convolution
close all
clear
clc
g0 = imread('E:\images\cameraman256.png');%reading the image
figure;imagesc(abs(g0));colormap(gray);axis off;axis equal;title('Image');
g0 = double(g0(:,:,1));
g0 = g0./max(max(g0));
%%%Gaussian PSF generation
%Blur Kernel
ksize = 31;
kernel = zeros(ksize);
%Gaussian Blur
s = 3;
% m = ksize/2;
[X, Y] = meshgrid(1:ksize);
kernel = (1/(2*pi*s^2))*exp(-((X).^2 + (Y).^2)/(2*s^2));
%Display Kernel
figure, imagesc(kernel)
axis square
title('Blur Kernel')
colormap gray
%Embed kernel in image that is size of original image
[h, w] = size(g0);
kernelimage = zeros(h,w);
kernelimage(1:ksize, 1:ksize) = kernel;
n=size(g0,1);
W = exp(1j*2*pi*[0:n-1]'*[0:n-1]/n);
ft = W*g0*W.';
ft_psf = W*kernelimage*W.';
convol = W*(ft.*ft_psf)*W.';
figure;imagesc(abs(convol));colormap(gray);axis off;axis equal;title('Blurred Image');
The DFT matrix implementation has been done according to the source found on the following link:
https://scicomp.stackexchange.com/questions/6949/how-can-a-2-d-fft-be-constructed-to-an-equivalent-matrix
Input Image
Blurred Image

MATLAB: How to use imnoise(I, 'localvar', image_intensity,var)?

I am trying to add noise to an image that varies based on the intensity of an image.
I = imread(filename);
figure, imshow(I);
v = I(:);
J = imnoise(I, 'localvar', v, 0.04*v);
figure, imshow(J);
But when I run the algorithm, I get the following exception:
error using max: Integers can only be combined with integers of the
same class, or scalar doubles
I'm not sure what my issue is either. Thank you so much!
Most likely, you read I from the file in one format, and imnoise function uses different format. After reading I, write the following line:
I = double(I)
That would help you. Here is the whole example from a similar question:
Using imnoise to add gaussian noise to an image:
I = imread('eight.tif');
I = double(I);
%// Adjust intensities in image I to range from 0 to 1
I = I - min(I(:));
I = I / max(I(:));
%// Add noise to image
v = var(I(:)) / sqrt(10);
I_noisy = imnoise(I, 'gaussian', 0, v);
%// Show images
figure
subplot(1, 2, 1), imshow(I), title('Original image')
subplot(1, 2, 2), imshow(I_noisy), title('Noisy image, SNR=5db')

Which one is the correct way of simulating addtive Gaussian noise

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:
create a gaussian noise and add it to image,
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');
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')
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...

Decrease Target Contrast without losing image details

I have a original image (on the left) and I want to decrease object (horizontal shape thing) contrast to simulate the reference image (on the right). I have tried all smoothing methods but all of them will impact image contrast (say background contrast). Is there any way I can build a model then subtract it from the original image?
In another word, is there any way we can add opacity to the image on the left to simulate the image on the right? The object mask has been provided and it is the same size as original image.
Any suggestion will be appreciated.
You reduce the contrast by multiplying the masked area in the input image:
I = imread('https://i.stack.imgur.com/QML1p.png'); %I = imread('1.png'); %Read image
M = imbinarize(imread('https://i.stack.imgur.com/nBqeS.png')); %imbinarize(imread('2.png')); %Read mask, and convert to binary image.
J = I;
J(M) = J(M)*.5; %Multiply the "horizontal shape thing" by 0.5 - reducing contrast.
figure;imshow(J);
Result:
The above solution is kind of setting the opacity of the "shape thing".
I tried to make it a bit smoother, but result is still very different.
I = imread('https://i.stack.imgur.com/QML1p.png');
%I = imread('1.png'); %Read image
M = imbinarize(imread('https://i.stack.imgur.com/nBqeS.png'));
%M = imbinarize(imread('2.png')); %Read mask, and convert to binary image.
M = imdilate(M, strel('disk', 20)); %Make mask thicker.
%Crate blurred "shape thing"
T = zeros(size(I));
T(M) = double(I(M)); %"shape thing" with some margins, and black surrounding.
T = T/255; %Change pixels range from [0, 255] to [0, 1].
T = imgaussfilt(double(T), 5); %Blur (2-D Gaussian filtering).
%Create blurred mask:
M = imgaussfilt(double(M), 20); %Blur the mask (2-D Gaussian filtering).
M = max(M, 0.5);
J = T.*M + im2double(I).*(1-M); %Weighed average.
J = imgaussfilt(J, 1);
J = im2uint8(J);
figure;imshow(J);
Result:
Try to play with it a little...
Another try:
Reduce the relative contrast between "shape thing" and background by averaging J and 0.5
Add gaussian noise (so result be closer to reference).
Code:
I = imread('https://i.stack.imgur.com/QML1p.png');
M = imbinarize(imread('https://i.stack.imgur.com/nBqeS.png'));
M = imdilate(M, strel('disk', 20)); %Make mask thicker.
%Crate blurred "shape thing"
T = zeros(size(I));
T(M) = double(I(M)); %"shape thing" with some margins, and black surrounding.
T = T/255; %Change pixels range from [0, 255] to [0, 1].
T = imgaussfilt(double(T), 5); %Blur (2-D Gaussian filtering).
T = T*1.5; %Scale T for changing opaquely
%Create blurred mask:
M = imgaussfilt(double(M), 20); %Blur the mask (2-D Gaussian filtering).
M = max(M, 0.5);
J = T.*M + im2double(I).*(1-M); %Weighed average.
J = imgaussfilt(J, 1);
%Reduce the relative contrast between "shape thing" and background by averaging J and 0.5
J = (J + 0.5)/2;
J = min(J, 1);
%Add gaussian noise (so result be closer to reference).
J = imnoise(J, 'gaussian', 0, 0.005);
J = im2uint8(J);
figure;imshow(J);
Result: