package fr.unistra.pelican.demos.applied.remotesensing;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Calendar;
import fr.unistra.pelican.Image;
import fr.unistra.pelican.PelicanException;
import fr.unistra.pelican.algorithms.applied.remotesensing.building.OriginalBinaryBuildingDetection;
import fr.unistra.pelican.algorithms.arithmetic.Maximum;
import fr.unistra.pelican.algorithms.io.ImageLoader;
import fr.unistra.pelican.algorithms.io.ImageSave;
import fr.unistra.pelican.algorithms.logical.AND;
import fr.unistra.pelican.algorithms.morphology.binary.BinaryGradient;
import fr.unistra.pelican.algorithms.segmentation.ManualThresholding;
import fr.unistra.pelican.algorithms.statistics.DetectionQualityEvaluation;
import fr.unistra.pelican.algorithms.visualisation.Viewer2D;
import fr.unistra.pelican.util.morphology.FlatStructuringElement2D;
/**
* Demo class for MM-based building detection
*
* @author lefevre,weber
*
*/
public class BuildingDetectionDemo {
// Attributs
boolean view = false;
boolean debug = true;
boolean save = true;
boolean computeDuration = true;
String dataset = "";
String bMode = "";
String fMode = "";
String experiment = "";
String duration = "";
PrintStream out = System.out;
int repeat = -1;
int min = -1;
int max = 0;
int xmin = -1;
int xmax = -1;
int ymin = -1;
int ymax = -1;
int binMode = OriginalBinaryBuildingDetection.BINARISATION_CLUSTER;
double binThr = 0.8;
int binParam = 1;
int filterMode = OriginalBinaryBuildingDetection.FILTER_GRANULOMETRY;
boolean globalTTR = true;
double minRatio = 0;
int granStep = 2;
int occo = 5;
String[] command = null;
double angle = 15.;
// Default path
String path = "/home/lefevre/data/teledetection/bati/";
/**
* @param args
*/
public static void main(String[] args) throws PelicanException {
// Possible use of hard-coded filename
/*
* String file="pescara_input.bmp";String reference="pescara_ref.bmp";
* String file="bishkek_input.bmp";String reference="bishkek_ref.bmp";
* String file="strasbourg_input.bmp";String reference="strasbourg_ref.bmp";
* String file="pesc_input.bmp";String reference="pesc_ref.bmp"; String
* file="pescs_input.bmp";String reference="pescs_ref.bmp"; String
* file="qbs1_input.png";String reference="qbs1_ref.png"; String
* file="qbs2_input.png";String reference="qbs2_ref.png"; String
* file="ortho_input.png";String reference="ortho_ref.png";
*/
BuildingDetectionDemo demo = new BuildingDetectionDemo();
demo.command = args.clone();
// Example of hard-coded use of evaluation mode
// demo.evaluateResult("/home/lefevre/data/global/teledetection/bati/qbs1_ref.png","/home/lefevre/publis/work/rig/tests/resultats/results-25nov2006/qbs1-manual/0-smooth.png","qbs1-smooth-stats.txt");
// Affichage des paramᅵtres
if (args.length == 0) {
afficheSimple();
return;
}
if (args[0].equalsIgnoreCase("help")) {
afficheComplet();
return;
}
// Mode evaluation
else if (args[0].equalsIgnoreCase("evaluate")) {
System.out.println("Evaluation Mode");
switch (args.length) {
case 3:
demo.evaluateResult(args[1], args[2]);
break;
case 4:
demo.evaluateResult(args[1], args[2], args[3], false);
break;
case 5:
demo.evaluateResult(args[1], args[2], args[3], args[4]
.equalsIgnoreCase("append"));
break;
default:
System.out.println("evaluate needs between 2 and 4 parameters");
}
return;
}
// Mode detection
else if (args[0].equalsIgnoreCase("detect")) {
System.out.println("Detection Mode");
try {
demo.configure(args);
} catch (Exception e) {
System.out.println(e.getMessage());
}
// Benchmark
demo.bench();
}
}
private void bench() {
// Dᅵmarrage
long t1 = System.currentTimeMillis();
System.out.println(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + "h "
+ Calendar.getInstance().get(Calendar.MINUTE) + "m "
+ Calendar.getInstance().get(Calendar.SECOND) + "s");
// Chargement
String file = dataset + "_input.png";
String reference = dataset + "_ref.png";
Image inputImage = ImageLoader.exec(path + file);
if (view)
Viewer2D.exec(inputImage, "input");
// Calcul du nombre d'itᅵrations
int iterations = Math.abs(repeat);
for (int d = 1; d < iterations + 1; d++) {
// Paramᅵtres
experiment = dataset + "-" + bMode + "-" + fMode;
if (iterations != 1)
experiment = experiment + "-" + d + "0";
experiment = experiment + "/";
File f = new File(experiment);
f.mkdir();
if (repeat != -1 || binThr == -1)
binThr = (double) (d) / (iterations + 1);
if (save)
ImageSave.exec(inputImage, experiment + "input.png");
// Dᅵtection
// Image outputImage =
// BinaryBuildingDetection.exec(inputImage,xmin,ymin,xmax,ymax);
Image outputImage = (Image) new OriginalBinaryBuildingDetection().process(
inputImage, xmin, ymin, xmax, ymax, view, save, debug, null, binThr,
binMode, filterMode, 0, angle, binParam, granStep, globalTTR, minRatio,
occo, experiment);
// Image outputImage =
// BinaryBuildingDetection.exec(inputImage,binMode,binParam,binThr,filterMode,angle,xmin,ymin,xmax,ymax);
// Sauvegarde des rᅵsultats
if (save)
ImageSave.exec(outputImage, experiment + "mask.png");
Image contour = BinaryGradient.exec(outputImage, FlatStructuringElement2D
.createSquareFlatStructuringElement(3));
Image visu = Maximum.exec(inputImage, contour);
if (view)
Viewer2D.exec(visu, "visu2");
if (save)
ImageSave.exec(visu, experiment + "result.png");
// Evaluation
Image ref = ImageLoader.exec(path + reference);
if (view && debug)
Viewer2D.exec(ref, "reference");
Image croise = AND.exec(outputImage, ref);
if (view && debug)
Viewer2D.exec(croise, "croisement");
Image contour2 = BinaryGradient.exec(croise, FlatStructuringElement2D
.createSquareFlatStructuringElement(3));
Image visu2 = Maximum.exec(inputImage, contour2);
if (view)
Viewer2D.exec(visu2, "visu2");
if (save)
ImageSave.exec(visu2, experiment + "correct.png");
// Statistiques
try {
out = new PrintStream(new FileOutputStream(experiment + "stats.txt"));
} catch (IOException ex) {
ex.printStackTrace();
}
writeHeader();
// Arrᅵt
long t2 = System.currentTimeMillis() - t1;
String duration = "Temps CPU : " + (t2 / 1000) + " secondes";
if (computeDuration)
out.println(duration + "\n");
System.out.println("Dᅵmo terminᅵe. " + duration);
System.out.println(Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
+ "h " + Calendar.getInstance().get(Calendar.MINUTE) + "m "
+ Calendar.getInstance().get(Calendar.SECOND) + "s");
out.println(DetectionQualityEvaluation.exec(outputImage, ref, true, true,
true));
}
}
private void writeHeader() {
out.print("Date : ");
out.print(Calendar.getInstance().get(Calendar.DATE) + "/");
out.print(Calendar.getInstance().get(Calendar.MONTH) + "/");
out.print(Calendar.getInstance().get(Calendar.YEAR) + " -- ");
out.print(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":");
out.print(Calendar.getInstance().get(Calendar.MINUTE) + ":");
out.print(Calendar.getInstance().get(Calendar.SECOND) + "\n");
out.print("Options : ");
for (int i = 0; i < command.length; i++)
out.print(command[i] + " ");
out.println();
out.println("Dataset : " + dataset);
out.println("Mode : " + bMode + " - " + fMode);
out.println("binThr : " + binThr + " / " + " Itᅵrations : " + repeat
+ " binParam: " + binParam);
out.println("Tailles : [" + xmin + "x" + ymin + " , " + xmax + "x" + ymax
+ "]");
out.println();
}
private void evaluateResult(String pathResult, String pathRef) {
// Options
out.print("Options : ");
for (int i = 0; i < command.length; i++)
out.print(command[i] + " ");
out.println();
out.println();
// Evaluation
Image imgResult = ManualThresholding
.exec(ImageLoader.exec(pathResult), 0.5);
Image imgRef = ManualThresholding.exec(ImageLoader.exec(pathRef), 0.5);
out.println(DetectionQualityEvaluation.exec(imgResult, imgRef, true, true,
true));
}
private void evaluateResult(String pathResult, String pathRef,
String pathOutput, boolean append) {
try {
out = new PrintStream(new FileOutputStream(pathOutput, append));
} catch (IOException ex) {
ex.printStackTrace();
}
evaluateResult(pathResult, pathRef);
}
private static void afficheComplet() {
System.out.println("BuildingDetectionDemo usage :");
System.out.println("\n evaluation mode :");
System.out
.println(" evaluate pathResult pathReference (pathOutput) (append)");
System.out.println("\t pathResult: path to the generated binary result");
System.out.println("\t pathReference: path to the reference binary image");
System.out
.println("\t pathOutput: path to the textual file used as output");
System.out
.println("\t append: if true, append the text at the end of the existing pathOutput file");
System.out.println("\n detection mode :");
System.out.println(" detect [-options]");
System.out
.println("\t -data name of the dataset (xxx_input.png and xxx_ref.png)");
System.out.println("\t -bmode binarisation method : auto, manual, cluster");
System.out.println("\t -fmode filtering method : auto, granulometry");
System.out
.println("\t -repeat number of iterations for varying parameter (threshold or percentage)");
System.out
.println("\t -threshold value of the threshold used in binarisation process (real between 0 and 1)");
System.out
.println("\t -view enable or disable image viewing (true or false)");
System.out.println("\t -debug enable or disable debugging (true or false)");
System.out
.println("\t -save enable or disable image saving (true or false)");
System.out.println("\t -min minimal size (height or width) of a building");
System.out.println("\t -max maximum size (height or width) of a building");
System.out.println("\t -xmin minimal height of a building");
System.out.println("\t -xmax maximum height of a building");
System.out.println("\t -ymin minimal width of a building");
System.out.println("\t -ymax maximum width of a building");
System.out
.println("\t -fusion maximum number of clusters in fusion process");
System.out
.println("\t -level color level of objects : 0 for black objects, 1 for white objects, 2 for both");
System.out.println("\t -binParam equivalent to -fusion or -level");
System.out
.println("\t -path specify the directory which contains data (optional)");
System.out.println("\t -angle set the step of the orientation(real > 0.");
}
private static void afficheSimple() {
System.out.println("BuildingDetectionDemo usage :");
System.out.println("\n evaluation mode :");
System.out
.println(" evaluate pathResult pathReference (pathOutput) (append)");
System.out.println("\t pathResult: path to the generated binary result");
System.out.println("\t pathReference: path to the reference binary image");
System.out
.println("\t pathOutput: path to the textual file used as output");
System.out
.println("\t append: if true, append the text at the end of the existing pathOutput file");
System.out.println("\n detection mode :");
System.out.println(" detect [-options]");
System.out
.println("\t -data name of the dataset (xxx_input.png and xxx_ref.png)");
System.out.println("\t -bmode binarisation method : auto, manual, cluster");
System.out.println("\t -fmode filtering method : auto, granulometry");
System.out
.println("\t -repeat number of iterations for varying parameter (threshold or percentage)");
System.out
.println("\t -threshold value of the threshold used in binarisation process (real between 0 and 1)");
System.out
.println("\t -view enable or disable image viewing (true or false)");
System.out.println("\t -debug enable or disable debugging (true or false)");
System.out
.println("\t -save enable or disable image saving (true or false)");
System.out.println("\t -min minimal size (height or width) of a building");
System.out.println("\t -max maximum size (height or width) of a building");
System.out.println("\t -xmin minimal height of a building");
System.out.println("\t -xmax maximum height of a building");
System.out.println("\t -ymin minimal width of a building");
System.out.println("\t -ymax maximum width of a building");
System.out
.println("\t -fusion maximum number of clusters in fusion process");
System.out
.println("\t -level color level of objects : 0 for black objects, 1 for white objects, 2 for both");
System.out.println("\t -binParam equivalent to -fusion or -level");
System.out
.println("\t -path specify the directory which contains data (optional)");
System.out.println("\t -angle set the step of the orientation(real > 0.");
}
private void configure(String[] args) throws Exception {
int i = 0;
try {
for (i = 0; i < args.length - 1; i++) {
if (args[i].equalsIgnoreCase("-data"))
dataset = args[i + 1];
else if (args[i].equalsIgnoreCase("-bMode"))
bMode = args[i + 1];
else if (args[i].equalsIgnoreCase("-repeat"))
repeat = Integer.parseInt(args[i + 1]);
else if (args[i].equalsIgnoreCase("-threshold")
|| args[i].equalsIgnoreCase("-seuil"))
binThr = Double.parseDouble(args[i + 1]);
else if (args[i].equalsIgnoreCase("-view"))
view = Boolean.parseBoolean(args[i + 1]);
else if (args[i].equalsIgnoreCase("-debug"))
debug = Boolean.parseBoolean(args[i + 1]);
else if (args[i].equalsIgnoreCase("-save"))
save = Boolean.parseBoolean(args[i + 1]);
else if (args[i].equalsIgnoreCase("-min"))
min = Integer.parseInt(args[i + 1]);
else if (args[i].equalsIgnoreCase("-max"))
max = Integer.parseInt(args[i + 1]);
else if (args[i].equalsIgnoreCase("-xmin"))
xmin = Integer.parseInt(args[i + 1]);
else if (args[i].equalsIgnoreCase("-xmax"))
xmax = Integer.parseInt(args[i + 1]);
else if (args[i].equalsIgnoreCase("-ymin"))
ymin = Integer.parseInt(args[i + 1]);
else if (args[i].equalsIgnoreCase("-ymax"))
ymax = Integer.parseInt(args[i + 1]);
else if (args[i].equalsIgnoreCase("-fusion")
|| args[i].equalsIgnoreCase("-level")
|| args[i].equalsIgnoreCase("-binParam"))
binParam = Integer.parseInt(args[i + 1]);
else if (args[i].equalsIgnoreCase("-globalTTR"))
globalTTR = Boolean.parseBoolean(args[i + 1]);
else if (args[i].equalsIgnoreCase("-minratio"))
minRatio = Double.parseDouble(args[i + 1]);
else if (args[i].equalsIgnoreCase("-occo"))
occo = Integer.parseInt(args[i + 1]);
else if (args[i].equalsIgnoreCase("-fMode"))
fMode = args[i + 1];
else if (args[i].equalsIgnoreCase("-path"))
path = args[i + 1];
else if (args[i].equalsIgnoreCase("-angle"))
angle = Double.parseDouble(args[i + 1]);
}
} catch (Exception ex) {
throw new Exception("Problᅵme avec paramᅵtre #" + i + " : " + args[i]
+ " " + args[i + 1]);
}
// configure sizes if set to default
if (max==0)
System.out.println("Error : max unknown !");
if (xmax == -1)
xmax = max;
if (ymax == -1)
ymax = max;
if (xmin == -1)
if (min == -1)
xmin = xmax / 2;
else
xmin = min;
if (ymin == -1)
if (min == -1)
ymin = ymax / 2;
else
ymin = min;
// transform mode size into values
if (bMode.equalsIgnoreCase("MANUAL")) {
binMode = OriginalBinaryBuildingDetection.BINARISATION_MANUAL;
} else if (bMode.equalsIgnoreCase("AUTO")) {
binMode = OriginalBinaryBuildingDetection.BINARISATION_AUTO;
} else if (bMode.equalsIgnoreCase("CLUSTER")) {
binMode = OriginalBinaryBuildingDetection.BINARISATION_CLUSTER;
}
if (fMode.equalsIgnoreCase("MANUAL")) {
filterMode = OriginalBinaryBuildingDetection.FILTER_MANUAL;
} else if (fMode.equalsIgnoreCase("GRANULOMETRY")) {
filterMode = OriginalBinaryBuildingDetection.FILTER_GRANULOMETRY;
}
}
}