package fr.unistra.pelican.algorithms.segmentation;
import java.awt.Point;
import fr.unistra.pelican.Algorithm;
import fr.unistra.pelican.AlgorithmException;
import fr.unistra.pelican.ByteImage;
import fr.unistra.pelican.Image;
import fr.unistra.pelican.PelicanException;
import fr.unistra.pelican.algorithms.conversion.RGBToGray;
import fr.unistra.pelican.algorithms.edge.Sobel;
import fr.unistra.pelican.algorithms.geometric.Crop2D;
import fr.unistra.pelican.algorithms.io.ImageLoader;
import fr.unistra.pelican.algorithms.visualisation.Viewer2D;
import fr.unistra.pelican.util.snake.Snake;
/**
* segment an image using a snake model
*/
public class SnakeSegmentation extends Algorithm {
public Image inputImage;
public Image outputImage;
public Snake snake;
public Point init1;
public Point init2;
public boolean writeImage=true;
private boolean debug = false;
/**
* Constructor
*
*/
public SnakeSegmentation() {
super.inputs = "inputImage,init1,init2";
super.outputs = "outputImage";
}
/*
* (non-Javadoc)
*
* @see fr.unistra.pelican.Algorithm#launch()
*/
public void launch() throws AlgorithmException {
// Define initial snake
snake = new Snake(20, init1, init2);
// Initialise the parameters
int iterations = 50;
int zoom = 10;
snake.setNeighbourhood(3);
snake.setZoom(zoom);
snake.setGradientThreshold(150);
snake.setColorThreshold(50);
snake.setCoefficients(1, 1, 1, 1, 1, 1, 2);
// Initialise the image data by limiting the processing area
try {
Image data = Crop2D.exec(inputImage, init1.x - zoom, init1.y
- zoom, init2.x + zoom, init2.y + zoom);
data = inputImage;
snake.setData(data);
data = RGBToGray.exec(data);
Image gradient = Sobel.exec(data, Sobel.NORM);
snake.setGradient(gradient);
} catch (PelicanException ex) {
throw new AlgorithmException(ex.getMessage());
}
// debug info
Image debugImage = null;
int debugSampling = 1;
if (debug) {
debugImage = new ByteImage(inputImage.getXDim(), inputImage
.getYDim(), iterations / debugSampling, inputImage
.getTDim(), inputImage.getBDim());
debugImage.copyAttributes(inputImage);
}
boolean convergence = false;
int k;
for (k = 0; k < iterations && !convergence; k++) {
convergence = snake.deform();
snake.crop(init1, init2);
snake.deleteDoubles(false);
// snake.deleteCrossings(false);
snake.repareCrossings(false);
if (debug)
if (k % debugSampling == 0)
debugImage.setImage4D(snake.drawOnImage(inputImage, true,
true), k / debugSampling, Image.Z);
}
if (writeImage)
outputImage = snake.drawOnImage(inputImage, true, true);
else
outputImage = null;
if (debug) {
System.out.println(k + " iterations");
try {
Viewer2D.exec(debugImage, "iterations");
} catch (PelicanException ex) {
throw new AlgorithmException(ex.getMessage());
}
}
}
public static void checkPoints(Image inputImage, Point init1, Point init2) {
if (init1.x < 0)
init1.x = 0;
if (init1.x >= inputImage.getXDim())
init1.x = inputImage.getXDim() - 1;
if (init1.y < 0)
init1.y = 0;
if (init1.y >= inputImage.getYDim())
init1.y = inputImage.getYDim() - 1;
if (init2.x < 0)
init2.x = 0;
if (init2.x >= inputImage.getXDim())
init2.x = inputImage.getXDim() - 1;
if (init2.y < 0)
init2.y = 0;
if (init2.y >= inputImage.getYDim())
init2.y = inputImage.getYDim() - 1;
}
public static void main(String args[]) throws PelicanException {
Image image = (Image) new ImageLoader().process("samples/foot.png");
Point p1 = new Point(image.getXDim() * 7 / 10, image.getYDim() * 4 / 10);
Point p2 = new Point(image.getXDim() * 9 / 10, image.getYDim() * 6 / 10);
Image output = (Image) new SnakeSegmentation().process(image, p1, p2);
Viewer2D.exec(output, "snake");
}
}