package fr.unistra.pelican.algorithms.morphology.binary;
import java.awt.Point;
import java.util.ArrayList;
import fr.unistra.pelican.Algorithm;
import fr.unistra.pelican.AlgorithmException;
import fr.unistra.pelican.BooleanImage;
import fr.unistra.pelican.Image;
import fr.unistra.pelican.algorithms.arithmetic.Inversion;
import fr.unistra.pelican.algorithms.logical.OR;
import fr.unistra.pelican.util.Point4D;
import fr.unistra.pelican.util.morphology.FlatStructuringElement2D;
/**
* This class performs a binary rectangular HMT with various size. background SE
* is the one pixel size perimeter of the rectangle as foreground is the
* rectangle of size alpha*rectangle size centered at the center of the
* rectangle.
*
* @author Jonathan Weber
*/
public class BinaryRectangularVariableHMT extends Algorithm {
/**
* Image to be processed
*/
public Image inputImage;
/**
* Inferior limit of rectangule X value
*/
public Integer Xmin;
/**
* Superior limit of rectangule X value
*/
public Integer Xmax;
/**
* Inferior limit of rectangule Y value
*/
public Integer Ymin;
/**
* Superior limit of rectangule Y value
*/
public Integer Ymax;
/**
* Resulting picture
*/
public BooleanImage outputImage;
/**
* Orientation angle of the rectangle. Default is 0
*/
public Double angle = 0.;
/**
* Step for size variance Default is 2
*/
public Integer step = 2;
/**
* ratio of foreground SE Default is 0.6
*/
public double alpha = 0.6;
/**
* Constructor
*
*/
public BinaryRectangularVariableHMT() {
super.inputs = "inputImage,Xmin,Xmax,Ymin,Ymax";
super.options = "step,alpha,angle";
super.outputs = "outputImage";
}
public void launch() throws AlgorithmException {
int XDim = inputImage.getXDim();
int YDim = inputImage.getYDim();
Image inversion = (Image) new Inversion().process(inputImage);
outputImage = new BooleanImage(inputImage.getXDim(), inputImage.getYDim(),
inputImage.getZDim(), inputImage.getTDim(), 1);
outputImage.fill(0.);
Point pointsTab[][] = new Point[XDim][YDim];
for (int i = 0; i < XDim; i++)
for (int j = 0; j < YDim; j++) {
pointsTab[i][j] = new Point();
pointsTab[i][j].x = Xmax + 1;
pointsTab[i][j].y = Ymax + 1;
}
for (int Tx = Xmin; Tx <= Xmax; Tx += step) {
BooleanImage eroHMarker = new BooleanImage(inputImage.getXDim(),
inputImage.getYDim(), inputImage.getZDim(), inputImage.getTDim(), 1);
eroHMarker.fill(0.);
// Computation of the horizontal erosion
BooleanImage fse;
// if (angle != 0.)
fse = FlatStructuringElement2D.createLineFlatStructuringElement((int) (alpha * Tx),
angle);
// fse = FlatStructuringElement2D.rotate(FlatStructuringElement2D
// .createHorizontalLineFlatStructuringElement((int) (alpha * Tx)),
// angle);
// else
// fse = FlatStructuringElement2D
// .createHorizontalLineFlatStructuringElement((int) (alpha * Tx))/* .rotate(angle) */;
BinaryErosion erosion = new BinaryErosion();
ArrayList<Object> inputs = new ArrayList<Object>(3);
inputs.add(inputImage);
inputs.add(fse);
inputs.add(2);
inputs.add(true);
erosion.setInput(inputs);
Point4D[] points = fse.foreground();
for (int x = 0; x < XDim; x++)
for (int y = 0; y < YDim; y++) {
if (pointsTab[x][y].x > Tx) {
boolean result = erosion.getMin(x, y, 0, 0, 0, points);
if (result) {
eroHMarker.setPixelBoolean(x, y, 0, 0, 0, true);
} else {
pointsTab[x][y].x = Tx;
}
}
}
for (int Ty = Ymin; Ty <= Ymax; Ty += step) {
// Computation of the Vertical erosion
BooleanImage eroVMarker = new BooleanImage(inputImage.getXDim(),
inputImage.getYDim(), inputImage.getZDim(), inputImage.getTDim(), 1);
eroVMarker.fill(0.);
// if (angle != 0.)
fse = FlatStructuringElement2D.createLineFlatStructuringElement((int) (alpha * Ty),
angle+90);
// fse = FlatStructuringElement2D.rotate(FlatStructuringElement2D
// .createVerticalLineFlatStructuringElement((int) (alpha * Ty)),
// angle);
// else
// fse = FlatStructuringElement2D
// .createVerticalLineFlatStructuringElement((int) (alpha * Ty));
erosion = new BinaryErosion();
inputs = new ArrayList<Object>(3);
inputs.add(eroHMarker);
inputs.add(fse);
inputs.add(2);
inputs.add(true);
erosion.setInput(inputs);
points = fse.foreground();
for (int x = 0; x < XDim; x++)
for (int y = 0; y < YDim; y++) {
if (pointsTab[x][y].x > Tx && pointsTab[x][y].y > Ty) {
boolean result = erosion.getMin(x, y, 0, 0, 0, points);
if (result) {
eroVMarker.setPixelBoolean(x, y, 0, 0, 0, true);
} else {
pointsTab[x][y].y = Ty;
}
}
}
// Computation of the background erosion
BooleanImage eroBG = new BooleanImage(inputImage.getXDim(), inputImage
.getYDim(), inputImage.getZDim(), inputImage.getTDim(), 1);
eroBG.fill(0.);
fse = new BooleanImage(Tx, Ty, 1, 1, 1);
fse.resetCenter();
for (int k = 0; k < Tx; k++)
for (int l = 0; l < Ty; l++) {
if (k == 0 | k == (Tx - 1) | l == 0 | l == (Ty - 1))
fse.setPixelXYBoolean(k, l, true);
else
fse.setPixelXYBoolean(k, l, false);
}
if (angle != 0.)
fse = FlatStructuringElement2D.rotate(fse, angle);
erosion = new BinaryErosion();
inputs = new ArrayList<Object>(3);
inputs.add(inversion);
inputs.add(fse);
inputs.add(2);
inputs.add(true);
erosion.setInput(inputs);
points = fse.foreground();
for (int x = 0; x < XDim; x++)
for (int y = 0; y < YDim; y++) {
// if(pointsTab[x][y].x>Tx&&pointsTab[x][y].y>Ty)
if (eroVMarker.getPixelBoolean(x, y, 0, 0, 0)) {
boolean result = erosion.getMin(x, y, 0, 0, 0, points);
if (result) {
eroBG.setPixelBoolean(x, y, 0, 0, 0, true);
}
}
}
//eroBG=eroVMarker.copyImage(true);
outputImage = (BooleanImage) new OR().process(outputImage, eroBG);
}
}
}
/**
* This method performs a binary rectangular HMT with various size.
*
* @param InputImage
* image to be processed
* @param xmin
* Inferior limit of rectangule X value
* @param xmax
* Superior limit of rectangule X value
* @param ymin
* Inferior limit of rectangule Y value
* @param ymax
* Superior limit of rectangule Y value
* @return Rectangular variable HMT picture
*/
public static BooleanImage exec(Image InputImage, Integer xmin, Integer xmax,
Integer ymin, Integer ymax) {
return (BooleanImage) new BinaryRectangularVariableHMT().process(
InputImage, xmin, xmax, ymin, ymax);
}
public static BooleanImage exec(Image InputImage, Integer xmin, Integer xmax,
Integer ymin, Integer ymax,int step,double alpha,double angle) {
return (BooleanImage) new BinaryRectangularVariableHMT().process(
InputImage, xmin, xmax, ymin, ymax,step,alpha,angle);
}
public static BooleanImage exec(Image InputImage, Integer xmin, Integer xmax,
Integer ymin, Integer ymax,int step,double angle) {
return (BooleanImage) new BinaryRectangularVariableHMT().process(
InputImage, xmin, xmax, ymin, ymax,step,null,angle);
}
public static BooleanImage exec(Image InputImage, Integer xmin, Integer xmax,
Integer ymin, Integer ymax,double angle) {
return (BooleanImage) new BinaryRectangularVariableHMT().process(
InputImage, xmin, xmax, ymin, ymax,null,null,angle);
}
}