package fr.unistra.pelican.algorithms.segmentation.labels;
import fr.unistra.pelican.Algorithm;
import fr.unistra.pelican.AlgorithmException;
import fr.unistra.pelican.BooleanImage;
import fr.unistra.pelican.Image;
import fr.unistra.pelican.InvalidNumberOfParametersException;
import fr.unistra.pelican.InvalidTypeOfParameterException;
import fr.unistra.pelican.algorithms.arithmetic.DeleteSmallValues;
import fr.unistra.pelican.algorithms.arithmetic.EuclideanNorm;
import fr.unistra.pelican.algorithms.io.ImageLoader;
import fr.unistra.pelican.algorithms.morphology.gray.GrayGradient;
import fr.unistra.pelican.algorithms.segmentation.Watershed;
import fr.unistra.pelican.algorithms.visualisation.Viewer2D;
import fr.unistra.pelican.util.morphology.FlatStructuringElement2D;
/**
* Draw a frontier (in white) over an image. The frontiers image is a one band
* image and input image can have more than one bands.
*
* @author Derivaux, Lefevre, Régis Witz (management of colour option).
*/
public class DrawFrontiersOnImage extends Algorithm {
/** Input Image. */
public Image inputImage;
/** Border image (BooleanImage). */
public BooleanImage frontiers;
/** Resulting image. */
public Image outputImage;
/** Optional contour coloring colour value. */
public double[] colour = null;
/** Constructor. */
public DrawFrontiersOnImage() {
super.inputs = "inputImage,frontiers";
super.options = "colour";
super.outputs = "outputImage";
}
/*
* (non-Javadoc)
*
* @see fr.unistra.pelican.Algorithm#launch()
*/
public void launch() throws AlgorithmException {
this.outputImage = this.inputImage.copyImage( false );
if ( this.colour == null ) {
// we need to initialize the colour field
int bdim = this.inputImage.getBDim();
this.colour = new double[ bdim ];
for ( int b = 0 ; b < bdim ; b++ ) this.colour[b] = new Double( 1.0 );
}
int xDim = outputImage.getXDim();
int yDim = outputImage.getYDim();
int zDim = outputImage.getZDim();
int tDim = outputImage.getTDim();
int bDim = outputImage.getBDim();
for (int t = 0; t < tDim; t++)
for (int z = 0; z < zDim; z++)
for (int y = 0; y < yDim; y++)
for (int x = 0; x < xDim; x++)
for ( int b = 0; b < bDim; b++ ) {
if ( frontiers.getPixelXYZTBoolean( x,y,z,t ) )
outputImage.setPixelDouble( x,y,z,t,b, this.colour[b] );
else
outputImage.setPixelDouble( x,y,z,t,b,
inputImage.getPixelDouble( x,y,z,t,b) );
}
}
public static void main(String[] args) {
String file = "samples/remotesensing1.png";
if (args.length > 0)
file = args[0];
BooleanImage se3 = FlatStructuringElement2D
.createSquareFlatStructuringElement(3);
try {
// Load the image
Image source = (Image) new ImageLoader().process(file);
new Viewer2D().process(source, "Image " + file);
// Compute the gradient on each band
Image work = (Image) new GrayGradient().process(source, se3);
// Compute the euclidian distance of the gradient
work = (Image) new EuclideanNorm().process(work);
work = (Image) new DeleteSmallValues().process(work, 0.2);
// Process a watershed transformation
work = (Image) new Watershed().process(work);
Image frontiers = (Image) new FrontiersFromSegmentation()
.process(new DeleteFrontiers().process(work));
// View it
new Viewer2D().process(new DrawFrontiersOnImage().process(source,
frontiers), "Frontiers of " + file);
} catch (InvalidTypeOfParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidNumberOfParametersException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/* Draw some frontiers on an image. */
public static Image exec(Image image, BooleanImage frontiers) {
return (Image) new DrawFrontiersOnImage().process( image, frontiers );
}
/* Draw some frontiers on an image with an specified colour. */
public static Image exec( Image image, BooleanImage frontiers, double[] colour ) {
return (Image) new DrawFrontiersOnImage().process( image, frontiers, colour );
}
}