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 gaussian distributed noise to a given image's hue band * * @author ?, Benjamin Perret * @TODO check if keeping multivariate noise is necessary */ public class HueGaussian extends Algorithm { /** * Input image */ public Image inputImage; /** * Noisy result */ public Image outputImage; /** * Standard deviation of noise in [0;1] */ public double sdev; /** * Correlation degree in [0;1] */ public double corr; /** * Constructor * */ public HueGaussian() { 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.nextGaussian(); noise[1] = rand.nextGaussian(); noise[2] = rand.nextGaussian(); 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.nextGaussian(); } // only to the hue band // and attention to periodicity d[0] += v[0]; while(d[0]<0.0 || d[0]>1.0) { if (d[0] < 0.0) d[0] += 1.0; else if (d[0] > 1.0) d[0] -= 1.0; } outputImage.setVectorPixelXYZTDouble(x, y, z, t, d); } } } } } /** * Adds gaussian distributed noise to a given image's hue band * * @param inputImage input image * @param sdev deviation of noise * @param corr correlation between band * @return noisy image */ public static Image exec(Image inputImage, double sdev, double corr) { return (Image) new HueGaussian().process(inputImage,sdev,corr); } }