/** * */ package fr.unistra.pelican.algorithms.spatial; import java.awt.Point; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.AlgorithmException; import fr.unistra.pelican.DoubleImage; import fr.unistra.pelican.Image; import fr.unistra.pelican.algorithms.visualisation.Viewer2D; import fr.unistra.pelican.util.morphology.GrayStructuringElement; /** * Performs convolution of an image with a mask (GrayStructuringElement) Result * is normalized (divided by the sum of structuring element values) if requested * Works on double precision * * @author Benjamin Perret * * TODO merge with convolution * */ public class Convolution2 extends Algorithm { /** * Constant parameter to request normalization */ public static int NORMALIZE = 0; /** * Constant parameter to request no normalization */ public static int NO_NORMALIZE = 1; /** * Input Image */ public Image inputImage; /** * Input structuring element */ public GrayStructuringElement se; /** * Input normalization argument */ public int normalize = 1; /** * Output Image */ public Image outputImage; /** * Constructor * */ public Convolution2() { super(); super.inputs = "inputImage,se"; super.options="normalize"; super.outputs = "outputImage"; } /** * Compute convolution for a given point * * @param x * @param y * @param z * @param t * @param b * @return */ public double getVal(int x, int y, int z, int t, int b, boolean f) { double sum = 0.0; double tmp = 0.0; boolean flag = false; for (int j = 0; j < se.getYDim(); j++) for (int i = 0; i < se.getXDim(); i++){ /* * Take inverse structuring element */ int valX = x - se.getCenter().x + i; int valY = y - se.getCenter().y + j; if (valX >= 0 && valX < inputImage.getXDim() && valY >= 0 && valY < inputImage.getYDim()) { tmp += inputImage.getPixelDouble(valX, valY, z, t, b) * se.getPixelXYDouble(i, j); if (f) sum += se.getPixelXYDouble(i, j); flag = true; } } if (f) tmp /= sum; // FIXME: Strange, if nothing is under the se, what is the right way? return (flag == true) ? tmp : inputImage.getPixelDouble(x, y, z, t, b); } /* * (non-Javadoc) * * @see fr.unistra.pelican.Algorithm#launch() */ public void launch() throws AlgorithmException { outputImage = inputImage.copyImage(false); se = se.getReflection(); int xDim = inputImage.getXDim(); int yDim = inputImage.getYDim(); int tDim = inputImage.getTDim(); int bDim = inputImage.getBDim(); int zDim = inputImage.getZDim(); 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; x < xDim; x++) for (int y = 0; y < yDim; y++) outputImage.setPixelDouble(x, y, z, t, b, getVal(x, y, z, t, b, normalize == NORMALIZE)); } /*public static void main(String[] args) { Image im = new DoubleImage(256, 256, 1, 1, 1); im.setPixelXYDouble(50, 50, 1.0); im.setPixelXYDouble(51, 50, 1.0); im.setPixelXYDouble(50, 51, 1.0); im.setPixelXYDouble(51, 51, 1.0); im.setPixelXYDouble(50, 52, 1.0); im.setPixelXYDouble(52, 50, 1.0); im.setPixelXYDouble(52, 51, 1.0); im.setPixelXYDouble(51, 52, 1.0); im.setPixelXYDouble(52, 52, 1.0); im.setPixelXYDouble(100, 100, 1.0); im.setPixelXYDouble(102, 100, 1.0); new Viewer2D().process(im, "op"); GrayStructuringElement se = new GrayStructuringElement(21, 21, new Point(10, 10)); double[] vals = GaussianMask.createLinearMask(21, 0.02); se.setPixels(vals); Image im2 = (Image) new Convolution2().process(im, se, Convolution2.NO_NORMALIZE); // Image im3=Convolution.process(im, se,Convolution.NORMALIZE); // Viewer2D.exec(se,"PSF"); new Viewer2D().process(((DoubleImage) im2).scaleToZeroOne(), "NO_NORMALIZE"); // Viewer2D.exec(((DoubleImage)im3).scaleToZeroOne(),"NORMALIZE"); }*/ /** * Standard convolution for linear filters * @param input Input image * @param kernel Structuring element used for the convolution * @return Output image */ public static Image exec(Image input, GrayStructuringElement kernel) { return (Image) new Convolution2().process(input,kernel); } /** * Standard convolution for linear filters * @param input Input image * @param kernel Structuring element used for the convolution * @param normalisation Specify if result is normalized * @return Output image */ public static Image exec(Image input, GrayStructuringElement kernel, int normalisation) { return (Image) new Convolution2().process(input,kernel,normalisation); } }