Commit cc900bac authored by Andrey Filippov's avatar Andrey Filippov

Before implementing tree-top filter

parent e43d01e8
...@@ -859,6 +859,7 @@ min_str_neib_fpn 0.35 ...@@ -859,6 +859,7 @@ min_str_neib_fpn 0.35
// combine parameters // combine parameters
public boolean terr_crop = true; // Crop output image to the bounds of all segments
public int terr_border_width = 6; public int terr_border_width = 6;
public boolean terr_render_open = true; // render open areas (no vegetation offset) public boolean terr_render_open = true; // render open areas (no vegetation offset)
public boolean terr_render_no_alpha = true; // render where no opacity is available public boolean terr_render_no_alpha = true; // render where no opacity is available
...@@ -876,6 +877,8 @@ min_str_neib_fpn 0.35 ...@@ -876,6 +877,8 @@ min_str_neib_fpn 0.35
public double terr_min_terrain = 0.001; public double terr_min_terrain = 0.001;
public double terr_min_vegetation = 0.5; public double terr_min_vegetation = 0.5;
public int terr_debug = 0; public int terr_debug = 0;
public String terr_debug_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/lma_um/";
public int terr_debug_length = 200;
public boolean terr_debug_improved = true; // Save debug data if LMA step improved public boolean terr_debug_improved = true; // Save debug data if LMA step improved
public boolean terr_debug_worsened = true; // Save debug data if LMA step improved public boolean terr_debug_worsened = true; // Save debug data if LMA step improved
...@@ -2191,6 +2194,7 @@ min_str_neib_fpn 0.35 ...@@ -2191,6 +2194,7 @@ min_str_neib_fpn 0.35
gd.addMessage ("Combining LMA results segments"); gd.addMessage ("Combining LMA results segments");
gd.addCheckbox ("Crop result image", terr_crop, "Crop output image to the bounds of all segments.");
gd.addNumericField("Overlap width", terr_border_width, 0,3,"","Width of the inter-tile oiverlap border."); gd.addNumericField("Overlap width", terr_border_width, 0,3,"","Width of the inter-tile oiverlap border.");
gd.addCheckbox ("Render open", terr_render_open, ""); gd.addCheckbox ("Render open", terr_render_open, "");
gd.addCheckbox ("Render no alpha", terr_render_no_alpha, ""); gd.addCheckbox ("Render no alpha", terr_render_no_alpha, "");
...@@ -2206,7 +2210,9 @@ min_str_neib_fpn 0.35 ...@@ -2206,7 +2210,9 @@ min_str_neib_fpn 0.35
gd.addNumericField("Min max terrain", terr_min_max_terrain, 5,7,"", "."); gd.addNumericField("Min max terrain", terr_min_max_terrain, 5,7,"", ".");
gd.addNumericField("Minimal terrain", terr_min_terrain, 5,7,"", "."); gd.addNumericField("Minimal terrain", terr_min_terrain, 5,7,"", ".");
gd.addNumericField("Minimal vegetation", terr_min_vegetation, 5,7,"", "."); gd.addNumericField("Minimal vegetation", terr_min_vegetation, 5,7,"", ".");
gd.addNumericField("LMA debug level", terr_debug, 0,3,"", "."); gd.addNumericField("LMA debug level", terr_debug, 0,3,"", "Debug level.");
gd.addStringField ("Debug directory", terr_debug_path, 120,"Directory to save debug images.");
gd.addNumericField("Debug length", terr_debug_length, 0,3,"","Maximal number of debug image slices.");
gd.addCheckbox ("Debug improved", terr_debug_improved, "Save debug image after successful LMA step."); gd.addCheckbox ("Debug improved", terr_debug_improved, "Save debug image after successful LMA step.");
gd.addCheckbox ("Debug worsened", terr_debug_worsened, "Save debug image after unsuccessful LMA step."); gd.addCheckbox ("Debug worsened", terr_debug_worsened, "Save debug image after unsuccessful LMA step.");
...@@ -2939,6 +2945,7 @@ min_str_neib_fpn 0.35 ...@@ -2939,6 +2945,7 @@ min_str_neib_fpn 0.35
terr_recalc_boost = gd.getNextNumber(); // double terr_recalc_boost = gd.getNextNumber(); // double
terr_recalc_average = gd.getNextBoolean();// boolean terr_recalc_average = gd.getNextBoolean();// boolean
terr_crop = gd.getNextBoolean();// boolean
terr_border_width = (int) gd.getNextNumber(); // int terr_border_width = (int) gd.getNextNumber(); // int
terr_render_open = gd.getNextBoolean();// boolean terr_render_open = gd.getNextBoolean();// boolean
terr_render_no_alpha = gd.getNextBoolean();// boolean terr_render_no_alpha = gd.getNextBoolean();// boolean
...@@ -2954,6 +2961,8 @@ min_str_neib_fpn 0.35 ...@@ -2954,6 +2961,8 @@ min_str_neib_fpn 0.35
terr_min_terrain = gd.getNextNumber();// double terr_min_terrain = gd.getNextNumber();// double
terr_min_vegetation = gd.getNextNumber();// double terr_min_vegetation = gd.getNextNumber();// double
terr_debug = (int) gd.getNextNumber(); // int terr_debug = (int) gd.getNextNumber(); // int
terr_debug_path = gd.getNextString(); // String
terr_debug_length = (int) gd.getNextNumber(); // int
terr_debug_improved = gd.getNextBoolean();// boolean terr_debug_improved = gd.getNextBoolean();// boolean
terr_debug_worsened = gd.getNextBoolean();// boolean terr_debug_worsened = gd.getNextBoolean();// boolean
// end of vegetation // end of vegetation
...@@ -3663,6 +3672,7 @@ min_str_neib_fpn 0.35 ...@@ -3663,6 +3672,7 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"terr_recalc_boost", terr_recalc_boost+""); // double properties.setProperty(prefix+"terr_recalc_boost", terr_recalc_boost+""); // double
properties.setProperty(prefix+"terr_recalc_average", terr_recalc_average+""); // boolean properties.setProperty(prefix+"terr_recalc_average", terr_recalc_average+""); // boolean
properties.setProperty(prefix+"terr_crop", terr_crop+""); // boolean
properties.setProperty(prefix+"terr_border_width", terr_border_width+""); // int properties.setProperty(prefix+"terr_border_width", terr_border_width+""); // int
properties.setProperty(prefix+"terr_render_open", terr_render_open+""); // boolean properties.setProperty(prefix+"terr_render_open", terr_render_open+""); // boolean
properties.setProperty(prefix+"terr_render_no_alpha", terr_render_no_alpha+""); // boolean properties.setProperty(prefix+"terr_render_no_alpha", terr_render_no_alpha+""); // boolean
...@@ -3678,6 +3688,8 @@ min_str_neib_fpn 0.35 ...@@ -3678,6 +3688,8 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"terr_min_terrain", terr_min_terrain+""); // double properties.setProperty(prefix+"terr_min_terrain", terr_min_terrain+""); // double
properties.setProperty(prefix+"terr_min_vegetation", terr_min_vegetation+""); // double properties.setProperty(prefix+"terr_min_vegetation", terr_min_vegetation+""); // double
properties.setProperty(prefix+"terr_debug", terr_debug+""); // int properties.setProperty(prefix+"terr_debug", terr_debug+""); // int
properties.setProperty(prefix+"terr_debug_path", terr_debug_path+""); // String
properties.setProperty(prefix+"terr_debug_length", terr_debug_length+""); // int
properties.setProperty(prefix+"terr_debug_improved", terr_debug_improved+""); // boolean properties.setProperty(prefix+"terr_debug_improved", terr_debug_improved+""); // boolean
properties.setProperty(prefix+"terr_debug_worsened", terr_debug_worsened+""); // boolean properties.setProperty(prefix+"terr_debug_worsened", terr_debug_worsened+""); // boolean
// end of vegetation // end of vegetation
...@@ -4411,6 +4423,7 @@ min_str_neib_fpn 0.35 ...@@ -4411,6 +4423,7 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"terr_recalc_boost")!= null) terr_recalc_boost=Double.parseDouble(properties.getProperty(prefix+"terr_recalc_boost")); if (properties.getProperty(prefix+"terr_recalc_boost")!= null) terr_recalc_boost=Double.parseDouble(properties.getProperty(prefix+"terr_recalc_boost"));
if (properties.getProperty(prefix+"terr_recalc_average")!= null) terr_recalc_average=Boolean.parseBoolean(properties.getProperty(prefix+"terr_recalc_average")); if (properties.getProperty(prefix+"terr_recalc_average")!= null) terr_recalc_average=Boolean.parseBoolean(properties.getProperty(prefix+"terr_recalc_average"));
if (properties.getProperty(prefix+"terr_crop")!= null) terr_crop=Boolean.parseBoolean(properties.getProperty(prefix+"terr_crop"));
if (properties.getProperty(prefix+"terr_border_width")!= null) terr_border_width=Integer.parseInt(properties.getProperty(prefix+"terr_border_width")); if (properties.getProperty(prefix+"terr_border_width")!= null) terr_border_width=Integer.parseInt(properties.getProperty(prefix+"terr_border_width"));
if (properties.getProperty(prefix+"terr_render_open")!= null) terr_render_open=Boolean.parseBoolean(properties.getProperty(prefix+"terr_render_open")); if (properties.getProperty(prefix+"terr_render_open")!= null) terr_render_open=Boolean.parseBoolean(properties.getProperty(prefix+"terr_render_open"));
if (properties.getProperty(prefix+"terr_render_no_alpha")!= null) terr_render_no_alpha=Boolean.parseBoolean(properties.getProperty(prefix+"terr_render_no_alpha")); if (properties.getProperty(prefix+"terr_render_no_alpha")!= null) terr_render_no_alpha=Boolean.parseBoolean(properties.getProperty(prefix+"terr_render_no_alpha"));
...@@ -4426,6 +4439,8 @@ min_str_neib_fpn 0.35 ...@@ -4426,6 +4439,8 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"terr_min_terrain")!= null) terr_min_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_terrain")); if (properties.getProperty(prefix+"terr_min_terrain")!= null) terr_min_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_terrain"));
if (properties.getProperty(prefix+"terr_min_vegetation")!= null) terr_min_vegetation=Double.parseDouble(properties.getProperty(prefix+"terr_min_vegetation")); if (properties.getProperty(prefix+"terr_min_vegetation")!= null) terr_min_vegetation=Double.parseDouble(properties.getProperty(prefix+"terr_min_vegetation"));
if (properties.getProperty(prefix+"terr_debug")!= null) terr_debug=Integer.parseInt(properties.getProperty(prefix+"terr_debug")); if (properties.getProperty(prefix+"terr_debug")!= null) terr_debug=Integer.parseInt(properties.getProperty(prefix+"terr_debug"));
if (properties.getProperty(prefix+"terr_debug_path")!= null) terr_debug_path=(String) properties.getProperty(prefix+"terr_debug_path");
if (properties.getProperty(prefix+"terr_debug_length")!= null) terr_debug_length=Integer.parseInt(properties.getProperty(prefix+"terr_debug_length"));
if (properties.getProperty(prefix+"terr_debug_improved")!= null) terr_debug_improved=Boolean.parseBoolean(properties.getProperty(prefix+"terr_debug_improved")); if (properties.getProperty(prefix+"terr_debug_improved")!= null) terr_debug_improved=Boolean.parseBoolean(properties.getProperty(prefix+"terr_debug_improved"));
if (properties.getProperty(prefix+"terr_debug_worsened")!= null) terr_debug_worsened=Boolean.parseBoolean(properties.getProperty(prefix+"terr_debug_worsened")); if (properties.getProperty(prefix+"terr_debug_worsened")!= null) terr_debug_worsened=Boolean.parseBoolean(properties.getProperty(prefix+"terr_debug_worsened"));
// end of vegetation // end of vegetation
...@@ -5119,6 +5134,7 @@ min_str_neib_fpn 0.35 ...@@ -5119,6 +5134,7 @@ min_str_neib_fpn 0.35
imp.terr_recalc_boost = this.terr_recalc_boost; imp.terr_recalc_boost = this.terr_recalc_boost;
imp.terr_recalc_average = this.terr_recalc_average; imp.terr_recalc_average = this.terr_recalc_average;
imp.terr_crop = this.terr_crop;
imp.terr_border_width = this.terr_border_width; imp.terr_border_width = this.terr_border_width;
imp.terr_render_open = this.terr_render_open; imp.terr_render_open = this.terr_render_open;
imp.terr_render_no_alpha = this.terr_render_no_alpha; imp.terr_render_no_alpha = this.terr_render_no_alpha;
...@@ -5134,7 +5150,8 @@ min_str_neib_fpn 0.35 ...@@ -5134,7 +5150,8 @@ min_str_neib_fpn 0.35
imp.terr_min_terrain = this.terr_min_terrain; imp.terr_min_terrain = this.terr_min_terrain;
imp.terr_min_vegetation = this.terr_min_vegetation; imp.terr_min_vegetation = this.terr_min_vegetation;
imp.terr_debug = this.terr_debug; imp.terr_debug = this.terr_debug;
imp.terr_debug_path = this.terr_debug_path;
imp.terr_debug_length = this.terr_debug_length;
imp.terr_debug_improved = this.terr_debug_improved; imp.terr_debug_improved = this.terr_debug_improved;
imp.terr_debug_worsened = this.terr_debug_worsened; imp.terr_debug_worsened = this.terr_debug_worsened;
// end of vegetation // end of vegetation
......
...@@ -216,6 +216,7 @@ public class VegetationLMA { ...@@ -216,6 +216,7 @@ public class VegetationLMA {
public boolean show_extra = true; // show extra samples public boolean show_extra = true; // show extra samples
public int debug_index; public int debug_index;
public int debug_iter; // LMA iteration for images public int debug_iter; // LMA iteration for images
public int debug_length=200; // maximal number of debug slices to save
public double [][] debug_image; public double [][] debug_image;
public int [] debug_iters; public int [] debug_iters;
public int [] debug_series; public int [] debug_series;
...@@ -505,9 +506,11 @@ public class VegetationLMA { ...@@ -505,9 +506,11 @@ public class VegetationLMA {
public int prepareLMA( public int prepareLMA(
final boolean keep_parameters, final boolean keep_parameters,
final Rectangle woi, final Rectangle woi,
final Rectangle woi_veg_in, // used when loading from file (may be different)
final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this
final int max_elevation, // maximal "elevation" to consider final int max_elevation, // maximal "elevation" to consider
final double elevation_radius, //Radius of elevation/vegetation influence. final double elevation_radius, //Radius of elevation/vegetation influence.
final boolean [][] valid_scene_pix_in, // may have nulls or be shorter (do not update "overlaid")
final double hifreq_weight, // 22.5 0 - do not use high-freq. Relative weight of laplacian components final double hifreq_weight, // 22.5 0 - do not use high-freq. Relative weight of laplacian components
final double terrain_correction, final double terrain_correction,
final boolean fit_terr, final boolean fit_terr,
...@@ -549,6 +552,7 @@ public class VegetationLMA { ...@@ -549,6 +552,7 @@ public class VegetationLMA {
// final double um_weight, // final double um_weight,
// String parameters_read_path, // String parameters_read_path,
final int debugLevel, final int debugLevel,
final String debug_path,
final boolean debug_save_improved, // Save debug image after successful LMA step."); final boolean debug_save_improved, // Save debug image after successful LMA step.");
final boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step."); final boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step.");
this.woi = woi; this.woi = woi;
...@@ -592,7 +596,9 @@ public class VegetationLMA { ...@@ -592,7 +596,9 @@ public class VegetationLMA {
this.max_warp = max_warp; this.max_warp = max_warp;
this.max_elevation = max_elevation; this.max_elevation = max_elevation;
this.elevation_radius = elevation_radius; this.elevation_radius = elevation_radius;
if ((debug_path != null) && (debug_path.length() > 0)) {
this.debug_path = debug_path;
}
this.debug_save_improved = debug_save_improved; this.debug_save_improved = debug_save_improved;
this.debug_save_worsened = debug_save_worsened; this.debug_save_worsened = debug_save_worsened;
this.elev_sum_weights = null; // calculate elevations on next getFxDErivsrun this.elev_sum_weights = null; // calculate elevations on next getFxDErivsrun
...@@ -621,12 +627,12 @@ public class VegetationLMA { ...@@ -621,12 +627,12 @@ public class VegetationLMA {
} }
// valid_scenes = getValidScenes(max_offset); // final int max_offset) // valid_scenes = getValidScenes(max_offset); // final int max_offset)
woi_veg = new Rectangle(); this.woi_veg = (woi_veg_in != null)? woi_veg_in : new Rectangle();
int max_sacrifice = 5; int max_sacrifice = 5;
boolean [] valid_pixels_in = null; boolean [] valid_pixels_in = null;
int [] valid_stats = new int[5]; int [] valid_stats = new int[5];
int [] max_warp_scene_pix = new int[2]; int [] max_warp_scene_pix = new int[2];
// woi_veg_in
boolean [][] valid_scene_pix = getValidScenesPixels( boolean [][] valid_scene_pix = getValidScenesPixels(
warps, // final double[][][] warps, warps, // final double[][][] warps,
max_warp, // final double max_warp, max_warp, // final double max_warp,
...@@ -638,6 +644,35 @@ public class VegetationLMA { ...@@ -638,6 +644,35 @@ public class VegetationLMA {
max_warp_scene_pix, // final int [] max_warp_scene_pix, max_warp_scene_pix, // final int [] max_warp_scene_pix,
this.woi, // final Rectangle woi, this.woi, // final Rectangle woi,
this.woi_veg); // final Rectangle woi_veg) // should be initialized, will be modified this.woi_veg); // final Rectangle woi_veg) // should be initialized, will be modified
if (valid_scene_pix_in != null) {
String [] names = {"scenes","terrain pixels","vegetation pixels"};
boolean mismatch = false;
// TODO: Compare and notify i=f different
for (int i = 0; i < names.length; i++) {
boolean mismatch_this = false;
int num_gen=0, num_restore = 0;
for (int n = 0; n < Math.min(valid_scene_pix[i].length,valid_scene_pix_in[i].length); n++) {
if (valid_scene_pix[i][n]!=valid_scene_pix_in[i][n]) {
mismatch_this=true;
}
if (valid_scene_pix[i][n]) num_gen++;
if (valid_scene_pix_in[i][n]) num_restore++;
}
if (mismatch_this) {
System.out.println("Restored valid "+names[i]+" do not match generated ones, number of restored = "+num_restore+
", number of generated = "+num_gen);
}
mismatch |= mismatch_this;
}
if (mismatch) {
System.out.println("Using restored valid scenes and pixels ('overlaid' is always generated)");
for (int i = 0; i < valid_scene_pix_in.length; i++) {
if (valid_scene_pix_in[i] != null) {
valid_scene_pix[i]=valid_scene_pix_in[i];
}
}
}
}
valid_scenes = valid_scene_pix[0]; valid_scenes = valid_scene_pix[0];
valid_terrain = valid_scene_pix[1]; valid_terrain = valid_scene_pix[1];
valid_vegetation = valid_scene_pix[2]; valid_vegetation = valid_scene_pix[2];
...@@ -825,7 +860,8 @@ public class VegetationLMA { ...@@ -825,7 +860,8 @@ public class VegetationLMA {
setupWeights( // after setupParametersIndices setupWeights( // after setupParametersIndices
scene_weights, scene_weights,
reg_weights, // final double reg_weights, reg_weights, // final double reg_weights,
hifreq_weight); // final double hifreq_weight ); hifreq_weight, // final double hifreq_weight );
debugLevel); // final int debugLevel) {
// false, // final boolean apply_transparency, // false, // final boolean apply_transparency,
// 1.0, // final double alpha_opaque, // 1.0, // final double alpha_opaque,
// 0.0); // final double alpha_pedestal) { // 0.0); // final double alpha_pedestal) {
...@@ -1427,9 +1463,13 @@ public class VegetationLMA { ...@@ -1427,9 +1463,13 @@ public class VegetationLMA {
} }
public String getParametersDebugTitle() { public String getParametersDebugTitle() {
return getParametersDebugTitle(false);
}
public String getParametersDebugTitle(boolean short_name) {
// alpha_en_holes -> alpha_mm_hole = NaN; // alpha_en_holes -> alpha_mm_hole = NaN;
// hifreq_weight // hifreq_weight
String debug_title = "parameters_vector-x"+woi.x+"-y"+woi.y+"-w"+woi.width+"-h"+woi.height; String debug_title = "parameters_vector-x"+woi.x+"-y"+woi.y+"-w"+woi.width+"-h"+woi.height;
if (!short_name) {
debug_title += "-hf"+hifreq_weight+"-tc"+terrain_correction; debug_title += "-hf"+hifreq_weight+"-tc"+terrain_correction;
debug_title += "-al"+alpha_loss+"-alo"+alpha_offset+"-amv"+alpha_min_veg+"-alp"+alpha_lpf+"-als"+alpha_scale_avg+(alpha_piece_linear?"-alin":"-acos"); debug_title += "-al"+alpha_loss+"-alo"+alpha_offset+"-amv"+alpha_min_veg+"-alp"+alpha_lpf+"-als"+alpha_scale_avg+(alpha_piece_linear?"-alin":"-acos");
debug_title += "-ap"+alpha_push+"-apn"+alpha_push_neutral+"-apc"+alpha_push_center+(alpha_en_holes?("-amm"+alpha_mm_hole):""); debug_title += "-ap"+alpha_push+"-apn"+alpha_push_neutral+"-apc"+alpha_push_center+(alpha_en_holes?("-amm"+alpha_mm_hole):"");
...@@ -1437,11 +1477,17 @@ public class VegetationLMA { ...@@ -1437,11 +1477,17 @@ public class VegetationLMA {
if (elev_alpha_en) { if (elev_alpha_en) {
debug_title += "-ea"+elev_alpha+"-ep"+elev_alpha_pwr+"-lv"+low_veget; debug_title += "-ea"+elev_alpha+"-ep"+elev_alpha_pwr+"-lv"+low_veget;
} }
debug_title += "-sp"+scenes_pull0+"-ss"+scale_scenes_pull+"-bp"+boost_parallax; debug_title += "-sp"+scenes_pull0+"-sp0"+ scenes_pull0+"-bp"+boost_parallax;
debug_title += from_file?"-file":"-new"; debug_title += from_file?"-file":"-new";
}
return debug_title; return debug_title;
} }
public static String getParametersDebugTitleEnd(boolean from_file) {
return from_file?"-file":"-new";
}
public void debugImageSaveShow( public void debugImageSaveShow(
double [] vector, double [] vector,
...@@ -2562,7 +2608,7 @@ public class VegetationLMA { ...@@ -2562,7 +2608,7 @@ public class VegetationLMA {
if (ntpar >= 0) { if (ntpar >= 0) {
terrain = vector[ntpar]; terrain = vector[ntpar];
} else { } else {
System.out.println("getFxDerivs(): BUG: par_index["+TVAO_TERRAIN+"]["+npix+"] ="+ntpar); System.out.println("getFxDerivs(): BUG: par_index["+TVAO_TERRAIN+"]["+npix+"] ="+ntpar+", nScene="+nScene+", x="+x+", y="+y+" npix="+npix+", wx="+wx+", wy="+wy);
continue; continue;
} }
} else { } else {
...@@ -2578,11 +2624,14 @@ public class VegetationLMA { ...@@ -2578,11 +2624,14 @@ public class VegetationLMA {
if (sw == 0) { if (sw == 0) {
anum_elev_err.getAndIncrement(); anum_elev_err.getAndIncrement();
if ((debug_level > -2) && (extra_data == null)){ if ((debug_level > -2) && (extra_data == null)){
System.out.println("getFxDerivs(): BUG: elev_sum_weights["+nScene+"]["+windx+"]=0"); System.out.println("getFxDerivs(): BUG: elev_sum_weights["+nScene+"]["+windx+"]=0. Restored with different overlaid?");
} }
} else { // OK, non-zero } else { // OK, non-zero
double avg_veget = veget_woi[windx] / sw; double avg_veget = veget_woi[windx] / sw;
double avg_alpha = alpha_woi[windx] / sw; double avg_alpha = alpha_woi[windx] / sw;
if (Double.isNaN(avg_veget) || Double.isNaN(avg_alpha)) {
System.out.println("getFxDerivs(): BUG: avg_veget="+avg_veget+", avg_alpha="+avg_alpha+",nScene="+nScene+", windx="+windx+". Restored with different overlaid?");
} else {
double k; double k;
if (alpha_piece_linear) { if (alpha_piece_linear) {
k = (avg_alpha < 0)? 0: ((avg_alpha > 1) ? 1.0: avg_alpha); k = (avg_alpha < 0)? 0: ((avg_alpha > 1) ? 1.0: avg_alpha);
...@@ -2684,6 +2733,7 @@ public class VegetationLMA { ...@@ -2684,6 +2733,7 @@ public class VegetationLMA {
} }
} }
} }
}
} else { // terrain-only pixel } else { // terrain-only pixel
d = terrain; d = terrain;
if (need_derivs && (ntpar >= 0)) { if (need_derivs && (ntpar >= 0)) {
...@@ -2713,7 +2763,7 @@ public class VegetationLMA { ...@@ -2713,7 +2763,7 @@ public class VegetationLMA {
System.out.println("getFxDerivs(): anum_elev_err="+anum_elev_err.get()); System.out.println("getFxDerivs(): anum_elev_err="+anum_elev_err.get());
} }
// process hi-frequnecy (laplacians) - needs contrib_threads combining // process hi-frequency (laplacians) - needs contrib_threads combining
// do later after more parameter inter-relations are added // do later after more parameter inter-relations are added
// combine contrib_threads // combine contrib_threads
final ArrayList<HashSet<Integer>> contrib_combo = need_derivs? new ArrayList<HashSet<Integer>>(woi_length): null; final ArrayList<HashSet<Integer>> contrib_combo = need_derivs? new ArrayList<HashSet<Integer>>(woi_length): null;
...@@ -2860,6 +2910,7 @@ public class VegetationLMA { ...@@ -2860,6 +2910,7 @@ public class VegetationLMA {
final double [][] fX_avg_thread = new double [threads.length][woi_length]; final double [][] fX_avg_thread = new double [threads.length][woi_length];
final double [][][] jt_avg_thread = (jt != null) ? new double [threads.length][jt.length][woi_length] : null; final double [][][] jt_avg_thread = (jt != null) ? new double [threads.length][jt.length][woi_length] : null;
final boolean debug_print = (debug_level >100); final boolean debug_print = (debug_level >100);
int dbg_windx = -246;
ai.set(0); ai.set(0);
ati.set(0); ati.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) {
...@@ -2870,8 +2921,11 @@ public class VegetationLMA { ...@@ -2870,8 +2921,11 @@ public class VegetationLMA {
int nscene = y_src[yIndx][YSRC_SCENE]; int nscene = y_src[yIndx][YSRC_SCENE];
int indx = y_src[yIndx][YSRC_FINDEX]; int indx = y_src[yIndx][YSRC_FINDEX];
int windx = getWindexFromFindex(indx); int windx = getWindexFromFindex(indx);
if (debug_print && (windx == 0)) { if (windx == dbg_windx) {
System.out.println("yIndx="+yIndx+", nscene="+nscene+", indx="+indx+", windx="+windx); System.out.println("getFxDerivs() SAMPLES_Y_AVG-1 windx="+windx);
}
if (debug_print && (windx == dbg_windx)) {
System.out.println("yIndx="+yIndx+", nscene="+nscene+", indx="+indx+", windx="+windx+", fX[yIndx]="+fX[yIndx]);
} }
double w = recalc_average ? weights[yIndx]/weight_to_scene_weight: scene_weights[nscene]; // norm_scene_weights[nscene]; double w = recalc_average ? weights[yIndx]/weight_to_scene_weight: scene_weights[nscene]; // norm_scene_weights[nscene];
w *= terrain_correction; w *= terrain_correction;
...@@ -2893,6 +2947,9 @@ public class VegetationLMA { ...@@ -2893,6 +2947,9 @@ public class VegetationLMA {
public void run() { public void run() {
for (int wIndx = ai.getAndIncrement(); wIndx < woi_length; wIndx = ai.getAndIncrement()){ for (int wIndx = ai.getAndIncrement(); wIndx < woi_length; wIndx = ai.getAndIncrement()){
int nx = samples_pointers[SAMPLES_Y_AVG][0]+wIndx; int nx = samples_pointers[SAMPLES_Y_AVG][0]+wIndx;
if (wIndx == dbg_windx) {
System.out.println("getFxDerivs() SAMPLES_Y_AVG-2 windx="+wIndx);
}
for (int nthread = 0; nthread < threads.length; nthread++) { for (int nthread = 0; nthread < threads.length; nthread++) {
fX[nx] += fX_avg_thread[nthread][wIndx]; fX[nx] += fX_avg_thread[nthread][wIndx];
if (jt_avg_thread != null) { if (jt_avg_thread != null) {
...@@ -4531,6 +4588,7 @@ public class VegetationLMA { ...@@ -4531,6 +4588,7 @@ public class VegetationLMA {
public double[][] restoreParametersFile( public double[][] restoreParametersFile(
String path, String path,
int debugLevel, int debugLevel,
String debug_path,
boolean debug_save_improved, // Save debug image after successful LMA step."); boolean debug_save_improved, // Save debug image after successful LMA step.");
boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step."); boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step.");
...@@ -4593,13 +4651,31 @@ public class VegetationLMA { ...@@ -4593,13 +4651,31 @@ public class VegetationLMA {
for (int i = 0; i < TVAO_NAMES.length; i++) { for (int i = 0; i < TVAO_NAMES.length; i++) {
disable_names[i]= "FIT_DISABLE_"+TVAO_NAMES[i]; disable_names[i]= "FIT_DISABLE_"+TVAO_NAMES[i];
} }
boolean [][] valid_scene_pix = new boolean [3][]; // no overlaid
valid_scene_pix[0] = new boolean [num_scenes];
for (int n = 0; n < num_scenes; n++) {
valid_scene_pix[0][n] = indices[TVAO_SCENE_OFFSET][n] >=0;
}
valid_scene_pix[1] = new boolean [woi.width*woi.height];
for (int n = 0; n < valid_scene_pix[1].length; n++) {
int wx = n % woi.width;
int wy = n / woi.width;
int wvindex = (wx + woi.x-woi_veg.x) + (wy + woi.y-woi_veg.y)*woi_veg.width;
valid_scene_pix[1][n] = indices[TVAO_TERRAIN][wvindex] >=0;
}
valid_scene_pix[2] = new boolean [woi_veg.width*woi_veg.height];
for (int n = 0; n < valid_scene_pix[2].length; n++) {
valid_scene_pix[2][n] = indices[TVAO_VEGETATION][n] >=0;
}
// int num_samples = // int num_samples =
prepareLMA( prepareLMA(
false, // final boolean keep_parameters, false, // final boolean keep_parameters,
woi, // final Rectangle woi, woi, // final Rectangle woi,
woi_veg, // final Rectangle woi_veg_in, // used when loading from file (may be different)
getProperty(imp_pars,"MAX_WARP", max_warp), // final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this getProperty(imp_pars,"MAX_WARP", max_warp), // final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this
getProperty(imp_pars,"MAX_ELEVATION", max_elevation), // final int max_offset, // maximal "elevation" to consider getProperty(imp_pars,"MAX_ELEVATION", max_elevation), // final int max_offset, // maximal "elevation" to consider
getProperty(imp_pars,"ELEVATION_RADIUS", elevation_radius), // final double elevation_radius, // Radius of elevation/vegetation influence. getProperty(imp_pars,"ELEVATION_RADIUS", elevation_radius), // final double elevation_radius, // Radius of elevation/vegetation influence.
valid_scene_pix, // final boolean [] valid_scene_pix, valid_scene_pix_in, // may have nulls or be shorter (do not update "overlaid")
getProperty(imp_pars, "HIGHFREQ_WEIGHT", hifreq_weight), // final double hifreq_weight, // 22.5 0 - do not use high-freq. Relative weight of laplacian components getProperty(imp_pars, "HIGHFREQ_WEIGHT", hifreq_weight), // final double hifreq_weight, // 22.5 0 - do not use high-freq. Relative weight of laplacian components
getProperty(imp_pars, "TERRAIN_CORRECTION", terrain_correction), // final double terrain_correction, getProperty(imp_pars, "TERRAIN_CORRECTION", terrain_correction), // final double terrain_correction,
getProperty(imp_pars, "FIT_TERRAIN", fits[TVAO_TERRAIN]), // final boolean adjust_terr, getProperty(imp_pars, "FIT_TERRAIN", fits[TVAO_TERRAIN]), // final boolean adjust_terr,
...@@ -4639,10 +4715,10 @@ public class VegetationLMA { ...@@ -4639,10 +4715,10 @@ public class VegetationLMA {
getProperty(imp_pars, "BOOST_PARALLAX", boost_parallax), // final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene getProperty(imp_pars, "BOOST_PARALLAX", boost_parallax), // final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene
getProperty(imp_pars, "MAX_PARALLAX", max_parallax), // final double max_parallax, // do not consider maximal parallax above this (consider it a glitch) getProperty(imp_pars, "MAX_PARALLAX", max_parallax), // final double max_parallax, // do not consider maximal parallax above this (consider it a glitch)
debugLevel, // final int debugLevel); debugLevel, // final int debugLevel);
debug_path, // final String debug_path,
debug_save_improved, // final boolean debug_save_improved, // Save debug image after successful LMA step."); debug_save_improved, // final boolean debug_save_improved, // Save debug image after successful LMA step.");
debug_save_worsened); // final boolean debug_save_worsened) // Save debug image after unsuccessful LMA step."); debug_save_worsened); // final boolean debug_save_worsened) // Save debug image after unsuccessful LMA step.");
num_pars[TVAO_TERRAIN] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_TERRAIN")); num_pars[TVAO_TERRAIN] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_TERRAIN"));
num_pars[TVAO_VEGETATION] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_VEGETATION")); num_pars[TVAO_VEGETATION] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_VEGETATION"));
num_pars[TVAO_ALPHA] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_ALPHA")); num_pars[TVAO_ALPHA] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_ALPHA"));
...@@ -4944,7 +5020,9 @@ public class VegetationLMA { ...@@ -4944,7 +5020,9 @@ public class VegetationLMA {
other_pars[0], // terrain_offset, other_pars[0], // terrain_offset,
tvao[TVAO_SCENE_OFFSET], // double [] scene_offsets, tvao[TVAO_SCENE_OFFSET], // double [] scene_offsets,
new double [][] {tvao[0],tvao[1],tvao[2],tvao[2]}, // double [][] tva) {} {} new double [][] {tvao[0],tvao[1],tvao[2],tvao[2]}, // double [][] tva) {} {}
null); // double [] confidence null, // double [] confidence
overlaid); //boolean [] overlaid)
} }
// sort in line-scan order // sort in line-scan order
Arrays.sort(segments, new Comparator<VegetationSegment>() { Arrays.sort(segments, new Comparator<VegetationSegment>() {
...@@ -4968,15 +5046,14 @@ public class VegetationLMA { ...@@ -4968,15 +5046,14 @@ public class VegetationLMA {
double transparency_pow, double transparency_pow,
double transparency_gb, double transparency_gb,
int debugLevel, int debugLevel,
String debug_path,
boolean debug_save_improved, // Save debug image after successful LMA step."); boolean debug_save_improved, // Save debug image after successful LMA step.");
boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step."); boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step.");
FileFilter parFileFilter = new FileFilter() FileFilter parFileFilter = new FileFilter()
{ {
//Override accept method //Override accept method
public boolean accept(File file) { public boolean accept(File file) { //if the file extension is .log return true, else false
//if the file extension is .log return true, else false
if (file.isFile() && file.getName().endsWith(suffix+PAR_EXT)) { if (file.isFile() && file.getName().endsWith(suffix+PAR_EXT)) {
return true; return true;
} }
...@@ -4986,13 +5063,29 @@ public class VegetationLMA { ...@@ -4986,13 +5063,29 @@ public class VegetationLMA {
File dir = new File(dir_path); File dir = new File(dir_path);
File [] par_files = dir.listFiles(parFileFilter); File [] par_files = dir.listFiles(parFileFilter);
VegetationSegment [] segments = new VegetationSegment [par_files.length]; VegetationSegment [] segments = new VegetationSegment [par_files.length];
int dbg_n = 13;
boolean bug_check = false; // true;
for (int n = 0; n < par_files.length; n++) { for (int n = 0; n < par_files.length; n++) {
// updates this to match file if (debugLevel > -3) {
System.out.println("====== readAllSegments(): n="+n+ ", "+par_files[n].getPath());
}
if (n==dbg_n) {
System.out.println("readAllSegments(): n="+n);
}// updates this to match file
double [][] tvao = restoreParametersFile( double [][] tvao = restoreParametersFile(
par_files[n].getPath(), // String path, par_files[n].getPath(), // String path,
debugLevel, // int debugLevel, (bug_check? -3 : debugLevel), // int debugLevel,
debug_path, // String debug_path,
debug_save_improved, // boolean debug_save_improved, // Save debug image after successful LMA step."); debug_save_improved, // boolean debug_save_improved, // Save debug image after successful LMA step.");
debug_save_worsened); //boolean debug_save_worsened) // Save debug image after unsuccessful LMA step."); debug_save_worsened); //boolean debug_save_worsened) // Save debug image after unsuccessful LMA step.");
if (!woi_veg.contains(woi)) {
System.out.println("****** readAllSegments(): bad data, woi_veg does not contain woi!");
System.out.println("----- readAllSegments() segment "+(n+1)+" (of "+par_files.length+")");
System.out.println("----- woi="+woi.toString()+", woi_veg="+woi_veg.toString());
System.out.println("----- "+par_files[n].getPath());
}
if (!bug_check) {
double [] confidence = getTransparencyConfidence( // woi double [] confidence = getTransparencyConfidence( // woi
null, // final double [] vector, null, // final double [] vector,
transparency_opaque, // final double transparency_opaque, transparency_opaque, // final double transparency_opaque,
...@@ -5009,11 +5102,15 @@ public class VegetationLMA { ...@@ -5009,11 +5102,15 @@ public class VegetationLMA {
terrain_offset, // terrain_offset, terrain_offset, // terrain_offset,
tvao[TVAO_SCENE_OFFSET], // double [] scene_offsets, tvao[TVAO_SCENE_OFFSET], // double [] scene_offsets,
new double [][] {tvao[0],tvao[1],tvao[2],tvao[3]}, // double [][] tva) {} {} new double [][] {tvao[0],tvao[1],tvao[2],tvao[3]}, // double [][] tva) {} {}
confidence); // double [] confidence confidence, // double [] confidence
overlaid); //boolean [] overlaid)
if (debugLevel>-2) { if (debugLevel>-2) {
Runtime runtime = Runtime.getRuntime(); Runtime runtime = Runtime.getRuntime();
runtime.gc(); runtime.gc();
System.out.println("----- readAllSegments() segment "+(n+1)+" (of "+par_files.length+") --- Free memory="+runtime.freeMemory()+" (of "+runtime.totalMemory()+")"); System.out.println("----- readAllSegments() segment "+(n+1)+" (of "+par_files.length+") --- Free memory="+runtime.freeMemory()+" (of "+runtime.totalMemory()+")");
System.out.println("----- woi="+woi.toString()+", woi_veg="+woi_veg.toString());
System.out.println("----- "+par_files[n].getPath());
}
} }
} }
// sort in line-scan order // sort in line-scan order
...@@ -5121,11 +5218,11 @@ public class VegetationLMA { ...@@ -5121,11 +5218,11 @@ public class VegetationLMA {
return max_err; return max_err;
} }
private void setupWeights( // after setupParametersIndices private void setupWeights( // after setupParametersIndices
final double [] scene_weights_in, final double [] scene_weights_in,
final double reg_weights, // relative to y_vector samples -> fraction of 1.0 final double reg_weights, // relative to y_vector samples -> fraction of 1.0
final double hifreq_weight) { final double hifreq_weight,
final int debugLevel) {
// double terrain_correction_weight = 1.0; // double terrain_correction_weight = 1.0;
boolean use_hf = (y_src_hf != null); boolean use_hf = (y_src_hf != null);
int y_avg_len = y_vector.length - (y_src.length + ((y_src_hf != null) ? y_src_hf.length : 0)); int y_avg_len = y_vector.length - (y_src.length + ((y_src_hf != null) ? y_src_hf.length : 0));
...@@ -5266,8 +5363,10 @@ public class VegetationLMA { ...@@ -5266,8 +5363,10 @@ public class VegetationLMA {
swn+= weights[i]; swn+= weights[i];
} }
sw += swn; sw += swn;
if (debugLevel > -2) {
System.out.println("sum weights["+n+"] = "+swn+", total = "+sw); System.out.println("sum weights["+n+"] = "+swn+", total = "+sw);
} }
}
return; return;
} }
...@@ -5311,7 +5410,7 @@ public class VegetationLMA { ...@@ -5311,7 +5410,7 @@ public class VegetationLMA {
final double transparency_frac, final double transparency_frac,
final double transparency_dist, //0 - do not apply final double transparency_dist, //0 - do not apply
final double transparency_pow){ final double transparency_pow){
final int dbg_windx = 113; final int dbg_windx = -113;
final int woi_length = woi.width*woi.height; final int woi_length = woi.width*woi.height;
final double [][] transparency_weights = new double [num_scenes][woi_length]; final double [][] transparency_weights = new double [num_scenes][woi_length];
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
...@@ -5667,236 +5766,6 @@ public class VegetationLMA { ...@@ -5667,236 +5766,6 @@ public class VegetationLMA {
return confidence; return confidence;
} }
public double [] applyTransparency_old(
final double [] vector,
final double transparency_opaque,
final double transparency_pedestal,
final double transparency_frac,
final double transparency_dist,
final double transparency_pow,
final double transparency_gb,
final double transparency_boost_in,
final boolean recalc_average,
String prefix) {
this.recalc_average = recalc_average;
final int woi_length = woi.width*woi.height;
final double transparency_boost = Math.max(transparency_boost_in, 1.0);
boolean use_hf = (y_src_hf != null);
int y_avg_len = y_vector.length - (y_src.length + ((y_src_hf != null) ? y_src_hf.length : 0));
double [][] transparency = getTransparency((vector==null)? parameters_vector:vector);
double [][] transparency_weights_preblur = getTransparenctWeights( // should be no NaNs!
transparency, // final double [][] transparency,
transparency_opaque, // final double transparency_opaque,
transparency_pedestal, // final double transparency_pedestal,
transparency_frac, // final double transparency_frac,
transparency_dist, // final double transparency_dist); //0 - do not apply
transparency_pow); // final double transparency_pow){
final double [][] transparency_weights = new double [num_scenes][];
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
if (transparency_gb <= 0) {
for (int n = 0; n < transparency_weights.length; n++) {
transparency_weights[n] = transparency_weights_preblur[n];
}
} else {
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
DoubleGaussianBlur gb = new DoubleGaussianBlur();
for (int nScene = ai.getAndIncrement(); nScene < num_scenes; nScene = ai.getAndIncrement()) {
transparency_weights[nScene] = transparency_weights_preblur[nScene].clone();
gb.blurDouble(
transparency_weights[nScene], //
woi.width, // terrain woi
woi.height,
transparency_gb, // double sigmaX,
transparency_gb, // double sigmaY,
0.01); // double accuracy)
}
}
};
}
ImageDtt.startAndJoin(threads);
}
double [] confidence = getTerrainConfidence(transparency_weights); // blurred
double max_confidence = 0;
for (int i = 0; i < confidence.length; i++) if (confidence[i] > max_confidence) {
max_confidence = confidence[i];
}
double max_scaled = max_confidence / transparency_boost;
final double [] scales = new double [confidence.length];
for (int i = 0; i < confidence.length; i++) {
if (confidence[i] >= max_scaled) {
scales[i] = max_confidence / confidence[i];
} else {
scales[i] = transparency_boost;
}
}
final double [][] scaled_weights = new double [num_scenes][woi_length];
// normalize weights for confidence
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nScene = ai.getAndIncrement(); nScene < num_scenes; nScene = ai.getAndIncrement()) {
for (int windx = 0; windx < woi_length; windx++) {
scaled_weights[nScene][windx] = transparency_weights[nScene][windx] * scales[windx];
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (prefix != null) {
String title =prefix+String.format("-opq%3f-pdst%5f-frac%3f-dst%2f-pwr%4f-gb%4f-boost%4f-avg%1d.tiff",
transparency_opaque,transparency_pedestal,transparency_frac,
transparency_dist,transparency_pow,transparency_gb, transparency_boost, recalc_average?1:0);
int nscenes = transparency.length;
String [] titles_top = {"transparency","pre-blur","weights","normalized"};
String [] titles = new String[nscenes + 1];
double [][][] dbg_img = new double[titles_top.length][titles.length][]; // woi_length];
dbg_img[0][nscenes] = new double[woi_length];
dbg_img[1][nscenes] = getTerrainConfidence(transparency_weights_preblur);
dbg_img[2][nscenes] = getTerrainConfidence(transparency_weights);
dbg_img[3][nscenes] = scales;
for (int nscene = 0; nscene < transparency.length; nscene++) {
titles[nscene] = "scene-"+nscene;
dbg_img[0][nscene] = transparency[nscene];
dbg_img[1][nscene] = transparency_weights_preblur[nscene];
dbg_img[2][nscene] = transparency_weights[nscene];
dbg_img[3][nscene] = scaled_weights[nscene];
for (int wpix = 0;wpix < woi_length; wpix++) {
if (dbg_img[0][nscenes][wpix] > transparency[nscene][wpix]) { // takes care of NaN
transparency[nscene][wpix] = dbg_img[0][nscenes][wpix];
}
// dbg_img[0][nscenes][wpix] = Math.max(transparency[nscene][wpix],dbg_img[0][nscenes][wpix]);
}
}
titles[nscenes] = "max/conf";
ShowDoubleFloatArrays.showArraysHyperstack(
dbg_img, // double[][][] pixels,
woi.width, // int width,
title, // "terrain_vegetation_render.tiff", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles, // String [] titles, // all slices*frames titles or just slice titles or null
titles_top, // String [] frame_titles, // frame titles or null
true); // boolean show)
}
double s = 0, ss=0;
for (int ny = 0; ny < y_src.length; ny++) {
int nscene = y_src[ny][YSRC_SCENE];
int findx = y_src[ny][YSRC_FINDEX];
int windx = getWindexFromFindex(findx);
double w = scaled_weights[nscene][windx];
if (Double.isNaN(w)) {
System.out.println("applyTransparency() 1: ny="+ny+", nscene="+nscene+", findx="+findx+", windx="+windx+", w="+w);
} else {
s += w;
}
ss += scene_weights[nscene];
}
// double s_scenes = s; // sum of all scene weight. Maybe skip scenes that do not exist?
double s_to_ss = s/ss;
if (use_hf) {
for (int ny = 0; ny < y_src_hf.length; ny++) {
int nscene = y_src_hf[ny][YSRC_SCENE];
int findx = y_src_hf[ny][YSRC_FINDEX];
int windx = getWindexFromFindex(findx);
double w = scaled_weights[nscene][windx] * hifreq_weight ;
if (Double.isNaN(w)) {
System.out.println("applyTransparency() 2: ny="+ny+", nscene="+nscene+", findx="+findx+", windx="+windx+", w="+w);
} else {
s += w;
}
}
}
// double s_y_yhf = s; //
// TODO: If using scaled_weights (in setupYVectorTransparency and getFxDerivs),
// then calculate following weights differently to keep ~ the same sum
// use recalc_average / this.recalc_average to change weights
if (y_avg_len > 0) {
for (int ny = 0; ny < y_avg_len; ny++) {
s += terrain_correction_weight; // scene_weights[nscene] is included in y_wavg and fX, jt
}
}
/// final double s0 = s;
s /= (1 - reg_weights); // *= (1+ reg_weights);s *= (1+ reg_weights);
final double k = 1.0/s; //corr_transp 10.85811847216958
weight_to_scene_weight = k * s_to_ss;
/// weight_pure = s0/s;
// final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
// final AtomicInteger ai = new AtomicInteger(0);
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nw = ai.getAndIncrement(); nw < weights.length; nw = ai.getAndIncrement()) {
if (nw < samples_pointers[SAMPLES_Y_HF][0]) { // DC differences
int ny = nw;
int nscene = y_src[ny][YSRC_SCENE];
int findx = y_src[ny][YSRC_FINDEX];
int windx = getWindexFromFindex(findx);
double w = scaled_weights[nscene][windx] * k;
if (!Double.isNaN(w)) {
weights[nw] = w;
} else {
System.out.println("weights["+nw+"]=NaN - 1");
}
} else if (nw < samples_pointers[SAMPLES_Y_AVG][0]) { // HF differences if exist
int ny = nw-y_src.length;
int nscene = y_src_hf[ny][YSRC_SCENE];
int findx = y_src_hf[ny][YSRC_FINDEX];
int windx = getWindexFromFindex(findx);
double w = scaled_weights[nscene][windx] * k * hifreq_weight; // scene_weights[nscene] * k * hifreq_weight;
if (!Double.isNaN(w)) {
weights[nw] = w;
} else {
System.out.println("weights["+nw+"]=NaN - 2");
}
} else if (nw < samples_pointers[SAMPLES_EXTRA][0]) { // y_wavg if exists
weights[nw] = k * terrain_correction_weight;
if (Double.isNaN(weights[nw])) {
System.out.println("weights["+nw+"]=NaN - 3");
}
/*
} else {
weights[nw] = reg_sample_weight;
if (Double.isNaN(weights[nw])) {
System.out.println("weights["+nw+"]=NaN - 4");
}
*/
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (y_src_hf != null) { // set average offset y - either old way with scene_weights[nscene] or new way with weights[ny]
setupYVectorTransparency();
}
if (prefix != null) {
double sw = 0;
for (int n = 0; n < (samples_pointers.length -1); n++) {
double swn = 0;
for (int i = samples_pointers[n][0]; i < (samples_pointers[n][0]+samples_pointers[n][1]); i++){
swn+= weights[i];
}
sw += swn;
System.out.println("sum weights["+n+"] = "+swn+", total = "+sw);
}
}
return confidence;
}
private void setupYVector( private void setupYVector(
boolean use_terr_corr, boolean use_terr_corr,
double [] scene_weights) { double [] scene_weights) {
...@@ -6616,7 +6485,7 @@ public class VegetationLMA { ...@@ -6616,7 +6485,7 @@ public class VegetationLMA {
if (woi.contains(ax,ay)) { if (woi.contains(ax,ay)) {
double ddx = ax - (x + dx); double ddx = ax - (x + dx);
double ddr2 = ddy2 + ddx*ddx; double ddr2 = ddy2 + ddx*ddx;
if (ddr2 <= radius2) { if ((ddy2 <= radius2) && (ddx*ddx < radius2)) { // if (ddr2 <= radius2) {
int wx = ax - woi.x; int wx = ax - woi.x;
int wy = ay - woi.y; int wy = ay - woi.y;
int wpix =wx + wy*woi.width; int wpix =wx + wy*woi.width;
...@@ -6813,11 +6682,35 @@ public class VegetationLMA { ...@@ -6813,11 +6682,35 @@ public class VegetationLMA {
} }
ImageDtt.startAndJoin(threads); ImageDtt.startAndJoin(threads);
Rectangle woi_veg_new = new Rectangle(amin_x.get(), amin_y.get(), amax_x.get()-amin_x.get()+1, amax_y.get()-amin_y.get()+1);
woi_veg_new.x=amin_x.get();
woi_veg_new.y=amin_y.get();
woi_veg_new.width= amax_x.get()-amin_x.get()+1;
woi_veg_new.height= amax_y.get()-amin_y.get()+1;
if (!woi_veg_new.contains(woi)) {
System.out.println("\n***** BUG FIX:woi_veg_new="+woi_veg_new.toString()+" does not contain woi="+woi.toString()+", increasing woi_veg_new");
Rectangle r = new Rectangle(woi_veg_new);
r.add(woi);
woi_veg_new.x=r.x;
woi_veg_new.y=r.y;
woi_veg_new.width= r.width;
woi_veg_new.height= r.height;
System.out.println("Updated woi_veg_new="+woi_veg_new.toString()+"\n");
}
if (woi_veg.width == 0) {
woi_veg.x = woi_veg_new.x;
woi_veg.y = woi_veg_new.y;
woi_veg.width = woi_veg_new.width;
woi_veg.height = woi_veg_new.height;
// copy num_used to a smaller array // copy num_used to a smaller array
woi_veg.x=amin_x.get(); } else {
woi_veg.y=amin_y.get(); System.out.println("Using provided woi_veg="+woi_veg.toString()+"\n");
woi_veg.width= amax_x.get()-amin_x.get()+1; if (!woi_veg.equals(woi_veg_new)) {
woi_veg.height= amax_y.get()-amin_y.get()+1; System.out.println("***** Provided woi_veg="+woi_veg.toString()+" does not match calculated one="+woi_veg_new.toString());
System.out.println("***** Using the provided one");
}
}
final boolean [] valid_vegetation = new boolean [woi_veg.width*woi_veg.height]; final boolean [] valid_vegetation = new boolean [woi_veg.width*woi_veg.height];
for (int row = 0; row < woi_veg.height; row++) { for (int row = 0; row < woi_veg.height; row++) {
int row_src = row + woi_veg.y - woi_ext.y; int row_src = row + woi_veg.y - woi_ext.y;
...@@ -7213,5 +7106,27 @@ public class VegetationLMA { ...@@ -7213,5 +7106,27 @@ public class VegetationLMA {
} }
return current; return current;
} }
public File [] getSegmentFiles(
String dir_path) {
String starts = getParametersDebugTitle(true);
String suffix1 = getParametersDebugTitleEnd(false);
String suffix2 = getParametersDebugTitleEnd(true);
FileFilter parFileFilter = new FileFilter()
{
//Override accept method
public boolean accept(File file) {
//if the file extension is .log return true, else false
if (file.isFile() && (file.getName().endsWith(suffix1+PAR_EXT) || file.getName().endsWith(suffix2+PAR_EXT))&& file.getName().startsWith(starts)) {
return true;
}
return false;
}
};
File dir = new File(dir_path);
File [] par_files = dir.listFiles(parFileFilter);
return par_files;
}
} }
...@@ -1596,13 +1596,20 @@ public class VegetationModel { ...@@ -1596,13 +1596,20 @@ public class VegetationModel {
double transparency_pow = clt_parameters.imp.terr_recalc_pwr ; // 1.0; // Raise transparency to this power when calculating weight double transparency_pow = clt_parameters.imp.terr_recalc_pwr ; // 1.0; // Raise transparency to this power when calculating weight
double transparency_gb = clt_parameters.imp.terr_recalc_gb ; // 2.0; // Blur transparency-based confidence double transparency_gb = clt_parameters.imp.terr_recalc_gb ; // 2.0; // Blur transparency-based confidence
double transparency_boost = clt_parameters.imp.terr_recalc_boost ; // 5.0; // Maximal boost while increasing low-confidence pixel weights double transparency_boost = clt_parameters.imp.terr_recalc_boost ; // 5.0; // Maximal boost while increasing low-confidence pixel weights
boolean recalc_average = clt_parameters.imp.terr_recalc_average ; //false; // apply transparency to average mismatch boolean recalc_average = clt_parameters.imp.terr_recalc_average ; // false; // apply transparency to average mismatch
String debug_path = clt_parameters.imp.terr_debug_path; // Directory to save debug images
boolean debug_save_improved = clt_parameters.imp.terr_debug_improved; boolean debug_save_improved = clt_parameters.imp.terr_debug_improved;
boolean debug_save_worsened = clt_parameters.imp.terr_debug_worsened; boolean debug_save_worsened = clt_parameters.imp.terr_debug_worsened;
int debug_length = clt_parameters.imp.terr_debug_length;
// boolean restore_mode = false; // boolean restore_mode = false;
boolean save_par_files = true; // false; boolean save_par_files = true; // false;
String segments_dir = getSegmentsDir(segments_sub); String segments_dir = getSegmentsDir(segments_sub);
boolean read_pars = false; // true; /// false; /// true; // false; // true; boolean read_pars = false; // true; /// false; /// true; // false; // true;
boolean crop_combo = clt_parameters.imp.terr_crop; // Crop output image to the bounds of all segments
// debug feature to read to continue - needs to be cleaned up/replaced // debug feature to read to continue - needs to be cleaned up/replaced
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-al100.0-alo0.0-alp10.0-alin-tl0.2-vl0.01-tp0.01-vp0.01-bp5.0-um1.0_0.8.tiff"; // String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-al100.0-alo0.0-alp10.0-alin-tl0.2-vl0.01-tp0.01-vp0.01-bp5.0-um1.0_0.8.tiff";
...@@ -2061,7 +2068,6 @@ public class VegetationModel { ...@@ -2061,7 +2068,6 @@ public class VegetationModel {
segments_dir, // String dir_path) segments_dir, // String dir_path)
segments_suffix); // String suffix); segments_suffix); // String suffix);
*/ */
boolean crop_combo = true;
VegetationSegment [] segments = vegetationLMA.readAllSegments( VegetationSegment [] segments = vegetationLMA.readAllSegments(
segments_dir, // String dir_path) segments_dir, // String dir_path)
segments_suffix, // String suffix); segments_suffix, // String suffix);
...@@ -2072,6 +2078,7 @@ public class VegetationModel { ...@@ -2072,6 +2078,7 @@ public class VegetationModel {
transparency_pow, // double transparency_pow, transparency_pow, // double transparency_pow,
transparency_gb, // double transparency_gb, transparency_gb, // double transparency_gb,
debugLevel, // int debugLevel, debugLevel, // int debugLevel,
debug_path, // String debug_path,
debug_save_improved, // boolean debug_save_improved, // Save debug image after successful LMA step."); debug_save_improved, // boolean debug_save_improved, // Save debug image after successful LMA step.");
debug_save_worsened); // boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step."); debug_save_worsened); // boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step.");
VegetationSegment.combineSegments( VegetationSegment.combineSegments(
...@@ -2116,9 +2123,11 @@ public class VegetationModel { ...@@ -2116,9 +2123,11 @@ public class VegetationModel {
int num_samples = vegetationLMA.prepareLMA( int num_samples = vegetationLMA.prepareLMA(
false, // final boolean keep_parameters, false, // final boolean keep_parameters,
woi, // final Rectangle woi, woi, // final Rectangle woi,
null, // final Rectangle woi_veg_in, // used when loading from file (may be different)
max_warp, // final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this max_warp, // final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this
max_offset, // final int max_offset, // maximal "elevation" to consider max_offset, // final int max_offset, // maximal "elevation" to consider
elevation_radius, // final double elevation_radius, // Radius of elevation/vegetation influence. elevation_radius, // final double elevation_radius, // Radius of elevation/vegetation influence.
null, // final boolean [] valid_scene_pix,
hifreq_weight, //final double hifreq_weight, // 22.5 0 - do not use high-freq. Relative weight of laplacian components hifreq_weight, //final double hifreq_weight, // 22.5 0 - do not use high-freq. Relative weight of laplacian components
terrain_correction,// final double terrain_correction, terrain_correction,// final double terrain_correction,
fit_terr, // final boolean adjust_terr, fit_terr, // final boolean adjust_terr,
...@@ -2160,6 +2169,7 @@ public class VegetationModel { ...@@ -2160,6 +2169,7 @@ public class VegetationModel {
// (um_en? um_weight: 0.0), // final double um_weight, // (um_en? um_weight: 0.0), // final double um_weight,
// par_path, // final String parameters_read_path, // par_path, // final String parameters_read_path,
debugLevel, // final int debugLevel); debugLevel, // final int debugLevel);
debug_path, // final String debug_path,
debug_save_improved, // final boolean debug_save_improved, // Save debug image after successful LMA step."); debug_save_improved, // final boolean debug_save_improved, // Save debug image after successful LMA step.");
debug_save_worsened);// final boolean debug_save_worsened) // Save debug image after unsuccessful LMA step."); debug_save_worsened);// final boolean debug_save_worsened) // Save debug image after unsuccessful LMA step.");
...@@ -2168,12 +2178,32 @@ public class VegetationModel { ...@@ -2168,12 +2178,32 @@ public class VegetationModel {
continue; continue;
} }
// if (save_par_files && skip_existing_woi) { // check that segment already exists
if (save_par_files && skip_existing_woi) { // check that segment already exists if (save_par_files && skip_existing_woi) { // check that segment already exists
// public boolean segmentFileExist(String dir_path) {
/*
String save_path = VegetationLMA.getSavePath( String save_path = VegetationLMA.getSavePath(
segments_dir, // String dir, segments_dir, // String dir,
vegetationLMA.getParametersDebugTitle()); // String title) vegetationLMA.getParametersDebugTitle()); // String title)
if (new File (save_path).exists()) { if (new File (save_path).exists()) {
System.out.println("File "+save_path+"\n already exists, skipping this woi"); */
File[] segment_files = vegetationLMA.getSegmentFiles(segments_dir);
if (tile_woi) {
if (segment_files.length > 0) {
for (File f : segment_files) {
System.out.println("File "+f+"\n with the same woi already exists, skipping this woi");
}
continue;
}
} else {
String save_path = VegetationLMA.getSavePath(
segments_dir, // String dir,
vegetationLMA.getParametersDebugTitle()); // String title)
if (new File (save_path).exists()) {
System.out.println("File "+save_path+"\n (exactly) already exists, skipping this woi");
// for (File f : segment_files) {
// System.out.println("File "+f+"\n (exactly) already exists, skipping this woi");
// }
continue; continue;
} }
if (new File (save_path.replace("-new-","-file-")).exists()) { if (new File (save_path.replace("-new-","-file-")).exists()) {
...@@ -2181,6 +2211,7 @@ public class VegetationModel { ...@@ -2181,6 +2211,7 @@ public class VegetationModel {
continue; continue;
} }
} }
}
int num_iter = num_iters[step_restore]; // int num_iter = num_iters[step_restore]; //
if (par_restore) { // always use last number of iterations - not anymore if (par_restore) { // always use last number of iterations - not anymore
String par_path = parameters_dir; String par_path = parameters_dir;
...@@ -2250,7 +2281,8 @@ public class VegetationModel { ...@@ -2250,7 +2281,8 @@ public class VegetationModel {
} }
/// next_run = true; /// next_run = true;
vegetationLMA.debug_index = 0; vegetationLMA.debug_index = 0;
vegetationLMA.debug_image = new double [100][]; // num_iter][]; vegetationLMA.debug_length = debug_length;
vegetationLMA.debug_image = new double [vegetationLMA.debug_length][]; // num_iter][];
int lma_rslt= vegetationLMA.runLma( // <0 - failed, >=0 iteration number (1 - immediately) int lma_rslt= vegetationLMA.runLma( // <0 - failed, >=0 iteration number (1 - immediately)
lambda, // double lambda, // 0.1 lambda, // double lambda, // 0.1
......
...@@ -15,6 +15,7 @@ public class VegetationSegment { ...@@ -15,6 +15,7 @@ public class VegetationSegment {
public double [][] tva; // woi_veg public double [][] tva; // woi_veg
public double terrain_offset; public double terrain_offset;
public double [] confidence; // woi public double [] confidence; // woi
public boolean [] overlaid;
public String path; public String path;
public VegetationSegment( public VegetationSegment(
String path, String path,
...@@ -23,7 +24,8 @@ public class VegetationSegment { ...@@ -23,7 +24,8 @@ public class VegetationSegment {
double terrain_offset, double terrain_offset,
double [] scene_offsets, // has NaNs double [] scene_offsets, // has NaNs
double [][] tva, double [][] tva,
double [] confidence) { double [] confidence,
boolean [] overlaid) {
this.path = path; this.path = path;
this.woi = woi; this.woi = woi;
this.woi_veg = woi_veg; this.woi_veg = woi_veg;
...@@ -31,6 +33,22 @@ public class VegetationSegment { ...@@ -31,6 +33,22 @@ public class VegetationSegment {
this.tva = tva; this.tva = tva;
this.terrain_offset = terrain_offset; this.terrain_offset = terrain_offset;
this.confidence = confidence; this.confidence = confidence;
this.overlaid = overlaid;
correctTerrainOffset();
}
public void correctTerrainOffset() {
if (!Double.isNaN(terrain_offset) && (overlaid != null)) {
int woi_length = woi.width * woi.height;
for (int windx = 0; windx < woi_length; windx++) {
int wx = windx % woi.width;
int wy = windx / woi.height;
int wvindx = (wx + woi.x - woi_veg.x) + (wy + woi.y - woi_veg.y) * woi_veg.width;
if (overlaid[windx]) {
tva[0][wvindx] += terrain_offset;
}
}
}
} }
public static Rectangle getBounds( // [0] - woi, [1] - woi_weg public static Rectangle getBounds( // [0] - woi, [1] - woi_weg
...@@ -98,7 +116,7 @@ public class VegetationSegment { ...@@ -98,7 +116,7 @@ public class VegetationSegment {
int x = wx + woi.x - out_woi.x; int x = wx + woi.x - out_woi.x;
int y = wy + woi.y - out_woi.y; int y = wy + woi.y - out_woi.y;
int indx = x + y * out_woi.width; int indx = x + y * out_woi.width;
preview_data[t][ns][indx] = woi_tva[t][wsrc]; preview_data[t][ns][indx] = woi_tva[t][wsrc]; // java.lang.ArrayIndexOutOfBoundsException: Index -43 out of bounds for length 550
} }
break; break;
case 1: // vegetation case 1: // vegetation
...@@ -156,10 +174,11 @@ public class VegetationSegment { ...@@ -156,10 +174,11 @@ public class VegetationSegment {
} }
VegetationModel vegetationModel = vegetationLMA.getModel(); VegetationModel vegetationModel = vegetationLMA.getModel();
String ref_scene = vegetationModel.reference_scene; String ref_scene = vegetationModel.reference_scene;
String pre_title = ref_scene+"-preview_segments-"+out_woi.x+"-"+out_woi.y+"-"+out_woi.width+"-"+out_woi.height;
ShowDoubleFloatArrays.showArraysHyperstack( ShowDoubleFloatArrays.showArraysHyperstack(
preview_data, // double[][][] pixels, preview_data, // double[][][] pixels,
out_woi.width, // int width, out_woi.width, // int width,
ref_scene+"-preview_segments", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy, pre_title, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles, // String [] titles, // all slices*frames titles or just slice titles or null titles, // String [] titles, // all slices*frames titles or just slice titles or null
top_titles, // String [] frame_titles, // frame titles or null top_titles, // String [] frame_titles, // frame titles or null
true); // boolean show) true); // boolean show)
...@@ -185,13 +204,23 @@ public class VegetationSegment { ...@@ -185,13 +204,23 @@ public class VegetationSegment {
um_weight); // final double um_weight) um_weight); // final double um_weight)
String [] result_titles = {"ref_render", "terrain_accum",String.format("terrain_accum_UM%5.2f-%4.2f",um_sigma,um_weight),"terrain"}; String [] result_titles = {"ref_render", "terrain_accum",String.format("terrain_accum_UM%5.2f-%4.2f",um_sigma,um_weight),"terrain"};
double [][] result_img = {terrain_reference,terrain_accumulated,terrain_um,preview_data[0][accum_indx]}; double [][] result_img = {terrain_reference,terrain_accumulated,terrain_um,preview_data[0][accum_indx]};
// ref_scene+"-result-terrain" boolean normalize = true;
int norm_index = 1;
if (normalize) {
result_img = normalize (
result_img, // final double [][] data,
norm_index); // final int norm_index){
}
String res_title = ref_scene+"-result_terrain-"+out_woi.x+"-"+out_woi.y+"-"+out_woi.width+"-"+out_woi.height;
if (normalize) {
res_title+= "-normalized"+norm_index;
}
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
result_img, result_img,
out_woi.width, out_woi.width,
out_woi.height, out_woi.height,
true, true,
ref_scene+"-result_terrain", res_title,
result_titles); result_titles);
...@@ -439,6 +468,68 @@ public class VegetationSegment { ...@@ -439,6 +468,68 @@ public class VegetationSegment {
} }
return cropped; return cropped;
} }
/**
* Normalize slices to match the selected one by average and standard deviation
* @param data array of image slices
* @param norm_index index (0-based) of the reference slice
* @return normalized image
*/
public static double [][] normalize (
final double [][] data,
final int norm_index){
final int num_slices = data.length;
final int num_pix = data[0].length;
double [][] normalized = new double [num_slices][];
for (int i = 0; i < num_slices; i++) {
normalized[i] = data[i].clone();
}
final double [] mean = new double[num_slices];
final double [] std = new double[num_slices];
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nSlice = ai.getAndIncrement(); nSlice < num_slices; nSlice = ai.getAndIncrement()) {
double [] slice = normalized[nSlice];
double s0=0, s1=0, s2=0;
for (int i = 0; i < slice.length; i++) if (!Double.isNaN(slice[i])) {
s0 += 1;
s1 += slice[i];
s2 += slice[i]*slice[i];
}
s1 /= s0;
s2 /= s0;
mean[nSlice] = s1;
std[nSlice] = Math.sqrt(s2 - s1 * s1);
}
}
};
}
ImageDtt.startAndJoin(threads);
final double [] a = new double [num_slices], b = new double[num_slices];
Arrays.fill(a, 1);
for (int n = 0; n < num_slices; n++) if (n != norm_index){
a[n] = std[norm_index]/std[n];
b[n] = mean[norm_index] - a[n]*mean[n];
}
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nPix = ai.getAndIncrement(); nPix < num_pix; nPix = ai.getAndIncrement()) {
for (int n = 0; n < num_slices; n++) if (n != norm_index){
double d = normalized[n][nPix];
if (!Double.isNaN(d)) {
normalized[n][nPix] = a[n]*d + b[n];
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return normalized;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment