package fr.unistra.pelican.algorithms.noise;
import java.util.Random;
import fr.unistra.pelican.Algorithm;
import fr.unistra.pelican.AlgorithmException;
import fr.unistra.pelican.Image;
import fr.unistra.pelican.PelicanException;
import fr.unistra.pelican.algorithms.statistics.Correlator;
/**
* Adds uniformly distributed noise to a given image (3 bands max)
*
* @author ?, Benjamin Perret
*
* @see fr.unistra.pelican.algorithms.noise.MultivariateNormalNoise
*/
public class Uniform extends Algorithm {
/**
* Input image
*/
public Image inputImage;
/**
* Output image
*/
public Image outputImage;
/**
* Noise deviation (same in each band) in [0;1]
* !!! Not equal to standard deviation
*/
public double sdev;
/**
* Inter band correlation in [0;1]
*/
public double corr;
/**
* Constructor
*
*/
public Uniform() {
super();
super.inputs = "inputImage,sdev,corr";
super.outputs = "outputImage";
}
/*
* (non-Javadoc)
*
* @see fr.unistra.pelican.Algorithm#launch()
*/
public void launch() throws AlgorithmException {
outputImage = inputImage.copyImage(false);
Random rand = new Random();
double s = sdev * sdev;
double r = s * corr;
double[][] sigma = { { s, r, r }, { r, s, r }, { r, r, s } };
if (sdev > 1.0 || sdev <= 0.0)
throw new AlgorithmException(
"The standard deviation must be in ]0,1]");
if (corr > 1.0 || corr < 0.0)
throw new AlgorithmException(
"The correlation degree must be in [0,1]");
if (inputImage.getBDim() != 3 && corr > 0)
throw new AlgorithmException(
"For now correlated noise is available only to 3 channel input, sorry");
int xDim = inputImage.getXDim();
int yDim = inputImage.getYDim();
int tDim = inputImage.getTDim();
int zDim = inputImage.getZDim();
for (int t = 0; t < tDim; t++)
for (int z = 0; z < zDim; z++)
for (int x = 0; x < xDim; x++)
for (int y = 0; y < yDim; y++) {
double[] d = inputImage.getVectorPixelXYZTDouble(x, y,
z, t);
double[] v = null;
if (corr > 0) {
double[] noise = new double[3];
noise[0] = rand.nextDouble();
noise[1] = rand.nextDouble();
noise[2] = rand.nextDouble();
try {
v = (double[]) new Correlator().process(noise, sigma);
} catch (PelicanException e) {
e.printStackTrace();
}
} else {
v = new double[inputImage.getBDim()];
for (int i = 0; i < inputImage.getBDim(); i++)
v[i] = sdev * (rand.nextDouble() - 0.5) * 2;
}
for (int i = 0; i < inputImage.getBDim(); i++) {
d[i] += v[i];
if (d[i] < 0.0)
d[i] = 0.0;
else if (d[i] > 1.0)
d[i] = 1.0;
}
outputImage.setVectorPixelXYZTDouble(x, y, z, t, d);
}
}
/**
* Adds uniformly distributed noise to a given image (3 bands max)
*
* @param inputImage Input image
* @param sdev Deviation between [0;1], should not be considered as standard deviation
* @param corr Correlation between bands (identical between each bands)
* @return Noisy image
*/
public static Image exec(Image inputImage, double sdev, double corr)
{
return (Image) new Uniform().process(inputImage,sdev,corr);
}
}