package fr.unistra.pelican.algorithms.morphology.gray;
import fr.unistra.pelican.Algorithm;
import fr.unistra.pelican.AlgorithmException;
import fr.unistra.pelican.BooleanImage;
import fr.unistra.pelican.Image;
import fr.unistra.pelican.util.Point4D;
import fr.unistra.pelican.util.morphology.FlatStructuringElement3D;
/**
* This class performs a standard morphological lambda-leveling
*
* (warning actually just X,Y and T dim are taken into account)
*
* TODO : Put in ND
*
*
* @author Abdullah
*/
public class GrayLeveling extends Algorithm {
/**
* The input image
*/
public Image input;
/**
* The marker image
*/
public Image marker;
/**
* The lambda parameter
*/
public int lambda;
/**
* The output image
*/
public Image output;
private boolean DEBUG = false;
/**
* Default constructor
*/
public GrayLeveling() {
super.inputs = "input,marker,lambda";
super.outputs = "output";
}
/**
* Performs a standard morphological lambda-leveling
* @param input The input image
* @param marker The marker image
* @param lambda The lambda parameter
* @return The output image
*/
public static Image exec (Image input, Image marker, int lambda) {
return (Image) new GrayLeveling().process(input,marker,lambda);
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.Algorithm#launch()
*/
public void launch() throws AlgorithmException {
// checking only the immediate 10-neighborhood
BooleanImage se = FlatStructuringElement3D.createTemporal10ConnectivityFlatStructuringElement();
Point4D[] points = se.foreground();
if (lambda < 0 || lambda > 254)
throw new AlgorithmException("Lambda value out of bounds!");
Image tmp = null;
output = marker.copyImage(true);
int i = 0;
do {
tmp = output;
output = level(output, points, se);
if (DEBUG) System.err.println("Iteration " + (i++));
} while (output.equals(tmp) == false);
}
private Image level(Image img, Point4D[] points, BooleanImage se)
{
Image tmp = img.copyImage(true);
for (int t = 0; t < img.getTDim(); t++){
for (int y = 0; y < img.getYDim(); y++) {
for (int x = 0; x < img.getXDim(); x++) {
for (int b = 0; b < input.getBDim(); b++) {
if ( !input.isPresentXYTB( x, y, t, b ) ) continue;
int g = tmp.getPixelXYTBByte(x, y, t, b);
int f = input.getPixelXYTBByte(x, y, t, b);
if (g > f + lambda)
tmp.setPixelXYTBByte(x, y, t, b, getLowerLevelledGray(tmp,
x, y, t, b, points, se));
else if (f > g + lambda)
tmp.setPixelXYTBByte(x, y, t, b, getUpperLevelledGray(tmp,
x, y, t, b, points, se));
else
; // f == g do nothing
}
}
}
}
return tmp;
}
private int getLowerLevelledGray(Image img, int x, int y, int t, int b, Point4D[] points, BooleanImage se)
{
double min = 255;
for (int i = 0; i < points.length; i++) {
int _x = x - se.getCenter().x + points[i].x;
int _y = y - se.getCenter().y + points[i].y;
int _t = t - se.getCenter().t + points[i].t;
if ( _x >= 0 && _x < input.getXDim()
&& _y >= 0 && _y < input.getYDim()
&& _t >= 0 && _t < input.getTDim()
&& input.isPresentXYTB( _x,_y,_t,b ) ) {
int p = img.getPixelXYTBByte(_x, _y, _t, b);
if (min > p)
min = p;
}
}
return (int) Math.max(min, input.getPixelXYTBByte(x, y, t, b));
}
private int getUpperLevelledGray(Image img, int x, int y, int t, int b,
Point4D[] points, BooleanImage se) {
double max = 0;
for (int i = 0; i < points.length; i++) {
int _x = x - se.getCenter().x + points[i].x;
int _y = y - se.getCenter().y + points[i].y;
int _t = t - se.getCenter().t + points[i].t;
if ( _x >= 0 && _x < input.getXDim()
&& _y >= 0 && _y < input.getYDim()
&& _t >= 0 && _t < input.getTDim()
&& input.isPresentXYTB( _x, _y, _t, b ) ) {
int p = img.getPixelXYTBByte(_x, _y, _t, b);
if (max < p)
max = p;
}
}
return (int) Math.min(max, input.getPixelXYTBByte(x, y, t, b));
}
}