package fr.unistra.pelican.algorithms.spatial;
import fr.unistra.pelican.Algorithm;
import fr.unistra.pelican.AlgorithmException;
import fr.unistra.pelican.Image;
/**
* Performs a Gaussian Smoothing (by the use of Gaussian masks)
*
* @author Dany DAMAJ
*/
public class GaussianSmoothing extends Algorithm {
/**
* Input image
*/
public Image input;
/**
* Size of the mask
*/
public Integer size;
/**
* Standard deviation of the gaussian
*/
public Float sig;
/**
* Output image
*/
public Image output;
/**
* Gaussian mask
*/
public float gaussianMask[][];
/**
* ???
*/
public int xDim, yDim;
/**
* Constructor
*
*/
public GaussianSmoothing() {
super();
super.inputs = "input,size,sig";
super.outputs = "output";
}
/*
* (non-Javadoc)
*
* @see fr.unistra.pelican.Algorithm#launch()
*/
public void launch() throws AlgorithmException {
computeGaussianMask();
xDim = input.getXDim();
yDim = input.getYDim();
int tDim = input.getTDim();
int bDim = input.getBDim();
int zDim = input.getZDim();
output = input.copyImage(false);
for (int b = 0; b < bDim; b++)
for (int t = 0; t < tDim; t++)
for (int z = 0; z < zDim; z++)
for (int x = 0/* (size - 1) / 2 */; x < xDim /*- (size-1)/2*/; x++)
for (int y = 0/* (size - 1) / 2 */; y < yDim /*- (size - 1) / 2*/; y++) {
double tmp = applyGaussianMask(x, y, z, t, b);
output.setPixelDouble(x, y, z, t, b, tmp);
}
}
/*
*
*/
private double applyGaussianMask(int x, int y, int z, int t, int b) {
double res = 0.0;
if (x >= (size - 1) / 2 && x < xDim - (size - 1) / 2
&& y >= (size - 1) / 2 && y < yDim - (size - 1) / 2) { // normal
// case
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
res += gaussianMask[i][j]
* input.getPixelDouble(x + i - (size - 1) / 2, y
+ j - (size - 1) / 2, z, t, b);
} else { // the mask overflows the image
float real_sum = 0.0f;
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
if (x + i - (size - 1) / 2 >= 0
&& x + i - (size - 1) / 2 < xDim
&& y + j - (size - 1) / 2 >= 0
&& y + j - (size - 1) / 2 < yDim)
real_sum += gaussianMask[i][j];
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
if (x + i - (size - 1) / 2 >= 0
&& x + i - (size - 1) / 2 < xDim
&& y + j - (size - 1) / 2 >= 0
&& y + j - (size - 1) / 2 < yDim)
res += gaussianMask[i][j]
* input.getPixelDouble(x + i - (size - 1) / 2,
y + j - (size - 1) / 2, z, t, b)
/ real_sum;
}
return res;
}
/*
*
*/
public void computeGaussianMask(int sizeDesired, float sigma) {
size = sizeDesired;
sig = sigma;
computeGaussianMask();
}
/*
*
*/
private void computeGaussianMask() {
gaussianMask = new float[size][size];
float sum = 0.0f;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
gaussianMask[i][j] = G(i - (size - 1) / 2, j - (size - 1) / 2);
sum += gaussianMask[i][j];
}
}
// normalisation
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
gaussianMask[i][j] /= sum;
}
}
}
/*
*
*/
private float G(int i, int j) {
return (float) (Math.pow(Math.E, -((double) (i * i + j * j))
/ (2.0 * sig * sig)) / (2.0 * Math.PI * sig * sig));
}
/**
* Performs a Gaussian Smoothing (by the use of Gaussian masks)
* @param input Input image
* @param sigma Standard deviation of the gaussian
* @return Ouput image
*/
public static Image exec(Image image, int maskSize, float sigma) {
return (Image) new GaussianSmoothing().process(image,maskSize,sigma);
}
}