Commit 7506079e authored by Andrey Filippov's avatar Andrey Filippov

Refactoring, bug fixing

parent a45f56ef
......@@ -5802,9 +5802,13 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
} else if (label.equals("Process Merged")) {
OrangeTest.processMerged();
} else if (label.equals("Vegetation LMA")) {
VegetationModel.testVegetationLMA(false); //boolean combine_segments);
VegetationModel.testVegetationLMA(
CLT_PARAMETERS, //CLTParameters clt_parameters,
false); //boolean combine_segments);
} else if (label.equals("Combine LMA Segments")) {
VegetationModel.testVegetationLMA(true); //boolean combine_segments);
VegetationModel.testVegetationLMA(
CLT_PARAMETERS, //CLTParameters clt_parameters,
true); //boolean combine_segments);
}
//
}
......
......@@ -24,6 +24,7 @@
*/
package com.elphel.imagej.tileprocessor;
import java.awt.Color;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.Properties;
import java.util.StringTokenizer;
......@@ -719,6 +720,66 @@ min_str_neib_fpn 0.35
public Color annotate_color_mono = new Color( 255, 180, 50); // reddish over grey
public boolean annotate_transparent_mono = false; // // black if not transparent
// terrain parameters
public boolean terr_um_en = true;
public double terr_um_sigma = 1.0;
public double terr_um_weight = 0.8;
public boolean terr_tile_woi = true; // if false - use woi50;
public Rectangle terr_woi_enclos = new Rectangle(80, 210, 210, 230); // will be tiled, using width/height from woi_step;
public Rectangle terr_woi_step = new Rectangle(10,10,20,20);
public Rectangle terr_woi_last = new Rectangle(0,0,0,0); // also single
public boolean terr_skip_exist= true; // skip existing woi/parameters, already saved.
public boolean terr_continue= false; // start from last/single
public int terr_min_scenes = 1; // minimal number of scenes (inside woi) vegetation pixel must influence
public double terr_alpha_dflt = 0.5;
public double terr_alpha_loss = 100.0;
public double terr_alpha_offset = 0.0;
public double terr_alpha_lpf = 2.5; // pull to average of 4 neighbors
public boolean terr_alpha_piece_linear = true;
public double terr_alpha_scale_avg = 1.0; // scale average alpha (around 0.5) when pulling to it
public double terr_alpha_push = 12; // push from alpha==0.5
public double terr_alpha_push_neutral = 0.5; // alpha point from which push (closer to opaque)
public double terr_alpha_weight_center =1.5; // weight of center alpha pixel relative to each of the 4 ortho ones
public double terr_alpha_mm_hole = 0.1; // NaN to disable. Local "almost minimum" (lower than this fraction between min and max neighbor) is not subject to alpha_lpf
public double terr_terr_lpf = 0.1; // pull terrain to average of 4 neighbors (very small)
public double terr_veget_lpf = 0.2; // pull vegetation to average of 4 neighbors (very small - maybe not needed)
public double terr_terr_pull0 = 0.05; // pull terrain to zero (makes sense with UM
public double terr_veget_pull0 = 0.05; // pull vegetation to zero (makes sense with UM
// LMA parameters
public double terr_boost_parallax = 3.0; //
public double terr_reg_weights = 0.25; // fraction of the total weight used for regularization
public double terr_lambda = 5.0; //
public double terr_lambda_scale_good = 0.5;
public double terr_lambda_scale_bad = 8.0;
public double terr_lambda_max = 1000;
public double terr_rms_diff = 1e-8; // 0.0001; virtually forever
public int terr_num_iter = 25; // 100;
// combine parameters
public int terr_border_width = 6;
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 double terr_alpha_min = 0.1; // below - completely transparent vegetation
public double terr_alpha_max = 0.8; // above - completely opaque
public double terr_weight_opaque = 0.02; // render through completely opaque vegetation
public int terr_num_exaggerate = 3; // generate exagerrated rendering
// Experimental reconstruction
public double terr_threshold_terrain = 0.05;
public double terr_min_max_terrain= 0.1;
public double terr_min_terrain = 0.001;
public double terr_min_vegetation = 0.5;
// public String ter_rendered_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/1697877491_613999-terrain_vegetation_render.tiff";
// public String ter_warp_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/1697877491_613999-combo_offset.tiff";
public boolean renderRef() {return renderRef (debug_level);}
public boolean renderScene() {return renderScene (debug_level);}
......@@ -1878,6 +1939,63 @@ min_str_neib_fpn 0.35
gd.addCheckbox ("Transparent timestamp background (monochrome)",this.annotate_transparent_mono,
"Put monochrome timestamp over image (unchecked - use black background). Color - always black.");
// vegetation
gd.addTab("Vegetation","See through foliage parameters");
gd.addCheckbox ("Enable UM", terr_um_en, "Enable unsharp mask filter.");
gd.addNumericField("UM sigma", terr_um_sigma, 5,7, "pix", "Unsharp mask sigma.");
gd.addNumericField("UM weight", terr_um_weight, 5,7, "", "Unsharp mask weight.");
gd.addMessage ("Scan WOI parameters");
gd.addCheckbox ("Tiled WOI", terr_tile_woi, "Process tiled WOI (False - a single one).");
gd.addCheckbox ("Continue WOI", terr_continue, "Continue WOI scan after \"Single/last WOI\"");
gd.addStringField ("Scan enclosing WOI", rectangleToString(terr_woi_enclos), 40, "Scan WOI position and size.");
gd.addStringField ("Step WOI", rectangleToString(terr_woi_step), 40, "Scan step (x,y) and size (width, hight).");
gd.addStringField ("Single/last WOI", rectangleToString(terr_woi_last), 40, "A single/last scanned WOI.");
gd.addCheckbox ("Skip existing WOI", terr_skip_exist, "Skip already esisting WOIs during scanning.");
gd.addMessage ("LMA losses and goals for alpha, terrain and vegetation pixels");
gd.addNumericField("Min influenced scenes",terr_min_scenes, 0,3, "", "Minimal number of scenes (inside woi) vegetation pixel must influence.");
gd.addNumericField("Defalt alpha", terr_alpha_dflt, 5,7,"", "Default vegetation alpha.");
gd.addNumericField("Alpha loss", terr_alpha_loss, 5,7,"", "Alpha quadratic growing loss for when out of [0,1] range");
gd.addNumericField("Alpha offset", terr_alpha_offset, 5,7,"", "Start alpha losses above 0.0 and below 1.0 by this value.");
gd.addNumericField("Alpha diffusion", terr_alpha_lpf, 5,7,"", "Alpha diffusion to 4 ortho neighbors.");
gd.addCheckbox ("Alpha piece-linear", terr_alpha_piece_linear, "Piece-linear alpha (_/\u203E, false - 0.0-cosine-1.0.");
gd.addNumericField("Scale alpha", terr_alpha_scale_avg, 5,7,"","Scale target (average of neighbors) alpha before pulling to it (not used now).");
gd.addNumericField("Push alpha", terr_alpha_push, 5,7,"", "Quadratic loss for middle alpha (push to 0.0 or 1.0.");
gd.addNumericField("Neutral alpha", terr_alpha_push_neutral, 5,7,"", "Alpha point from which to push (default 0.5).");
gd.addNumericField("Alpha center weight", terr_alpha_weight_center, 5,7,"","Weight of center alpha pixel relative to each of the 4 ortho ones.");
gd.addNumericField("Alpha MM fraction", terr_alpha_mm_hole, 5,7,"", "Disable diffusion for local \"almost minimum\" (lower than this fraction between min and max neighbors).");
gd.addNumericField("Terrain diffusion", terr_terr_lpf, 5,7,"", "LPF for terrain pixels (diffusion to 4 neighbors).");
gd.addNumericField("Vegetation diffusion", terr_veget_lpf, 5,7,"", "LPF for vegetation pixels (diffusion to 4 neighbors).");
gd.addNumericField("Terrain pull zero", terr_terr_pull0, 5,7,"", "Terrain pixels pull to 0 (makes sense with UM).");
gd.addNumericField("Vegetation pull zero", terr_veget_pull0, 5,7,"", "Vegetation pixels pull to 0 (makes sense with UM).");
gd.addMessage ("LMA parameters");
gd.addNumericField("Boost parallax", terr_boost_parallax, 5,7,"", "Increase weight of scenes that have high parallax to the reference one.");
gd.addNumericField("Losses weight", terr_reg_weights, 5,7,"", "Fraction of other losses compared to the RMSE.");
gd.addNumericField("Initial lambda", terr_lambda, 5,7,"", "Initial LMA lambda.");
gd.addNumericField("Lambda scale on good", terr_lambda_scale_good, 5,7,"","Scale lambda if RMSE improved.");
gd.addNumericField("Lambda scale on bad", terr_lambda_scale_bad, 5,7,"","Scale lambda if RMSE worsened.");
gd.addNumericField("Lambda max to fail", terr_lambda_max, 5,7,"", "Fail if lambda gets larger than that.");
gd.addNumericField("RMSE difference", terr_rms_diff, 8,10,"", "Exit if RMSE improvement is lower.");
gd.addNumericField("(Maximal) iterations", terr_num_iter, 0,3,"", "Maximal number of LMA iterations.");
gd.addMessage ("Combining LMA results segments");
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 no alpha", terr_render_no_alpha, "");
gd.addNumericField("Transparent alpha", terr_alpha_min, 5,7,"", ".");
gd.addNumericField("Opaque alpha", terr_alpha_max, 5,7,"", ".");
gd.addNumericField("Opaque weight", terr_weight_opaque, 5,7,"", ".");
gd.addNumericField("Exagerrate steps", terr_num_exaggerate, 0,3,"", ".");
gd.addMessage ("Experimental");
gd.addNumericField("Terrain threshold alpha",terr_threshold_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 vegetation", terr_min_vegetation, 5,7,"", ".");
}
public void dialogAnswers(GenericJTabbedDialog gd) {
......@@ -2494,8 +2612,56 @@ min_str_neib_fpn 0.35
}
this.annotate_transparent_mono= gd.getNextBoolean();
// vegetation
terr_um_en = gd.getNextBoolean();// boolean
terr_um_sigma = gd.getNextNumber();// double
terr_um_weight = gd.getNextNumber();// double
terr_tile_woi = gd.getNextBoolean();// boolean
terr_continue = gd.getNextBoolean();// boolean
terr_woi_enclos = stringToRectangle(gd.getNextString());// Rectangle
terr_woi_step = stringToRectangle(gd.getNextString());// Rectangle
terr_woi_last = stringToRectangle(gd.getNextString());// Rectangle
terr_skip_exist = gd.getNextBoolean();// boolean
terr_min_scenes = (int) gd.getNextNumber();// int
terr_alpha_dflt = gd.getNextNumber();// double
terr_alpha_loss = gd.getNextNumber();// double
terr_alpha_offset = gd.getNextNumber();// double
terr_alpha_lpf = gd.getNextNumber();// double
terr_alpha_piece_linear = gd.getNextBoolean();// boolean
terr_alpha_scale_avg = gd.getNextNumber();// double
terr_alpha_push = gd.getNextNumber();// double
terr_alpha_push_neutral = gd.getNextNumber();// double
terr_alpha_weight_center = gd.getNextNumber();// double
terr_alpha_mm_hole = gd.getNextNumber();// double
terr_terr_lpf = gd.getNextNumber();// double
terr_veget_lpf = gd.getNextNumber();// double
terr_terr_pull0 = gd.getNextNumber();// double
terr_veget_pull0 = gd.getNextNumber();// double
terr_boost_parallax = gd.getNextNumber();// double
terr_reg_weights = gd.getNextNumber();// double
terr_lambda = gd.getNextNumber();// double
terr_lambda_scale_good = gd.getNextNumber();// double
terr_lambda_scale_bad = gd.getNextNumber();// double
terr_lambda_max = gd.getNextNumber();// double
terr_rms_diff = gd.getNextNumber();// double
terr_num_iter = (int) gd.getNextNumber();// int
terr_border_width = (int) gd.getNextNumber();// int
terr_render_open = gd.getNextBoolean();// boolean
terr_render_no_alpha = gd.getNextBoolean();// boolean
terr_alpha_min = gd.getNextNumber();// double
terr_alpha_max = gd.getNextNumber();// double
terr_weight_opaque = gd.getNextNumber();// double
terr_num_exaggerate = (int)gd.getNextNumber();// int
terr_threshold_terrain = gd.getNextNumber();// double
terr_min_max_terrain = gd.getNextNumber();// double
terr_min_terrain = gd.getNextNumber();// double
terr_min_vegetation = gd.getNextNumber();// double
// end of vegetation
if (this.weight_zero_neibs > 1.0) this.weight_zero_neibs = 1.0;
}
......@@ -3084,6 +3250,58 @@ min_str_neib_fpn 0.35
}
properties.setProperty(prefix+"annotate_transparent_mono",this.annotate_transparent_mono+"");// boolean
// vegetation
properties.setProperty(prefix+"terr_um_en", terr_um_en+""); // boolean
properties.setProperty(prefix+"terr_um_sigma", terr_um_sigma+""); // double
properties.setProperty(prefix+"terr_um_weight", terr_um_weight+""); // double
properties.setProperty(prefix+"terr_tile_woi", terr_tile_woi+""); // boolean
properties.setProperty(prefix+"terr_continue", terr_continue+""); // boolean
properties.setProperty(prefix+"terr_woi_enclos", rectangleToString(terr_woi_enclos)+""); // Rectangle
properties.setProperty(prefix+"terr_woi_step", rectangleToString(terr_woi_step)+""); // Rectangle
properties.setProperty(prefix+"terr_woi_last", rectangleToString(terr_woi_last)+""); // Rectangle
properties.setProperty(prefix+"terr_skip_exist", terr_skip_exist+""); // boolean
properties.setProperty(prefix+"terr_min_scenes", terr_min_scenes+""); // int
properties.setProperty(prefix+"terr_alpha_dflt", terr_alpha_dflt+""); // double
properties.setProperty(prefix+"terr_alpha_loss", terr_alpha_loss+""); // double
properties.setProperty(prefix+"terr_alpha_offset", terr_alpha_offset+""); // double
properties.setProperty(prefix+"terr_alpha_lpf", terr_alpha_lpf+""); // double
properties.setProperty(prefix+"terr_alpha_piece_linear", terr_alpha_piece_linear+""); // boolean
properties.setProperty(prefix+"terr_alpha_scale_avg", terr_alpha_scale_avg+""); // double
properties.setProperty(prefix+"terr_alpha_push", terr_alpha_push+""); // double
properties.setProperty(prefix+"terr_alpha_push_neutral", terr_alpha_push_neutral+""); // double
properties.setProperty(prefix+"terr_alpha_weight_center", terr_alpha_weight_center+"");// double
properties.setProperty(prefix+"terr_alpha_mm_hole", terr_alpha_mm_hole+""); // double
properties.setProperty(prefix+"terr_terr_lpf", terr_terr_lpf+""); // double
properties.setProperty(prefix+"terr_veget_lpf", terr_veget_lpf+""); // double
properties.setProperty(prefix+"terr_terr_pull0", terr_terr_pull0+""); // double
properties.setProperty(prefix+"terr_veget_pull0", terr_veget_pull0+""); // double
properties.setProperty(prefix+"terr_boost_parallax", terr_boost_parallax+""); // double
properties.setProperty(prefix+"terr_reg_weights", terr_reg_weights+""); // double
properties.setProperty(prefix+"terr_lambda", terr_lambda+""); // double
properties.setProperty(prefix+"terr_lambda_scale_good", terr_lambda_scale_good+""); // double
properties.setProperty(prefix+"terr_lambda_scale_bad", terr_lambda_scale_bad+""); // double
properties.setProperty(prefix+"terr_lambda_max", terr_lambda_max+""); // double
properties.setProperty(prefix+"terr_rms_diff", terr_rms_diff+""); // double
properties.setProperty(prefix+"terr_num_iter", terr_num_iter+""); // 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_no_alpha", terr_render_no_alpha+""); // boolean
properties.setProperty(prefix+"terr_alpha_min", terr_alpha_min+""); // double
properties.setProperty(prefix+"terr_alpha_max", terr_alpha_max+""); // double
properties.setProperty(prefix+"terr_weight_opaque", terr_weight_opaque+""); // double
properties.setProperty(prefix+"terr_num_exaggerate", terr_num_exaggerate+""); // int
properties.setProperty(prefix+"terr_threshold_terrain", terr_threshold_terrain+""); // double
properties.setProperty(prefix+"terr_min_max_terrain", terr_min_max_terrain+""); // double
properties.setProperty(prefix+"terr_min_terrain", terr_min_terrain+""); // double
properties.setProperty(prefix+"terr_min_vegetation", terr_min_vegetation+""); // double
// end of vegetation
}
public void getProperties(String prefix,Properties properties){
......@@ -3692,6 +3910,59 @@ min_str_neib_fpn 0.35
else this.annotate_color_mono = setLongColor(lcolor_annotate);
}
if (properties.getProperty(prefix+"annotate_transparent_mono")!=null) this.annotate_transparent_mono=Boolean.parseBoolean(properties.getProperty(prefix+"annotate_transparent_mono"));
// vegetation
if (properties.getProperty(prefix+"terr_um_en")!= null) terr_um_en=Boolean.parseBoolean(properties.getProperty(prefix+"terr_um_en"));
if (properties.getProperty(prefix+"terr_um_sigma")!= null) terr_um_sigma=Double.parseDouble(properties.getProperty(prefix+"terr_um_sigma"));
if (properties.getProperty(prefix+"terr_um_weight")!= null) terr_um_weight=Double.parseDouble(properties.getProperty(prefix+"terr_um_weight"));
if (properties.getProperty(prefix+"terr_tile_woi")!= null) terr_tile_woi=Boolean.parseBoolean(properties.getProperty(prefix+"terr_tile_woi"));
if (properties.getProperty(prefix+"terr_continue")!= null) terr_continue=Boolean.parseBoolean(properties.getProperty(prefix+"terr_continue"));
if (properties.getProperty(prefix+"terr_woi_enclos")!= null) terr_woi_enclos=stringToRectangle((String) properties.getProperty(prefix+"terr_woi_enclos"));
if (properties.getProperty(prefix+"terr_woi_step")!= null) terr_woi_step=stringToRectangle((String) properties.getProperty(prefix+"terr_woi_step"));
if (properties.getProperty(prefix+"terr_woi_last")!= null) terr_woi_last=stringToRectangle((String) properties.getProperty(prefix+"terr_woi_last"));
if (properties.getProperty(prefix+"terr_skip_exist")!= null) terr_skip_exist=Boolean.parseBoolean(properties.getProperty(prefix+"terr_skip_exist"));
if (properties.getProperty(prefix+"terr_min_scenes")!= null) terr_min_scenes=Integer.parseInt(properties.getProperty(prefix+"terr_min_scenes"));
if (properties.getProperty(prefix+"terr_alpha_dflt")!= null) terr_alpha_dflt=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_dflt"));
if (properties.getProperty(prefix+"terr_alpha_loss")!= null) terr_alpha_loss=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_loss"));
if (properties.getProperty(prefix+"terr_alpha_offset")!= null) terr_alpha_offset=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_offset"));
if (properties.getProperty(prefix+"terr_alpha_lpf")!= null) terr_alpha_lpf=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_lpf"));
if (properties.getProperty(prefix+"terr_alpha_piece_linear")!= null) terr_alpha_piece_linear=Boolean.parseBoolean(properties.getProperty(prefix+"terr_alpha_piece_linear"));
if (properties.getProperty(prefix+"terr_alpha_scale_avg")!= null) terr_alpha_scale_avg=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_scale_avg"));
if (properties.getProperty(prefix+"terr_alpha_push")!= null) terr_alpha_push=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_push"));
if (properties.getProperty(prefix+"terr_alpha_push_neutral")!= null) terr_alpha_push_neutral=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_push_neutral"));
if (properties.getProperty(prefix+"terr_alpha_weight_center")!=null) terr_alpha_weight_center=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_weight_center"));
if (properties.getProperty(prefix+"terr_alpha_mm_hole")!= null) terr_alpha_mm_hole=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_mm_hole"));
if (properties.getProperty(prefix+"terr_terr_lpf")!= null) terr_terr_lpf=Double.parseDouble(properties.getProperty(prefix+"terr_terr_lpf"));
if (properties.getProperty(prefix+"terr_veget_lpf")!= null) terr_veget_lpf=Double.parseDouble(properties.getProperty(prefix+"terr_veget_lpf"));
if (properties.getProperty(prefix+"terr_terr_pull0")!= null) terr_terr_pull0=Double.parseDouble(properties.getProperty(prefix+"terr_terr_pull0"));
if (properties.getProperty(prefix+"terr_veget_pull0")!= null) terr_veget_pull0=Double.parseDouble(properties.getProperty(prefix+"terr_veget_pull0"));
if (properties.getProperty(prefix+"terr_boost_parallax")!= null) terr_boost_parallax=Double.parseDouble(properties.getProperty(prefix+"terr_boost_parallax"));
if (properties.getProperty(prefix+"terr_reg_weights")!= null) terr_reg_weights=Double.parseDouble(properties.getProperty(prefix+"terr_reg_weights"));
if (properties.getProperty(prefix+"terr_lambda")!= null) terr_lambda=Double.parseDouble(properties.getProperty(prefix+"terr_lambda"));
if (properties.getProperty(prefix+"terr_lambda_scale_good")!= null) terr_lambda_scale_good=Double.parseDouble(properties.getProperty(prefix+"terr_lambda_scale_good"));
if (properties.getProperty(prefix+"terr_lambda_scale_bad")!= null) terr_lambda_scale_bad=Double.parseDouble(properties.getProperty(prefix+"terr_lambda_scale_bad"));
if (properties.getProperty(prefix+"terr_lambda_max")!= null) terr_lambda_max=Double.parseDouble(properties.getProperty(prefix+"terr_lambda_max"));
if (properties.getProperty(prefix+"terr_rms_diff")!= null) terr_rms_diff=Double.parseDouble(properties.getProperty(prefix+"terr_rms_diff"));
if (properties.getProperty(prefix+"terr_num_iter")!= null) terr_num_iter=Integer.parseInt(properties.getProperty(prefix+"terr_num_iter"));
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_no_alpha")!= null) terr_render_no_alpha=Boolean.parseBoolean(properties.getProperty(prefix+"terr_render_no_alpha"));
if (properties.getProperty(prefix+"terr_alpha_min")!= null) terr_alpha_min=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_min"));
if (properties.getProperty(prefix+"terr_alpha_max")!= null) terr_alpha_max=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_max"));
if (properties.getProperty(prefix+"terr_weight_opaque")!= null) terr_weight_opaque=Double.parseDouble(properties.getProperty(prefix+"terr_weight_opaque"));
if (properties.getProperty(prefix+"terr_num_exaggerate")!= null) terr_num_exaggerate=Integer.parseInt(properties.getProperty(prefix+"terr_num_exaggerate"));
if (properties.getProperty(prefix+"terr_threshold_terrain")!= null) terr_threshold_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_threshold_terrain"));
if (properties.getProperty(prefix+"terr_min_max_terrain")!= null) terr_min_max_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_max_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"));
// end of vegetation
}
@Override
......@@ -4268,6 +4539,57 @@ min_str_neib_fpn 0.35
imp.annotate_color_mono = this. annotate_color_mono;
imp.annotate_transparent_mono = this. annotate_transparent_mono;
// vegetation
imp.terr_um_en = this.terr_um_en;
imp.terr_um_sigma = this.terr_um_sigma;
imp.terr_um_weight = this.terr_um_weight;
imp.terr_tile_woi = this.terr_tile_woi;
imp.terr_continue = this.terr_continue;
imp.terr_woi_enclos = new Rectangle(this.terr_woi_enclos);
imp.terr_woi_step = new Rectangle(this.terr_woi_step);
imp.terr_woi_last = new Rectangle(this.terr_woi_last);
imp.terr_skip_exist = this.terr_skip_exist;
imp.terr_min_scenes = this.terr_min_scenes;
imp.terr_alpha_dflt = this.terr_alpha_dflt;
imp.terr_alpha_loss = this.terr_alpha_loss;
imp.terr_alpha_offset = this.terr_alpha_offset;
imp.terr_alpha_lpf = this.terr_alpha_lpf;
imp.terr_alpha_piece_linear = this.terr_alpha_piece_linear;
imp.terr_alpha_scale_avg = this.terr_alpha_scale_avg;
imp.terr_alpha_push = this.terr_alpha_push;
imp.terr_alpha_push_neutral = this.terr_alpha_push_neutral;
imp.terr_alpha_weight_center = this.terr_alpha_weight_center;
imp.terr_alpha_mm_hole = this.terr_alpha_mm_hole;
imp.terr_terr_lpf = this.terr_terr_lpf;
imp.terr_veget_lpf = this.terr_veget_lpf;
imp.terr_terr_pull0 = this.terr_terr_pull0;
imp.terr_veget_pull0 = this.terr_veget_pull0;
imp.terr_boost_parallax = this.terr_boost_parallax;
imp.terr_reg_weights = this.terr_reg_weights;
imp.terr_lambda = this.terr_lambda;
imp.terr_lambda_scale_good = this.terr_lambda_scale_good;
imp.terr_lambda_scale_bad = this.terr_lambda_scale_bad;
imp.terr_lambda_max = this.terr_lambda_max;
imp.terr_rms_diff = this.terr_rms_diff;
imp.terr_num_iter = this.terr_num_iter;
imp.terr_border_width = this.terr_border_width;
imp.terr_render_open = this.terr_render_open;
imp.terr_render_no_alpha = this.terr_render_no_alpha;
imp.terr_alpha_min = this.terr_alpha_min;
imp.terr_alpha_max = this.terr_alpha_max;
imp.terr_weight_opaque = this.terr_weight_opaque;
imp.terr_num_exaggerate = this.terr_num_exaggerate;
imp.terr_threshold_terrain = this.terr_threshold_terrain;
imp.terr_min_max_terrain = this.terr_min_max_terrain;
imp.terr_min_terrain = this.terr_min_terrain;
imp.terr_min_vegetation = this.terr_min_vegetation;
// end of vegetation
return imp;
}
......@@ -4363,13 +4685,63 @@ min_str_neib_fpn 0.35
}
}
public static String rectangleToString(Rectangle r) {
return intsToString(new int []{r.x,r.y,r.width, r.height});
}
public static Rectangle stringToRectangle(String s) {
int [] data = StringToInts(s, 4);
return new Rectangle(data[0], data[1], data[2], data[3]);
}
public static String intsToString(int [] data) {
return intsToString(data, null);
}
public static String intsToString(int [] data, String fmt) {
String s = "";
for (int i = 0; i < data.length; i++) {
if (fmt==null) {
s += data[i]; // unformatted
} else {
s+=String.format(fmt,data[i]);
}
if (i < (data.length - 1)) {
s+= ", ";
}
}
return s;
}
public static int [] StringToInts(String s, int len) {
StringTokenizer st = new StringTokenizer(s, " \t\n\r\f,");
if (st.countTokens() == 0) {
return null;
}
if (len <= 0) {
len = st.countTokens();
}
int [] data = new int [len];
int i = 0;
while (st.hasMoreTokens() && (i < len)) {
int d = 0;
try {
d = Integer.parseInt(st.nextToken());
} catch(NumberFormatException e){
d = 0;
}
data[i++] = d;
}
return data;
}
public static String doublesToString(double [] data) {
return doublesToString(data, null);
}
public static String doublesToString(double [] data, String fmt) {
// if ((fmt == null) || (fmt.trim().length()==0)) {
// fmt = "%.0f";
// }
String s = "";
for (int i = 0; i < data.length; i++) {
if (fmt==null) {
......@@ -4451,6 +4823,5 @@ min_str_neib_fpn 0.35
}
return s;
}
}
......@@ -5687,20 +5687,26 @@ public class OpticalFlow {
// generates 3-d modes, colors, stereos, tiffs/videos
// Testing vegetation, for debugging supposing that terrain layer is already set in *-INTER-INTRA-LMA.tiff - normally it is only set during 3d model generation
// Moved to the very end, after 3D
boolean test_vegetation = true;
/*
if (test_vegetation) { // limit start of the quadCLTs by reading start/end from the reference scene
int [] first_last = quadCLTs[ref_index].getFirstLastIndex(quadCLTs);
QuadCLT [] quadCLT_tail = new QuadCLT [quadCLTs.length - earliest_scene];
System.arraycopy(quadCLTs, earliest_scene, quadCLT_tail, 0, quadCLT_tail.length);
VegetationModel.test_vegetation(
clt_parameters, // CLTParameters clt_parameters,
quadCLTs, // QuadCLT [] quadCLTs,
ref_index, // int ref_index,
debugLevel); // int debugLevel)
clt_parameters, // CLTParameters clt_parameters,
quadCLT_tail, // QuadCLT [] quadCLTs,
ref_index-earliest_scene, // int ref_index,
debugLevel); // int debugLevel)
if (videos != null) {
videos[0] = new String[0];
}
// temporarily - exiting now
return quadCLTs[ref_index].getX3dTopDirectory();
}
*/
if (generate_mapped || reuse_video) { // modifies combo_dsn_final ?
......@@ -6357,6 +6363,22 @@ public class OpticalFlow {
}
// boolean test_vegetation = true;
if (test_vegetation) { // limit start of the quadCLTs by reading start/end from the reference scene
// int [] first_last = quadCLTs[ref_index].getFirstLastIndex(quadCLTs);
QuadCLT [] quadCLT_tail = new QuadCLT [quadCLTs.length - earliest_scene];
System.arraycopy(quadCLTs, earliest_scene, quadCLT_tail, 0, quadCLT_tail.length);
VegetationModel.test_vegetation(
clt_parameters, // CLTParameters clt_parameters,
quadCLT_tail, // QuadCLT [] quadCLTs,
ref_index-earliest_scene, // int ref_index,
debugLevel); // int debugLevel)
if (videos != null) {
videos[0] = new String[0];
}
// temporarily - exiting now
}
if (export_images) {
if (combo_dsn_final == null) {
combo_dsn_final =quadCLTs[ref_index].restoreComboDSI(true); // also sets quadCLTs[ref_index].dsi and blue sky
......
......@@ -54,7 +54,13 @@ public class VegetationLMA {
// 0:{ scene, full_indx, terr_indx, scale_indx} - always present as parameters
// 1: [4]/null Z-shape 4 corners vegetation, either >= as parameter index or -1 - (x + image_width*y) of the unmodified full index
// 2: [4]/null Z-shape 4 corners vegetation alpha, either >= as parameter index or -1 - (x + image_width*y) of the unmodified full index
private double [][] corners_weights; // matches data_source, non-nulls specify Z-shape 4 corners of vegetation/alpha weights
private double [][] corners_weights; // matches data_source, non-nulls specify Z-shape 4 corners of vegetation/alpha weights
// private int num_used_scenes; // -> num_par_scenes
private boolean [] used_scenes; // encode unused as NaN
// private int [] used_scenes_indices;
private double [] parameters_vector = null;
private double [] y_vector = null;
......@@ -123,9 +129,7 @@ public class VegetationLMA {
double [][][] vegetation_offsets // [num_scenes][pixel]{dx,dy} differential offsets of vegetation to terrain grid
) {
full = new Rectangle(0,0,width, terrain_average.length/width);
// image_width = width;
image_length = terrain_average.length;
// image_height = image_length/width;
diff_offsets = diff_mode;
num_scenes = vegetation_offsets.length;
this.vegetation_average = vegetation_average;
......@@ -137,13 +141,32 @@ public class VegetationLMA {
tvao[TVAO_VEGETATION] = this.vegetation_average.clone();
tvao[TVAO_VEGETATION_ALPHA] = new double [image_length]; // 0 - use terrain
tvao[TVAO_SCENE_OFFSET] = new double [num_scenes];
}
public VegetationLMA (VegetationModel vegetationModel) {
full = vegetationModel.full;
image_length = full.width * full.height;
num_scenes = vegetationModel.terrain_scenes_render.length;
vegetation_average =vegetationModel.vegetation_average_render;
terrain_average = vegetationModel.terrain_average_render;
terrain_rendered = vegetationModel.terrain_scenes_render;
vegetation_offsets =vegetationModel.vegetation_warp;
tvao = new double[4][];
tvao[TVAO_TERRAIN] = this.terrain_average.clone();
tvao[TVAO_VEGETATION] = this.vegetation_average.clone();
tvao[TVAO_VEGETATION_ALPHA] = new double [image_length]; // 0 - use terrain
tvao[TVAO_SCENE_OFFSET] = new double [num_scenes];
diff_offsets = vegetationModel.diff_mode;
}
public int prepareLMA(
final boolean keep_parameters,
final Rectangle woi,
final int min_scenes, // minimal number of scenes (inside woi) vegetation pixel must influence
final int min_total_scenes,
final int min_samples_scene, // 10
final int min_valid_pixels,
final double default_alpha,
final double reg_weights, // fraction of the total weight used for regularization
final double alpha_loss, // quadratic loss when alpha reaches -1.0 or 2.0
......@@ -160,6 +183,7 @@ public class VegetationLMA {
final double terr_pull0, // pull terrain to zero (makes sense with UM
final double veget_pull0, // pull vegetation to zero (makes sense with UM
final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene
final double max_parallax, // do not consider maximal parallax above this (consider it a glitch)
final double um_sigma, // just use in debug image names
final double um_weight,
String parameters_read_path,
......@@ -181,7 +205,7 @@ public class VegetationLMA {
this.boost_parallax = boost_parallax;
this.um_sigma = um_sigma; // just use in debug image names
this.um_weight = um_weight;
if ("RESTORE".equals(parameters_read_path)) {
from_file = false;
String restore_dir = debug_path;
......@@ -197,14 +221,23 @@ public class VegetationLMA {
final double [] scene_weights = setupSceneWeights(
boost_parallax, // double boost_parallax)
woi); // Rectangle woi)
woi, // Rectangle woi)
max_parallax); // final double ceil_parallax)
int min_scenes_uses = min_scenes;
int min_scenes_used = min_scenes * 4;
boolean [][] valid_woi = filterValidWoi (
min_scenes_uses, // int min_scenes_uses,
min_scenes_used, // int min_scenes_used,
min_valid_pixels, // int min_valid_pixels,
debugLevel > 3); // boolean debug_img){ // 4x?
setupParametersIndices(valid_woi);
if (valid_woi == null) {
System.out.println("Too few valid pixels (< min_valid_pixels="+min_valid_pixels+").");
return -1;
}
setupParametersIndices(valid_woi); // needs to know number of used scenes // all but scenes
// alpha_neibs = getAlphaNeighbors();
alpha_neibs = getNeighbors(
TVAO_VEGETATION_ALPHA, // final int tvao, // TVAO_VEGETATION_ALPHA
......@@ -219,6 +252,16 @@ public class VegetationLMA {
ind_pars_vegetation, // final int ind_samples, // ind_pars_vegetation_alpha
num_pars_vegetation); // final int num_samples); // num_pars_vegetation_alpha
setupDataSource(
min_samples_scene); // int min_samples_scene); // condensed
finishParametersIndices(); // scene-related parameters
if (num_pars_scenes < min_total_scenes) {
System.out.println("Too few valid scenes="+num_pars_scenes+" < min_total_scenes="+min_total_scenes+").");
return -1;
}
if (!keep_parameters) {
setupParametersVector (default_alpha); // areas where both terrain and vegetation are available
}
......@@ -230,7 +273,8 @@ public class VegetationLMA {
1) ;// int gap)
}
setupDataSource(); // condensed
// setupDataSource(
// min_samples_scene); // int min_samples_scene); // condensed
setupYVector();
setupWeights( // after setupParametersIndices
scene_weights,
......@@ -244,9 +288,11 @@ public class VegetationLMA {
}
private double [] setupSceneWeights(
double boost_parallax,
Rectangle woi) {
final double boost_parallax,
final Rectangle woi,
final double ceil_parallax) {
// find max parallax
final double ceil_parallax2 = ceil_parallax * ceil_parallax;
final double [] scene_weights = new double[vegetation_offsets.length];
if (boost_parallax == 0) {
for (int nscene = 0; nscene < vegetation_offsets.length; nscene++) {
......@@ -265,7 +311,7 @@ public class VegetationLMA {
int indx = row*full.width + col;
double [] d = vegetation_offsets[nscene][indx];
if (d != null) {
double d2 = d[0]*d[0] + d[1]*d[1];
double d2 = Math.min(ceil_parallax2, d[0]*d[0] + d[1]*d[1]);
/*
if (d2 > max_parallax2[nscene]) {
System.out.println("setupSceneWeights(): nscene="+nscene+", pix = ("+(i%640)+","+(i/640)+") ="+i+" d2="+d2);
......@@ -512,7 +558,7 @@ public class VegetationLMA {
jtjl_inv = wjtjlambda.inverse(); // check for errors
} catch (RuntimeException e) {
rslt[1] = true;
if (debug_level > 0) {
if (debug_level > -2) {
System.out.println("Singular Matrix!");
}
......@@ -982,11 +1028,13 @@ public class VegetationLMA {
jt[data_source[n][0][2]][n] = 1; // d/dterrain
}
}
double scene_offs = vector[data_source[n][0][3]];
fX[n] = d + scene_offs;
if (jt != null) {
jt[data_source[n][0][3]][n] = 1;
}
if (data_source[n][0][3] >= 0) {
double scene_offs = vector[data_source[n][0][3]];
fX[n] = d + scene_offs;
if (jt != null) {
jt[data_source[n][0][3]][n] = 1;
}
}
}
}
};
......@@ -1315,7 +1363,8 @@ public class VegetationLMA {
private int [] getParamDebugIndices(
int gap) {
int woi_width3=woi.width*3 + 2 * gap;
int num_scene_rows = (int) Math.ceil(1.0*par_index[3].length/woi_width3);
// int num_scene_rows = (int) Math.ceil(1.0*par_index[3].length/woi_width3);
int num_scene_rows = (int) Math.ceil(1.0*num_scenes/woi_width3); // some scenes have NaN
int [] indices = new int [woi_width3 * (woi.height + gap+ num_scene_rows)];
Arrays.fill(indices, -1);
for (int h = 0; h < woi.height; h++) {
......@@ -1327,7 +1376,7 @@ public class VegetationLMA {
}
}
for (int i = 0; i < par_index[3].length; i++) {
indices [((woi.height + gap) * woi_width3) + i] = par_index[3][i];
indices [((woi.height + gap) * woi_width3) + i] = par_index[3][i]; // some will be -1
}
return indices;
}
......@@ -1419,16 +1468,26 @@ public class VegetationLMA {
return dbg_img;
}
public static String getSavePath(
String dir,
String title) { // no .par-tiff
return getSavePath(dir,title,PAR_EXT);
}
public static String getSavePath(
String dir,
String title,
String ext) {
if (!dir.endsWith(Prefs.getFileSeparator())) {
dir+=Prefs.getFileSeparator();
}
return dir+title+PAR_EXT;
return dir+title+ext;
}
public void saveParametersFile(
String dir,
String title, // no .par-tiff
......@@ -1641,6 +1700,7 @@ public class VegetationLMA {
final double alpha_max, // above - completely opaque
final double weight_opaque, // render through completely opaque vegetation
final double boost_parallax, // increase weights of scenes with high parallax relative to the reference one
final double max_parallax,
final int num_exaggerate) { // show amplified difference from filtering
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
......@@ -1713,16 +1773,18 @@ public class VegetationLMA {
Rectangle woi = segments[ns].woi;
int woi_length = woi.width*woi.height;
double scene_offset = segments[ns].scene_offsets[nscene];
double [] wnd = overlapCosineWindow (woi, width);
for (int windx = 0; windx < woi_length; windx++) {
int x = windx % woi.width + woi.x;
int y = windx / woi.width + woi.y;
int indx = x + y * full.width;
for (int t = 0; t < preview_data.length; t++) {
double w = wnd[windx];
sw [indx] += w;
swd[indx] += w * scene_offset ;
}
if (!Double.isNaN(scene_offset)) {
double [] wnd = overlapCosineWindow (woi, width);
for (int windx = 0; windx < woi_length; windx++) {
int x = windx % woi.width + woi.x;
int y = windx / woi.width + woi.y;
int indx = x + y * full.width;
for (int t = 0; t < preview_data.length; t++) {
double w = wnd[windx];
sw [indx] += w;
swd[indx] += w * scene_offset ;
}
}
}
}
(new DoubleGaussianBlur()).blurDouble(
......@@ -1767,7 +1829,8 @@ public class VegetationLMA {
alpha_min, // final double alpha_min, // below - completely transparent vegetation
alpha_max, // final double alpha_max, // above - completely opaque
weight_opaque, // final double weight_opaque, // render through completely opaque vegetation
boost_parallax); // final double boost_parallax) { // increase weights of scenes with high parallax relative to the reference one
boost_parallax, // final double boost_parallax) { // increase weights of scenes with high parallax relative to the reference one
max_parallax); // final double max_parallax)
// num_exaggerate
double [][] result_renders = new double [1+num_exaggerate][];
......@@ -1819,13 +1882,15 @@ public class VegetationLMA {
final double alpha_min, // below - completely transparent vegetation
final double alpha_max, // above - completely opaque
final double weight_opaque, // render through completely opaque vegetation
final double boost_parallax) { // increase weights of scenes with high parallax relative to the reference one
final double boost_parallax, // increase weights of scenes with high parallax relative to the reference one
final double max_parallax) {
final int full_length = full.width*full.height;
final double [] render = new double [full_length];
Arrays.fill(render, Double.NaN);
final double [] scene_weights = setupSceneWeights(
boost_parallax, // double boost_parallax)
full); // Rectangle woi)
full, // Rectangle woi)
max_parallax); //final double ceil_parallax)
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
......@@ -2203,7 +2268,7 @@ public class VegetationLMA {
private void setupDataSource() {
private void setupDataSource(int min_samples_scene) {
final int woi_length = woi.width*woi.height;
final int [][][][] data_src = new int [num_scenes][woi_length][][];
final double [][][] corn_w = new double [num_scenes][woi_length][]; // null where no vegetation
......@@ -2224,7 +2289,8 @@ public class VegetationLMA {
scene_samples[nScene]++;
data_src[nScene][windx] = new int[3][];
// maybe use windx instead of indx below?
data_src[nScene][windx][0] = new int [] {nScene, indx, par_index[TVAO_TERRAIN][indx],par_index[TVAO_SCENE_OFFSET][nScene]};
// data_src[nScene][windx][0] = new int [] {nScene, indx, par_index[TVAO_TERRAIN][indx],par_index[TVAO_SCENE_OFFSET][nScene]};
data_src[nScene][windx][0] = new int [] {nScene, indx, par_index[TVAO_TERRAIN][indx],nScene};
// next 3 not needed - they are already nulls
data_src[nScene][windx][1] = null;
data_src[nScene][windx][2] = null;
......@@ -2269,23 +2335,45 @@ public class VegetationLMA {
ImageDtt.startAndJoin(threads);
// now condense removing nulls in data_src (cornw may still have nulls)
int num_samples = 0;
for (int nscene = 0; nscene < scene_samples.length; nscene++) {
used_scenes = new boolean [num_scenes];
final int [] used_scene_indices = new int [num_scenes];
int num_used_scenes = 0;
for (int nscene = 0; nscene < num_scenes; nscene++) {
int num_prev = num_samples;
num_samples+= scene_samples[nscene];
scene_samples[nscene] = num_prev; // start index
int defined = scene_samples[nscene];
used_scene_indices[nscene] = num_used_scenes;
if (defined >= min_samples_scene) {
used_scenes[nscene] = true;
num_samples+= scene_samples[nscene];
scene_samples[nscene] = num_prev; // start index
num_used_scenes++;
}
}
/*
*
used_scenes_indices = new int [num_used_scenes];
int indx = 0;
for (int nscene = 0; nscene < num_scenes; nscene++) {
if (used_scenes[nscene]) {
used_scenes_indices[indx++] = nscene;
}
}
*/
data_source = new int [num_samples][][];
corners_weights = new double[num_samples][];
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 nScene = ai.getAndIncrement(); nScene < num_scenes; nScene = ai.getAndIncrement()) if (used_scenes[nScene]){
int out_indx = scene_samples[nScene];
for (int windx = 0; windx < woi_length; windx++) {
if (data_src[nScene][windx] != null) {
corners_weights[out_indx] = corn_w[nScene][windx];
data_source [out_indx++] = data_src[nScene][windx];
int [][] dsrc = data_src[nScene][windx];
dsrc[0][3] = ind_pars_scenes + used_scene_indices[dsrc[0][3]]; // replace scene number with the corresponding parameter index
data_source [out_indx++] = dsrc; // data_src[nScene][windx];
}
}
}
......@@ -2293,6 +2381,7 @@ public class VegetationLMA {
};
}
ImageDtt.startAndJoin(threads);
return;
}
private void setupParametersVector(
......@@ -2319,7 +2408,7 @@ public class VegetationLMA {
}
}
}
for (int i = 0; i < par_index[TVAO_SCENE_OFFSET].length; i++) {
for (int i = 0; i < par_index[TVAO_SCENE_OFFSET].length; i++) if (par_index[TVAO_SCENE_OFFSET][i] >= 0){
parameters_vector[par_index[TVAO_SCENE_OFFSET][i]]= tvao[TVAO_SCENE_OFFSET][i];
}
}
......@@ -2393,21 +2482,48 @@ public class VegetationLMA {
num_pars_vegetation_alpha = par_num - ind_pars_vegetation_alpha; // normally should be == num_pars_vegetation
// int num_pars_pixel = par_num;
ind_pars_scenes = par_num;
for (int i = 0; i < par_index[TVAO_SCENE_OFFSET].length; i++) {
par_rindex[par_num][0] = 3;
par_rindex[par_num][1] = i;
par_index[TVAO_SCENE_OFFSET][i] = par_num++;
}
// temporarily assign full rindex, will finalize in finishParametersIndices()
this.par_rindex = par_rindex;
/*
this.par_rindex = new int [par_num][2];
System.arraycopy(par_rindex, 0, this.par_rindex, 0, par_num);
num_pars_scenes = par_num - ind_pars_scenes;
parameters_vector = new double [par_num];
*/
}
private void finishParametersIndices() {
int par_num = ind_pars_scenes;
int [][] par_rindex = this.par_rindex;
for (int i = 0; i < par_index[TVAO_SCENE_OFFSET].length; i++) {
if (used_scenes[i]) {
par_rindex[par_num][0] = 3;
par_rindex[par_num][1] = i;
par_index[TVAO_SCENE_OFFSET][i] = par_num++;
} else {
par_index[TVAO_SCENE_OFFSET][i] = -1;
}
}
this.par_rindex = new int [par_num][2];
System.arraycopy(par_rindex, 0, this.par_rindex, 0, par_num);
num_pars_scenes = par_num - ind_pars_scenes;
parameters_vector = new double [par_num];
}
private boolean [][] filterValidWoi (
int min_scenes_uses,
int min_scenes_used,
int min_valid_pixels,
boolean debug_img){ // 4x?
int max_iter = 100;
boolean [][] valid_pix = new boolean [2][woi.width*woi.height];
......@@ -2426,6 +2542,12 @@ public class VegetationLMA {
if (valid_pix[1][i]) num_valid[1]++;
}
System.out.println("Iteration "+(iter+1)+", valid pixels: terrain "+num_valid[0]+", vegetation "+num_valid[1]+" (was "+num_valid_prev[0]+", "+num_valid_prev[1]+")");
if ((num_valid[0] < min_valid_pixels) || (num_valid[1] < min_valid_pixels)) {
// System.out.println("Too few valid pixels (< min_valid_pixels="+min_valid_pixels+").");
return null;
}
if ((num_valid[0] == num_valid_prev[0]) && (num_valid[1] == num_valid_prev[1])) {
break;
}
......@@ -2526,8 +2648,8 @@ public class VegetationLMA {
}
return num_uses;
}
// public boolean [] getValidVegetation
......
......@@ -10,6 +10,7 @@ import org.apache.commons.math3.analysis.interpolation.PiecewiseBicubicSplineInt
import com.elphel.imagej.cameras.CLTParameters;
import com.elphel.imagej.common.DoubleGaussianBlur;
import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.jp4.JP46_Reader_camera;
import com.elphel.imagej.orthomosaic.OrthoMap;
import com.elphel.imagej.tileprocessor.ErsCorrection;
import com.elphel.imagej.tileprocessor.ImageDtt;
......@@ -20,6 +21,7 @@ import com.elphel.imagej.tileprocessor.TileProcessor;
import ij.ImagePlus;
import ij.ImageStack;
import ij.io.FileSaver;
/*
* in -INTER-INTRA-LMA.tiff: for pixels where ground==terrain, use disparity layer for both, where they are different
......@@ -29,10 +31,13 @@ import ij.ImageStack;
*
*/
public class VegetationModel {
public static final String RENDERED_PATH = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/1697877491_613999-terrain_vegetation_render.tiff";
public static final String WARP_PATH = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/1697877491_613999-combo_offset.tiff";
public static final int WARP_HYPER = 3; // number of hyper-slices in warp file
public static final int RENDERED_HYPER = 2; // number of hyper-slices in rendered
public static final String TERRVEG_EXT = ".terrveg-tiff";
public static final int [][] FOUR_CORNERS_Z =
{
......@@ -45,71 +50,179 @@ public class VegetationModel {
public static final int PXPYD_LEN=3;
public static final int [][] CORN_CW_OFFS = {{0,0},{1,0},{1,1},{0,1}};
public double [][] terrain_scenes_render = null;
public double [] terrain_average_render = null;
public double [] vegetation_average_render = null;
public double [][][] vegetation_warp = null;
public String [] scene_names = null; // TODO: Implement!
public boolean diff_mode = true;
public Rectangle full;
public boolean failed = false;
public String model_directory;
public String model_top_directory;
public boolean isFailed() {
return failed;
}
public static double [][] getTerrainVegetation(
final double [][] combo_dsn,
final int tilesX,
final double min_above, // absolute disparity difference
final int patch_neibs,
final double neibs_pow){ // raise strength to this power when averaging neighbors
final double [] terrain = combo_dsn[OpticalFlow.COMBO_DSN_INDX_TERRAIN];
final double [] ground = combo_dsn[OpticalFlow.COMBO_DSN_INDX_GROUND];
final double [] disparity = combo_dsn[OpticalFlow.COMBO_DSN_INDX_LMA];
final double [] strength = combo_dsn[OpticalFlow.COMBO_DSN_INDX_STRENGTH];
final int num_pixels = disparity.length;
final double [] vegetation = new double [num_pixels];
Arrays.fill(vegetation, Double.NaN);
final int dbg_tile = -(22+17*80);
public void saveState(
String dir,
String title) {
int num_scenes = terrain_scenes_render.length; // == vegetation_warp.length
final int full_length = full.width*full.height;
String [] titles = new String[3*num_scenes + 2];
final double [][] data = new double [titles.length][];
titles[0] = "terrain_accumulated";
data[0] = terrain_average_render;
titles[1] = "vegetation_accumulated";
data [1] = vegetation_average_render;
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
for (int n = 0; n < num_scenes; n++) {
titles[2 + n] = "terrain_scene_"+n;
data [2 + n] = terrain_scenes_render[n];
final int fslice = 2 + num_scenes + 2*n;
titles[fslice + 0] = "vegetation_warp_"+n+"_x";
titles[fslice + 1] = "vegetation_warp_"+n+"_y";
data [fslice + 0] = new double [full_length];
data [fslice + 1] = new double [full_length];
ai.set(0);
final int fscene = n;
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nPix = ai.getAndIncrement(); nPix < full_length; nPix = ai.getAndIncrement()) {
if (vegetation_warp[fscene][nPix] == null) {
data [fslice + 0][nPix] = Double.NaN;
data [fslice + 1][nPix] = Double.NaN;
} else {
data [fslice + 0][nPix] = vegetation_warp[fscene][nPix][0];
data [fslice + 1][nPix] = vegetation_warp[fscene][nPix][1];
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
//TERRVEG_EXT
ImagePlus imp = ShowDoubleFloatArrays.makeArrays(
data,
full.width,
full.height,
title, // +"-objects_"+scene_num,
titles); // test_titles,
imp.setProperty("FULL_X", ""+full.x);
imp.setProperty("FULL_Y", ""+full.y);
imp.setProperty("FULL_WIDTH", ""+full.width);
imp.setProperty("FULL_HEIGHT", ""+full.height);
imp.setProperty("DIFF_MODE", ""+diff_mode);
imp.setProperty("MODEL_DIRECTORY", ""+model_directory);
imp.setProperty("MODEL_TOP_DIRECTORY", ""+model_top_directory);
String path = VegetationLMA.getSavePath(
dir, // String dir,
title, // String title)
TERRVEG_EXT); // String ext) {
JP46_Reader_camera.encodeProperiesToInfo(imp);
FileSaver fs=new FileSaver(imp);
fs.saveAsTiff(path);
System.out.println("VegetationModel.saveState(): saved "+path); // dir+title+PAR_EXT);
}
public VegetationModel(
String dir,
String title) {
String path = VegetationLMA.getSavePath(
dir, // String dir,
title, // String title)
TERRVEG_EXT); // String ext) {
ImagePlus imp_pars = new ImagePlus (path);
if (imp_pars.getWidth()==0) {
throw new IllegalArgumentException("VegetationModel(): Could not read "+path);
}
int num_slices = imp_pars.getStack().getSize();
JP46_Reader_camera.decodeProperiesFromInfo(imp_pars);
full = new Rectangle (
Integer.parseInt((String) imp_pars.getProperty("FULL_X")),
Integer.parseInt((String) imp_pars.getProperty("FULL_Y")),
Integer.parseInt((String) imp_pars.getProperty("FULL_WIDTH")),
Integer.parseInt((String) imp_pars.getProperty("FULL_HEIGHT")));
final int num_scenes = (num_slices - 2) / 3;
final int full_length = full.width*full.height;
diff_mode = Boolean.parseBoolean((String) imp_pars.getProperty("DIFF_MODE"));
terrain_scenes_render = new double [num_scenes][full_length];
terrain_average_render= new double [full_length];
vegetation_average_render= new double [full_length];
vegetation_warp = new double [num_scenes][full_length][];
if (imp_pars.getProperty("MODEL_DIRECTORY") != null) model_directory = (String) imp_pars.getProperty("MODEL_DIRECTORY");
if (imp_pars.getProperty("MODEL_TOP_DIRECTORY") != null) model_top_directory = (String) imp_pars.getProperty("MODEL_TOP_DIRECTORY");
scene_names = new String[num_scenes];
for (int n = 0; n < num_scenes; n++) {
scene_names[n] = imp_pars.getStack().getSliceLabel(n+3);
}
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
TileNeibs tn = new TileNeibs(tilesX, vegetation.length/tilesX);
for (int nTile = ai.getAndIncrement(); nTile < vegetation.length; nTile = ai.getAndIncrement()) {
if (nTile==dbg_tile) {
System.out.println("getTerrainVegetation(): nTile="+nTile);
for (int n = ai.getAndIncrement(); n < (num_scenes + 2); n = ai.getAndIncrement()) {
double [] data = (n==0) ? terrain_average_render :((n==1)? vegetation_average_render : terrain_scenes_render[n-2]);
float [] pixels = (float[]) imp_pars.getStack().getPixels(n + 1);
for (int i = 0; i < full_length; i++) {
data[i] = pixels[i];
}
if ((ground[nTile] > terrain[nTile]) &&(disparity[nTile]-terrain[nTile] > min_above)) {
vegetation[nTile] = disparity[nTile];
} else {
int num_neibs = 0;
double sum_wd = 0.0, sum_w = 0.0;
for (int dir = 0; dir < TileNeibs.DIRS; dir++) {
int nTile1 = tn.getNeibIndex(nTile, dir);
if ((nTile1 >= 0) &&
(disparity[nTile1]-terrain[nTile1] > min_above) &&
(ground[nTile1] > terrain[nTile1]) &&
(strength[nTile1] > 0)) {
double d = disparity[nTile1];
double w = Math.pow(strength[nTile1], neibs_pow);
sum_wd += d*w;
sum_w += w;
num_neibs++;
}
}
if (num_neibs >= patch_neibs) {
vegetation[nTile] = sum_wd/sum_w;
}
}
};
}
ImageDtt.startAndJoin(threads);
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int n = ai.getAndIncrement(); n < num_scenes; n = ai.getAndIncrement()) {
double [][] data = vegetation_warp[n];
float [] pixels_x = (float[]) imp_pars.getStack().getPixels(2 + num_scenes + 2 * n + 1);
float [] pixels_y = (float[]) imp_pars.getStack().getPixels(2 + num_scenes + 2 * n + 2);
for (int i = 0; i < full_length; i++) {
if (!Float.isNaN(pixels_x[i]) && !Float.isNaN(pixels_y[i])) {
data[i] = new double [] {pixels_x[i],pixels_y[i]};
}
}
}
}
}
};
}
}
ImageDtt.startAndJoin(threads);
return new double [][] {terrain,vegetation};
return;
}
public static void test_vegetation(
/**
* Prepare terrain rendered, terrain average, vegetation average and vegetation offset. Created from test_vegetation
* @param clt_parameters
* @param quadCLTs
* @param ref_index
* @param debugLevel
* @return
*/
public VegetationModel (
CLTParameters clt_parameters,
QuadCLT [] quadCLTs,
int ref_index,
int debugLevel) {
int debugLevel) {
boolean show_debug = false;
TileProcessor tp = quadCLTs[ref_index].getTileProcessor();
int tilesX = tp.getTilesX();
int tilesY = tp.getTilesY();
......@@ -126,14 +239,16 @@ public class VegetationModel {
patch_neib, // final int patch_neib){
neibs_pow); // final double neibs_pow);
String [] titles_terr_veg = {"terrain","vegetation"};
ShowDoubleFloatArrays.showArrays(
terr_veg,
tilesX,
tilesY,
true,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation-min_ab"+min_above+".tiff",
titles_terr_veg);
if (show_debug) {
String [] titles_terr_veg = {"terrain","vegetation"};
ShowDoubleFloatArrays.showArrays(
terr_veg,
tilesX,
tilesY,
true,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation-min_ab"+min_above+".tiff",
titles_terr_veg);
}
double [] reference_xyz = OpticalFlow.ZERO3;
double [] reference_atr = OpticalFlow.ZERO3;
double [][][] terrain_pXpYD = getPxPyDs(
......@@ -155,6 +270,10 @@ public class VegetationModel {
double [][][] terrain_diff = diffPxPyDs(
terrain_pXpYD, // final double [][][] pXpYD,
ref_index); // final int ref_index)
if (terrain_diff == null) {
failed = true;
return;
}
double [][][] vegetation_diff = diffPxPyDs(
vegetation_pXpYD, // final double [][][] pXpYD,
ref_index); // final int ref_index)
......@@ -163,7 +282,6 @@ public class VegetationModel {
int num_scenes = quadCLTs.length;
int num_tiles = terrain_pXpYD[0].length;
int num_pixels = num_tiles*tileSize*tileSize;
boolean show_debug = true;
if (show_debug) {
String [] titles_frame = {"terr-pX","veg-pX","terr-pY","veg-pY","terr-D","veg-D"};
String [] titles_scene = new String [num_scenes];
......@@ -196,7 +314,7 @@ public class VegetationModel {
ShowDoubleFloatArrays.showArraysHyperstack(
data_dbg, // double[][][] pixels,
tilesX, // int width,
"terrain_vegetation_pXpYD", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation_pXpYD", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
......@@ -231,7 +349,7 @@ public class VegetationModel {
ShowDoubleFloatArrays.showArraysHyperstack(
diff_dbg, // double[][][] pixels,
tilesX, // int width,
"terrain_vegetation_pXpYD_differetial", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation_pXpYD_differetial", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
......@@ -297,7 +415,7 @@ public class VegetationModel {
}
}
}
String title = "terrain_vegetation_pix"+ (use_bicubic?"-bicubic":"-bilinear")+".tiff";
String title = quadCLTs[ref_index].getImageName()+"-terrain_vegetation_pix"+ (use_bicubic?"-bicubic":"-bilinear")+".tiff";
ShowDoubleFloatArrays.showArraysHyperstack(
data_dbg, // double[][][] pixels,
tilesX*tileSize, // int width,
......@@ -307,28 +425,17 @@ public class VegetationModel {
true); // boolean show)
}
double [][][] terrain_inv = new double [num_scenes][][];
double [][][] vegetation_inv = new double [num_scenes][][];
Rectangle out_window = new Rectangle(0,0,640,512);
boolean out_diff = true;
full = new Rectangle(0,0,640,512);
diff_mode = true;
boolean out_diff = diff_mode;
Rectangle out_window =full;
int patch_min_neibs = 6;
int [] pnum_patched = new int[1];
for (int nscene = 0; nscene < num_scenes; nscene++) {
if (nscene == dbg_scene) {
System.out.println("test_vegetation(): nscene="+nscene);
}
terrain_inv[nscene] = invertMap(
terrain_pix[nscene], // final double [][] map_in,
tilesX*tileSize, // final int width,
out_window, // final Rectangle out_window,
true, // final boolean in_diff,
out_diff, // final boolean out_diff)
patch_min_neibs, // final int patch_min_neibs)
pnum_patched); // final int [] pnum_patched)
vegetation_inv[nscene] = invertMap(
vegetation_pix[nscene], // final double [][] map_in,
tilesX*tileSize, // final int width,
......@@ -340,7 +447,6 @@ public class VegetationModel {
}
/* */
double [][][] veg_to_terr = new double [num_scenes][][];
double [][][] terr_to_terr = new double [num_scenes][][];
Rectangle window1 = new Rectangle(0,0,640,512);
Rectangle window2 = out_window;
boolean map_diff1 = true;
......@@ -355,75 +461,19 @@ public class VegetationModel {
window2, // final Rectangle window2,
map_diff2, // final boolean map_diff2,
map_diff_out); // final boolean map_diff_out)
terr_to_terr[nscene] = combineMaps(
terrain_pix[nscene], // final double [][] map1,
window1, // final Rectangle window1,
map_diff1, // final boolean map_diff1,
terrain_inv[nscene], // final double [][] map2,
window2, // final Rectangle window2,
map_diff2, // final boolean map_diff2,
map_diff_out); // final boolean map_diff_out)
}
/* */
}
vegetation_warp = veg_to_terr;
full = out_window;
/* USED */
if (show_debug) {
String [] titles_frame = {"terr-pX","veg-pX","terr-pY","veg-pY"};
String [] titles_scene = new String [num_scenes];
double [][][] data_dbg = new double [titles_frame.length][num_scenes][num_pixels];
for (int i = 0; i < data_dbg.length;i++) {
for (int j = 0; j < data_dbg[0].length;j++) {
Arrays.fill(data_dbg[i][j], Double.NaN);
}
}
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles_scene[nscene] = nscene+":"+quadCLTs[nscene].getImageName();
if ((terrain_inv[nscene] == null) || (vegetation_inv[nscene]==null)){
System.out.println("test_vegetation(): null for nscene="+nscene);
} else {
for (int npix = 0; npix < num_pixels; npix++) {
if (terrain_inv[nscene][npix] != null) {
for (int k = 0; k < terrain_inv[nscene][npix].length; k++) {
data_dbg[2*k + 0][nscene][npix] = terrain_inv[nscene][npix][k];
}
}
if (vegetation_inv[nscene][npix] != null) {
for (int k = 0; k < vegetation_inv[nscene][npix].length; k++) {
data_dbg[2*k + 1][nscene][npix] = vegetation_inv[nscene][npix][k];
}
}
}
}
}
ShowDoubleFloatArrays.showArraysHyperstack(
data_dbg, // double[][][] pixels,
tilesX*tileSize, // int width,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation_inv", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
showOffsetsDiff(
terrain_inv, // final double [][][] terrain,
vegetation_inv, // final double [][][] vegetation,
tilesX*tileSize, // final int width,
quadCLTs, // QuadCLT [] quadCLTs, // just for names
quadCLTs[ref_index].getImageName()+"-terrain_vegetation_offset.tiff"); // String title) { // with .tiff
/* */
showOffsetsCombo(
veg_to_terr, // final double [][][] map_combo,
tilesX*tileSize, // final int width,
quadCLTs, // QuadCLT [] quadCLTs, // just for names
quadCLTs[ref_index].getImageName()+"-combo_offset.tiff"); // String title) { // with .tiff
showOffsetsCombo(
terr_to_terr, // final double [][][] map_combo,
tilesX*tileSize, // final int width,
quadCLTs, // QuadCLT [] quadCLTs, // just for names
quadCLTs[ref_index].getImageName()+"-combo_terr-terr.tiff"); // String title) { // with .tiff
/* */
showOffsetsCombo(
veg_to_terr, // final double [][][] map_combo,
tilesX*tileSize, // final int width,
quadCLTs, // QuadCLT [] quadCLTs, // just for names
quadCLTs[ref_index].getImageName()+"-combo_offset.tiff"); // String title) { // with .tiff
}
boolean mb_en = clt_parameters.imp.mb_en; // && (fov_tiles==null) && (mode3d > 0);
......@@ -441,6 +491,8 @@ public class VegetationModel {
ref_index, // int ref_index,
terrain_pXpYD, // double [][][] pXpYD,
debugLevel); // int debugLevel){
double [][][] vegetation_render = renderDouble(
clt_parameters, // CLTParameters clt_parameters,
mb_en, // boolean mb_en,
......@@ -453,126 +505,69 @@ public class VegetationModel {
ref_index, // int ref_index,
vegetation_pXpYD, // double [][][] pXpYD,
debugLevel); // int debugLevel){
double [][] terrain_mono = new double [num_scenes][];
double [][] vegetation_mono = new double [num_scenes][];
double [][][] terrain_vegetation_all = new double [2][num_scenes+1][];
terrain_scenes_render = new double [num_scenes][];
double [][] vegetation_scenes_render = new double [num_scenes][];
for (int i = 0; i < num_scenes; i++) {
terrain_mono[i] = terrain_render[i][0];
vegetation_mono[i] = vegetation_render[i][0];
}
System.arraycopy(terrain_mono, 0, terrain_vegetation_all[0], 0, num_scenes);
System.arraycopy(vegetation_mono, 0, terrain_vegetation_all[1], 0, num_scenes);
terrain_vegetation_all[0][num_scenes] = averageMono(terrain_mono);
terrain_vegetation_all[1][num_scenes] = averageMono(vegetation_mono);
if (show_debug) {
String [] titles_frame = {"terrain","vegetation"};
String [] titles_scene = new String [num_scenes+1];
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles_scene[nscene] = nscene+":"+quadCLTs[nscene].getImageName();
}
titles_scene[num_scenes] = "average";
ShowDoubleFloatArrays.showArraysHyperstack(
terrain_vegetation_all, // double[][][] pixels,
tilesX * tileSize, // int width,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation_render.tiff", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
terrain_scenes_render[i] = terrain_render[i][0];
vegetation_scenes_render[i] = vegetation_render[i][0];
}
/* */
double [][] vegetation_mapped = new double [num_scenes][];
double scale_map = 1.0; // 0.5;
for (int nscene = 0; nscene < num_scenes; nscene++) {
vegetation_mapped[nscene] = applyMap(
// vegetation_render[nscene][0], // final double [] img,
terrain_vegetation_all[1][num_scenes], // final double [] img, // average vegetation
tilesX * tileSize, // final int img_width,
veg_to_terr[nscene], // final double [][] map,
window1, // final Rectangle window,
map_diff_out, // final boolean map_diff)
scale_map); // final double scale) { // debug feature, only works with differential map
terrain_average_render = averageMono(terrain_scenes_render);
vegetation_average_render = averageMono(vegetation_scenes_render);
model_directory = quadCLTs[ref_index].getX3dDirectory(); // getX3dTopDirectory();
model_top_directory = quadCLTs[ref_index].getX3dTopDirectory();
}
return;
}
if (show_debug) {
double [][] diff_veg = new double [num_scenes][num_pixels];
double [][] diff_terr = new double [num_scenes][num_pixels];
for (int nscene = 0; nscene < num_scenes; nscene++) {
Arrays.fill(diff_veg[nscene],Double.NaN);
Arrays.fill(diff_terr[nscene],Double.NaN);
for (int nPix = 0; nPix < num_pixels; nPix++) {
diff_veg[nscene][nPix] = terrain_mono[nscene][nPix] - vegetation_mapped[nscene][nPix];
if (!Double.isNaN(diff_veg[nscene][nPix])) {
diff_terr[nscene][nPix] = terrain_mono[nscene][nPix] - terrain_vegetation_all[1][num_scenes][nPix];
}
}
}
String [] titles_frame = {"terrain","diff_veg", "diff_terr","mapped_vegetation", "vegetation"};
String [] titles_scene = new String [num_scenes];
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles_scene[nscene] = nscene+":"+quadCLTs[nscene].getImageName();
}
double [][][] render3 = {terrain_mono, diff_veg, diff_terr, vegetation_mapped, vegetation_mono};
ShowDoubleFloatArrays.showArraysHyperstack(
render3, // double[][][] pixels,
tilesX * tileSize, // int width,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation_mapped-scale"+scale_map+".tiff", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
ShowDoubleFloatArrays.showArrays(
vegetation_mapped,
tilesX * tileSize,
tilesY * tileSize,
true,
quadCLTs[ref_index].getImageName()+"-vegetation_mapped.tiff",
titles_terr_veg);
ShowDoubleFloatArrays.showArrays(
diff_veg,
tilesX * tileSize,
tilesY * tileSize,
true,
quadCLTs[ref_index].getImageName()+"-diff-veg.tiff",
titles_terr_veg);
ShowDoubleFloatArrays.showArrays(
diff_terr,
tilesX * tileSize,
tilesY * tileSize,
true,
quadCLTs[ref_index].getImageName()+"-diff-terr.tiff",
titles_terr_veg);
}
/* */
return;
}
public static void testVegetationLMA(boolean combine_segments) {
final int dx_slice = 1;
final int dy_slice = 2;
ImagePlus imp_warp = new ImagePlus(WARP_PATH);
final ImageStack warp_stack = imp_warp.getImageStack();
final int warp_width = imp_warp.getWidth();
final int warp_height = imp_warp.getHeight();
final int warp_pixels = warp_width*warp_height;
final int num_scenes = warp_stack.getSize()/WARP_HYPER; // 3 slices
final double [][][] veg_to_terr = new double [num_scenes][warp_pixels][];
public static double [][] getTerrainVegetation(
final double [][] combo_dsn,
final int tilesX,
final double min_above, // absolute disparity difference
final int patch_neibs,
final double neibs_pow){ // raise strength to this power when averaging neighbors
final double [] terrain = combo_dsn[OpticalFlow.COMBO_DSN_INDX_TERRAIN];
final double [] ground = combo_dsn[OpticalFlow.COMBO_DSN_INDX_GROUND];
final double [] disparity = combo_dsn[OpticalFlow.COMBO_DSN_INDX_LMA];
final double [] strength = combo_dsn[OpticalFlow.COMBO_DSN_INDX_STRENGTH];
final int num_pixels = disparity.length;
final double [] vegetation = new double [num_pixels];
Arrays.fill(vegetation, Double.NaN);
final int dbg_tile = -(22+17*80);
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
int debugLevel = -1;
// read warps
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()) {
float [] dx_pixels = (float []) warp_stack.getPixels(dx_slice*num_scenes + nScene+1);
float [] dy_pixels = (float []) warp_stack.getPixels(dy_slice*num_scenes + nScene+1);
for (int nPix = 0; nPix < warp_pixels; nPix++) {
if (!Float.isNaN(dx_pixels[nPix]) && !Float.isNaN(dy_pixels[nPix])) {
veg_to_terr[nScene][nPix] = new double [] {dx_pixels[nPix],dy_pixels[nPix]};
TileNeibs tn = new TileNeibs(tilesX, vegetation.length/tilesX);
for (int nTile = ai.getAndIncrement(); nTile < vegetation.length; nTile = ai.getAndIncrement()) {
if (nTile==dbg_tile) {
System.out.println("getTerrainVegetation(): nTile="+nTile);
}
if ((ground[nTile] > terrain[nTile]) &&(disparity[nTile]-terrain[nTile] > min_above)) {
vegetation[nTile] = disparity[nTile];
} else {
int num_neibs = 0;
double sum_wd = 0.0, sum_w = 0.0;
for (int dir = 0; dir < TileNeibs.DIRS; dir++) {
int nTile1 = tn.getNeibIndex(nTile, dir);
if ((nTile1 >= 0) &&
(disparity[nTile1]-terrain[nTile1] > min_above) &&
(ground[nTile1] > terrain[nTile1]) &&
(strength[nTile1] > 0)) {
double d = disparity[nTile1];
double w = Math.pow(strength[nTile1], neibs_pow);
sum_wd += d*w;
sum_w += w;
num_neibs++;
}
}
if (num_neibs >= patch_neibs) {
vegetation[nTile] = sum_wd/sum_w;
}
}
}
......@@ -580,133 +575,989 @@ public class VegetationModel {
};
}
ImageDtt.startAndJoin(threads);
// read rendered images
ImagePlus imp_rendered = new ImagePlus(RENDERED_PATH);
final ImageStack rendered_stack = imp_rendered.getImageStack();
final int rendered_width = imp_rendered.getWidth();
final int rendered_height = imp_rendered.getHeight();
final int rendered_pixels = rendered_width*rendered_height;
if ((warp_width != rendered_width) || (warp_height != rendered_height)) {
throw new IllegalArgumentException("Rendered image dimensions ("+rendered_width+"x"+rendered_height+
") do not match warp data ("+warp_width+"x"+warp_height+").");
}
final int rendered_images = rendered_stack.getSize()/RENDERED_HYPER; // 2 slices
if (rendered_images != (num_scenes +1)) {
throw new IllegalArgumentException("Rendered image scenes ("+rendered_images+
") should be one more than number of warp slices ("+num_scenes+") as last rendered slice corresponds to averaged data.");
}
final double [] terrain_average = new double[rendered_pixels]; // full image average terrain (no nulls)
final double [] vegetation_average = new double[rendered_pixels]; // full image average vegetation (with nulls)
final double [][] terrain_rendered = new double[num_scenes][rendered_pixels]; // full image average vegetation (with nulls)
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 + 2; nScene = ai.getAndIncrement()) {
int indx = (nScene <= num_scenes) ? nScene : (nScene + num_scenes);
float [] fpixels = (float []) rendered_stack.getPixels(indx + 1);
if (nScene < num_scenes) {
for (int nPix = 0; nPix < rendered_pixels; nPix++) terrain_rendered[nScene][nPix] = fpixels[nPix];
} else if (nScene == num_scenes) {
for (int nPix = 0; nPix < rendered_pixels; nPix++) terrain_average[nPix] = fpixels[nPix];
} else {
for (int nPix = 0; nPix < rendered_pixels; nPix++) vegetation_average[nPix] = fpixels[nPix];
}
}
}
};
}
ImageDtt.startAndJoin(threads);
String [] titles = new String[num_scenes];
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles[nscene] = warp_stack.getSliceLabel(nscene+1).substring(5);
}
testVegetationLMA(
combine_segments, // boolean combine_segments,
warp_width, // int width,
terrain_average, // double [] terrain_average, // full image average terrain (no nulls)
// boolean diff_mode,
return new double [][] {terrain,vegetation};
}
public static void test_vegetation(
CLTParameters clt_parameters,
QuadCLT [] quadCLTs,
int ref_index,
int debugLevel) {
//Testing
VegetationModel vegetationModel = new VegetationModel (
clt_parameters, // CLTParameters clt_parameters,
quadCLTs, // QuadCLT [] quadCLTs,
ref_index, // int ref_index,
debugLevel); // int debugLevel)
if (vegetationModel.isFailed()) {
System.out.println("Creation of VegetationModel failed!");
return;
}
String dir_state = quadCLTs[ref_index].getX3dDirectory(); // getX3dTopDirectory();
String title_state = quadCLTs[ref_index].getImageName()+"-TERR-VEG-STATE";
vegetationModel.saveState(
dir_state, // String dir,
title_state); // String title)
if (debugLevel < 1000) {
return;
}
TileProcessor tp = quadCLTs[ref_index].getTileProcessor();
int tilesX = tp.getTilesX();
int tilesY = tp.getTilesY();
int tileSize = tp.getTileSize();
double min_above = 0.02; // 0.025; // .04;
int patch_neib = 4; // 5;
double neibs_pow = 0.5;
double [][] combo_dsn =quadCLTs[ref_index].restoreComboDSI(true);
double [][] terr_veg = getTerrainVegetation(
combo_dsn, // double [][] combo_dsn);
tilesX, // final int tilesX,
min_above, // final double min_above, // absolute disparity difference
patch_neib, // final int patch_neib){
neibs_pow); // final double neibs_pow);
String [] titles_terr_veg = {"terrain","vegetation"};
ShowDoubleFloatArrays.showArrays(
terr_veg,
tilesX,
tilesY,
true,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation-min_ab"+min_above+".tiff",
titles_terr_veg);
double [] reference_xyz = OpticalFlow.ZERO3;
double [] reference_atr = OpticalFlow.ZERO3;
double [][][] terrain_pXpYD = getPxPyDs(
reference_xyz, // double [] reference_xyz, // offset reference camera {x,y,z}
reference_atr, // double [] reference_atr,
terr_veg[0], // double [] ref_disparity,
quadCLTs, // QuadCLT [] quadCLTs,
null, // boolean [] scene_selection, // null or same length as quadCLTs
ref_index, // int ref_index,
debugLevel); // int debugLevel)
double [][][] vegetation_pXpYD = getPxPyDs(
reference_xyz, // double [] reference_xyz, // offset reference camera {x,y,z}
reference_atr, // double [] reference_atr,
terr_veg[1], // double [] ref_disparity,
quadCLTs, // QuadCLT [] quadCLTs,
null, // boolean [] scene_selection, // null or same length as quadCLTs
ref_index, // int ref_index,
debugLevel); // int debugLevel)
double [][][] terrain_diff = diffPxPyDs(
terrain_pXpYD, // final double [][][] pXpYD,
ref_index); // final int ref_index)
double [][][] vegetation_diff = diffPxPyDs(
vegetation_pXpYD, // final double [][][] pXpYD,
ref_index); // final int ref_index)
int num_scenes = quadCLTs.length;
int num_tiles = terrain_pXpYD[0].length;
int num_pixels = num_tiles*tileSize*tileSize;
boolean show_debug = true;
if (show_debug) {
String [] titles_frame = {"terr-pX","veg-pX","terr-pY","veg-pY","terr-D","veg-D"};
String [] titles_scene = new String [num_scenes];
double [][][] data_dbg = new double [titles_frame.length][num_scenes][num_tiles];
for (int i = 0; i < data_dbg.length;i++) {
for (int j = 0; j < data_dbg[0].length;j++) {
Arrays.fill(data_dbg[i][j], Double.NaN);
}
}
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles_scene[nscene] = nscene+":"+quadCLTs[nscene].getImageName();
if ((terrain_pXpYD[nscene] == null) || (vegetation_pXpYD[nscene]==null)){
System.out.println("test_vegetation(): null for nscene="+nscene);
} else {
for (int ntile = 0; ntile < num_tiles; ntile++) {
if (terrain_pXpYD[nscene][ntile] != null) {
for (int k = 0; k < terrain_pXpYD[nscene][ntile].length; k++) {
data_dbg[2*k + 0][nscene][ntile] = terrain_pXpYD[nscene][ntile][k];
}
}
if (vegetation_pXpYD[nscene][ntile] != null) {
for (int k = 0; k < vegetation_pXpYD[nscene][ntile].length; k++) {
data_dbg[2*k + 1][nscene][ntile] = vegetation_pXpYD[nscene][ntile][k];
}
}
}
}
}
ShowDoubleFloatArrays.showArraysHyperstack(
data_dbg, // double[][][] pixels,
tilesX, // int width,
"terrain_vegetation_pXpYD", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
// same for differences
double [][][] diff_dbg = new double [6][num_scenes][num_tiles];
for (int i = 0; i < diff_dbg.length;i++) {
for (int j = 0; j < diff_dbg[0].length;j++) {
Arrays.fill(diff_dbg[i][j], Double.NaN);
}
}
for (int nscene = 0; nscene < num_scenes; nscene++) {
// titles_scene[nscene] = nscene+":"+quadCLTs[nscene].getImageName();
if ((terrain_diff[nscene] == null) || (vegetation_diff[nscene]==null)){
System.out.println("test_vegetation(): null for nscene="+nscene);
} else {
for (int ntile = 0; ntile < num_tiles; ntile++) {
if (terrain_diff[nscene][ntile] != null) {
for (int k = 0; k < terrain_diff[nscene][ntile].length; k++) {
diff_dbg[2*k + 0][nscene][ntile] = terrain_diff[nscene][ntile][k];
}
}
if (vegetation_diff[nscene][ntile] != null) {
for (int k = 0; k < vegetation_diff[nscene][ntile].length; k++) {
diff_dbg[2*k + 1][nscene][ntile] = vegetation_diff[nscene][ntile][k];
}
}
}
}
}
ShowDoubleFloatArrays.showArraysHyperstack(
diff_dbg, // double[][][] pixels,
tilesX, // int width,
"terrain_vegetation_pXpYD_differetial", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
}
int dbg_scene = -64;
boolean use_bicubic = true;
double [][][] terrain_pix = new double [num_scenes][][];
double [][][] vegetation_pix = new double [num_scenes][][];
for (int nscene = 0; nscene < num_scenes; nscene++) {
if (nscene == dbg_scene) {
System.out.println("test_vegetation(): nscene="+nscene);
}
if (use_bicubic) {
terrain_pix[nscene] = interpolatePxPyDBicubic(
terrain_diff[nscene], // final double [][] pXpYD_tile,
tilesX, // final int tilesX,
tileSize); // final int tile_size)
vegetation_pix[nscene] = interpolatePxPyDBicubic(
vegetation_diff[nscene], // final double [][] pXpYD_tile,
tilesX, // final int tilesX,
tileSize); // final int tile_size)
} else {
terrain_pix[nscene] = interpolatePxPyDBilinear(
terrain_diff[nscene], // final double [][] pXpYD_tile,
tilesX, // final int tilesX,
tileSize); // final int tile_size)
vegetation_pix[nscene] = interpolatePxPyDBilinear(
vegetation_diff[nscene], // final double [][] pXpYD_tile,
tilesX, // final int tilesX,
tileSize); // final int tile_size)
}
}
if (show_debug) {
String [] titles_frame = {"terr-pX","veg-pX","terr-pY","veg-pY","terr-D","veg-D"};
String [] titles_scene = new String [num_scenes];
double [][][] data_dbg = new double [titles_frame.length][num_scenes][num_pixels];
for (int i = 0; i < data_dbg.length;i++) {
for (int j = 0; j < data_dbg[0].length;j++) {
Arrays.fill(data_dbg[i][j], Double.NaN);
}
}
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles_scene[nscene] = nscene+":"+quadCLTs[nscene].getImageName();
if ((terrain_pix[nscene] == null) || (vegetation_pix[nscene]==null)){
System.out.println("test_vegetation(): null for nscene="+nscene);
} else {
for (int npix = 0; npix < num_pixels; npix++) {
if (terrain_pix[nscene][npix] != null) {
for (int k = 0; k < terrain_pix[nscene][npix].length; k++) {
data_dbg[2*k + 0][nscene][npix] = terrain_pix[nscene][npix][k];
}
}
if (vegetation_pix[nscene][npix] != null) {
for (int k = 0; k < vegetation_pix[nscene][npix].length; k++) {
data_dbg[2*k + 1][nscene][npix] = vegetation_pix[nscene][npix][k];
}
}
}
}
}
String title = "terrain_vegetation_pix"+ (use_bicubic?"-bicubic":"-bilinear")+".tiff";
ShowDoubleFloatArrays.showArraysHyperstack(
data_dbg, // double[][][] pixels,
tilesX*tileSize, // int width,
title, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
}
double [][][] terrain_inv = new double [num_scenes][][];
double [][][] vegetation_inv = new double [num_scenes][][];
Rectangle out_window = new Rectangle(0,0,640,512);
boolean out_diff = true;
int patch_min_neibs = 6;
int [] pnum_patched = new int[1];
for (int nscene = 0; nscene < num_scenes; nscene++) {
if (nscene == dbg_scene) {
System.out.println("test_vegetation(): nscene="+nscene);
}
terrain_inv[nscene] = invertMap(
terrain_pix[nscene], // final double [][] map_in,
tilesX*tileSize, // final int width,
out_window, // final Rectangle out_window,
true, // final boolean in_diff,
out_diff, // final boolean out_diff)
patch_min_neibs, // final int patch_min_neibs)
pnum_patched); // final int [] pnum_patched)
vegetation_inv[nscene] = invertMap(
vegetation_pix[nscene], // final double [][] map_in,
tilesX*tileSize, // final int width,
out_window, // final Rectangle out_window,
true, // final boolean in_diff,
out_diff, // final boolean out_diff)
patch_min_neibs, // final int patch_min_neibs)
pnum_patched); // final int [] pnum_patched)
}
/* */
double [][][] veg_to_terr = new double [num_scenes][][];
double [][][] terr_to_terr = new double [num_scenes][][];
Rectangle window1 = new Rectangle(0,0,640,512);
Rectangle window2 = out_window;
boolean map_diff1 = true;
boolean map_diff2 = out_diff; // true;
boolean map_diff_out = true;
for (int nscene = 0; nscene < num_scenes; nscene++) {
veg_to_terr[nscene] = combineMaps(
terrain_pix[nscene], // final double [][] map1,
window1, // final Rectangle window1,
map_diff1, // final boolean map_diff1,
vegetation_inv[nscene], // final double [][] map2,
window2, // final Rectangle window2,
map_diff2, // final boolean map_diff2,
map_diff_out); // final boolean map_diff_out)
terr_to_terr[nscene] = combineMaps(
terrain_pix[nscene], // final double [][] map1,
window1, // final Rectangle window1,
map_diff1, // final boolean map_diff1,
terrain_inv[nscene], // final double [][] map2,
window2, // final Rectangle window2,
map_diff2, // final boolean map_diff2,
map_diff_out); // final boolean map_diff_out)
}
/* */
if (show_debug) {
String [] titles_frame = {"terr-pX","veg-pX","terr-pY","veg-pY"};
String [] titles_scene = new String [num_scenes];
double [][][] data_dbg = new double [titles_frame.length][num_scenes][num_pixels];
for (int i = 0; i < data_dbg.length;i++) {
for (int j = 0; j < data_dbg[0].length;j++) {
Arrays.fill(data_dbg[i][j], Double.NaN);
}
}
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles_scene[nscene] = nscene+":"+quadCLTs[nscene].getImageName();
if ((terrain_inv[nscene] == null) || (vegetation_inv[nscene]==null)){
System.out.println("test_vegetation(): null for nscene="+nscene);
} else {
for (int npix = 0; npix < num_pixels; npix++) {
if (terrain_inv[nscene][npix] != null) {
for (int k = 0; k < terrain_inv[nscene][npix].length; k++) {
data_dbg[2*k + 0][nscene][npix] = terrain_inv[nscene][npix][k];
}
}
if (vegetation_inv[nscene][npix] != null) {
for (int k = 0; k < vegetation_inv[nscene][npix].length; k++) {
data_dbg[2*k + 1][nscene][npix] = vegetation_inv[nscene][npix][k];
}
}
}
}
}
ShowDoubleFloatArrays.showArraysHyperstack(
data_dbg, // double[][][] pixels,
tilesX*tileSize, // int width,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation_inv", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
showOffsetsDiff(
terrain_inv, // final double [][][] terrain,
vegetation_inv, // final double [][][] vegetation,
tilesX*tileSize, // final int width,
quadCLTs, // QuadCLT [] quadCLTs, // just for names
quadCLTs[ref_index].getImageName()+"-terrain_vegetation_offset.tiff"); // String title) { // with .tiff
/* USED */
showOffsetsCombo(
veg_to_terr, // final double [][][] map_combo,
tilesX*tileSize, // final int width,
quadCLTs, // QuadCLT [] quadCLTs, // just for names
quadCLTs[ref_index].getImageName()+"-combo_offset.tiff"); // String title) { // with .tiff
showOffsetsCombo(
terr_to_terr, // final double [][][] map_combo,
tilesX*tileSize, // final int width,
quadCLTs, // QuadCLT [] quadCLTs, // just for names
quadCLTs[ref_index].getImageName()+"-combo_terr-terr.tiff"); // String title) { // with .tiff
/* */
}
boolean mb_en = clt_parameters.imp.mb_en; // && (fov_tiles==null) && (mode3d > 0);
double mb_max_gain = clt_parameters.imp.mb_max_gain; // 5.0; // motion blur maximal gain (if more - move second point more than a pixel
double [][][] terrain_render = renderDouble(
clt_parameters, // CLTParameters clt_parameters,
mb_en, // boolean mb_en,
mb_max_gain, // double mb_max_gain,
reference_xyz, // double [] reference_xyz, // offset reference camera {x,y,z}
reference_atr, // double [] reference_atr,
terr_veg[0], // double [] ref_disparity,
quadCLTs, // QuadCLT [] quadCLTs,
null, // boolean [] scene_selection, // null or same length as quadCLTs
ref_index, // int ref_index,
terrain_pXpYD, // double [][][] pXpYD,
debugLevel); // int debugLevel){
double [][][] vegetation_render = renderDouble(
clt_parameters, // CLTParameters clt_parameters,
mb_en, // boolean mb_en,
mb_max_gain, // double mb_max_gain,
reference_xyz, // double [] reference_xyz, // offset reference camera {x,y,z}
reference_atr, // double [] reference_atr,
terr_veg[1], // double [] ref_disparity,
quadCLTs, // QuadCLT [] quadCLTs,
null, // boolean [] scene_selection, // null or same length as quadCLTs
ref_index, // int ref_index,
vegetation_pXpYD, // double [][][] pXpYD,
debugLevel); // int debugLevel){
double [][] terrain_mono = new double [num_scenes][];
double [][] vegetation_mono = new double [num_scenes][];
double [][][] terrain_vegetation_all = new double [2][num_scenes+1][];
for (int i = 0; i < num_scenes; i++) {
terrain_mono[i] = terrain_render[i][0];
vegetation_mono[i] = vegetation_render[i][0];
}
System.arraycopy(terrain_mono, 0, terrain_vegetation_all[0], 0, num_scenes);
System.arraycopy(vegetation_mono, 0, terrain_vegetation_all[1], 0, num_scenes);
terrain_vegetation_all[0][num_scenes] = averageMono(terrain_mono);
terrain_vegetation_all[1][num_scenes] = averageMono(vegetation_mono);
/* Used */
if (show_debug) {
String [] titles_frame = {"terrain","vegetation"};
String [] titles_scene = new String [num_scenes+1];
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles_scene[nscene] = nscene+":"+quadCLTs[nscene].getImageName();
}
titles_scene[num_scenes] = "average";
ShowDoubleFloatArrays.showArraysHyperstack(
terrain_vegetation_all, // double[][][] pixels,
tilesX * tileSize, // int width,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation_render.tiff", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
}
/* */
double [][] vegetation_mapped = new double [num_scenes][];
double scale_map = 1.0; // 0.5;
for (int nscene = 0; nscene < num_scenes; nscene++) {
vegetation_mapped[nscene] = applyMap(
// vegetation_render[nscene][0], // final double [] img,
terrain_vegetation_all[1][num_scenes], // final double [] img, // average vegetation
tilesX * tileSize, // final int img_width,
veg_to_terr[nscene], // final double [][] map,
window1, // final Rectangle window,
map_diff_out, // final boolean map_diff)
scale_map); // final double scale) { // debug feature, only works with differential map
}
if (show_debug) {
double [][] diff_veg = new double [num_scenes][num_pixels];
double [][] diff_terr = new double [num_scenes][num_pixels];
for (int nscene = 0; nscene < num_scenes; nscene++) {
Arrays.fill(diff_veg[nscene],Double.NaN);
Arrays.fill(diff_terr[nscene],Double.NaN);
for (int nPix = 0; nPix < num_pixels; nPix++) {
diff_veg[nscene][nPix] = terrain_mono[nscene][nPix] - vegetation_mapped[nscene][nPix];
if (!Double.isNaN(diff_veg[nscene][nPix])) {
diff_terr[nscene][nPix] = terrain_mono[nscene][nPix] - terrain_vegetation_all[1][num_scenes][nPix];
}
}
}
String [] titles_frame = {"terrain","diff_veg", "diff_terr","mapped_vegetation", "vegetation"};
String [] titles_scene = new String [num_scenes];
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles_scene[nscene] = nscene+":"+quadCLTs[nscene].getImageName();
}
double [][][] render3 = {terrain_mono, diff_veg, diff_terr, vegetation_mapped, vegetation_mono};
ShowDoubleFloatArrays.showArraysHyperstack(
render3, // double[][][] pixels,
tilesX * tileSize, // int width,
quadCLTs[ref_index].getImageName()+"-terrain_vegetation_mapped-scale"+scale_map+".tiff", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scene, // String [] titles, // all slices*frames titles or just slice titles or null
titles_frame, // String [] frame_titles, // frame titles or null
true); // boolean show)
ShowDoubleFloatArrays.showArrays(
vegetation_mapped,
tilesX * tileSize,
tilesY * tileSize,
true,
quadCLTs[ref_index].getImageName()+"-vegetation_mapped.tiff",
titles_terr_veg);
ShowDoubleFloatArrays.showArrays(
diff_veg,
tilesX * tileSize,
tilesY * tileSize,
true,
quadCLTs[ref_index].getImageName()+"-diff-veg.tiff",
titles_terr_veg);
ShowDoubleFloatArrays.showArrays(
diff_terr,
tilesX * tileSize,
tilesY * tileSize,
true,
quadCLTs[ref_index].getImageName()+"-diff-terr.tiff",
titles_terr_veg);
}
/* */
return;
}
public static void testVegetationLMA(
CLTParameters clt_parameters,
boolean combine_segments)
{
// Temporary , it is actually a model directory // 1697877487_245877-TERR-VEG-STATE.terrveg-tiff
String model_directory = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/linked/linked_1697875868-1697879449-b/1697877487_245877/v35";
String model_state_file = "1697877487_245877-TERR-VEG-STATE";
if (model_state_file != null) {
VegetationModel vegetationModel = new VegetationModel(
model_directory, // String dir,
model_state_file); // String title)
vegetationModel.testVegetationLMA(
combine_segments, // boolean combine_segments,
clt_parameters, // CLTParameters clt_parameters,
-1); // int debugLevel) {
return;
}
final int dx_slice = 1;
final int dy_slice = 2;
ImagePlus imp_warp = new ImagePlus(WARP_PATH);
final ImageStack warp_stack = imp_warp.getImageStack();
final int warp_width = imp_warp.getWidth();
final int warp_height = imp_warp.getHeight();
final int warp_pixels = warp_width*warp_height;
final int num_scenes = warp_stack.getSize()/WARP_HYPER; // 3 slices
final double [][][] veg_to_terr = new double [num_scenes][warp_pixels][];
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
int debugLevel = -1;
// read warps
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()) {
float [] dx_pixels = (float []) warp_stack.getPixels(dx_slice*num_scenes + nScene+1);
float [] dy_pixels = (float []) warp_stack.getPixels(dy_slice*num_scenes + nScene+1);
for (int nPix = 0; nPix < warp_pixels; nPix++) {
if (!Float.isNaN(dx_pixels[nPix]) && !Float.isNaN(dy_pixels[nPix])) {
veg_to_terr[nScene][nPix] = new double [] {dx_pixels[nPix],dy_pixels[nPix]};
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
// read rendered images
ImagePlus imp_rendered = new ImagePlus(RENDERED_PATH);
final ImageStack rendered_stack = imp_rendered.getImageStack();
final int rendered_width = imp_rendered.getWidth();
final int rendered_height = imp_rendered.getHeight();
final int rendered_pixels = rendered_width*rendered_height;
if ((warp_width != rendered_width) || (warp_height != rendered_height)) {
throw new IllegalArgumentException("Rendered image dimensions ("+rendered_width+"x"+rendered_height+
") do not match warp data ("+warp_width+"x"+warp_height+").");
}
final int rendered_images = rendered_stack.getSize()/RENDERED_HYPER; // 2 slices
if (rendered_images != (num_scenes +1)) {
throw new IllegalArgumentException("Rendered image scenes ("+rendered_images+
") should be one more than number of warp slices ("+num_scenes+") as last rendered slice corresponds to averaged data.");
}
final double [] terrain_average = new double[rendered_pixels]; // full image average terrain (no nulls)
final double [] vegetation_average = new double[rendered_pixels]; // full image average vegetation (with nulls)
final double [][] terrain_rendered = new double[num_scenes][rendered_pixels]; // full image average vegetation (with nulls)
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 + 2; nScene = ai.getAndIncrement()) {
int indx = (nScene <= num_scenes) ? nScene : (nScene + num_scenes);
float [] fpixels = (float []) rendered_stack.getPixels(indx + 1);
if (nScene < num_scenes) {
for (int nPix = 0; nPix < rendered_pixels; nPix++) terrain_rendered[nScene][nPix] = fpixels[nPix];
} else if (nScene == num_scenes) {
for (int nPix = 0; nPix < rendered_pixels; nPix++) terrain_average[nPix] = fpixels[nPix];
} else {
for (int nPix = 0; nPix < rendered_pixels; nPix++) vegetation_average[nPix] = fpixels[nPix];
}
}
}
};
}
ImageDtt.startAndJoin(threads);
String [] titles = new String[num_scenes];
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles[nscene] = warp_stack.getSliceLabel(nscene+1).substring(5);
}
testVegetationLMA(
combine_segments, // boolean combine_segments,
clt_parameters, // CLTParameters clt_parameters,
warp_width, // int width,
terrain_average, // double [] terrain_average, // full image average terrain (no nulls)
// boolean diff_mode,
vegetation_average, // double [] vegetation_average, // full image average vegetation (with nulls)
terrain_rendered, // double [][] terrain_rendered, // terrain rendered for scenes (has nulls)
veg_to_terr, // double [][][] vegetation_offsets, // [num_scenes][pixel]{dx,dy} differential offsets of vegetation to terrain grid
titles, // String [] titles,
debugLevel); // int debugLevel)
}
public static void unsharpMaskMulti(
final double [][] data,
final int width,
final double um_sigma,
final double um_weight) {
final int height = data[0].length / width;
final int num_images = data.length;
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [] data_orig = new double [width * height];
for (int nimg = ai.getAndIncrement(); nimg < num_images; nimg = ai.getAndIncrement()) {
double [] data_slice = data[nimg];
System.arraycopy(data_slice, 0, data_orig,0,data_orig.length);
(new DoubleGaussianBlur()).blurDouble(
data_slice, //
width,
height,
um_sigma, // double sigmaX,
um_sigma, // double sigmaY,
0.01); // double accuracy)
for (int i = 0; i < data_orig.length; i++) {
data_slice[i] = data_orig[i] - um_weight * data_slice[i];
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
public static Rectangle nextTileWoi(
Rectangle enclosing,
Rectangle step,
Rectangle single,
Rectangle current,
boolean tile_woi) {
if (!tile_woi) {
if (current == null) {
return single;
} else {
return null;
}
} else {
if (current == null) {
return new Rectangle (enclosing.x, enclosing.y, step.width, step.height);
} else {
int x = current.x + step.x;
int y = current.y + step.y;
if (x < enclosing.x + enclosing.width) {
return new Rectangle (x, current.y, step.width, step.height);
} else if (y < enclosing.y + enclosing.height) {
return new Rectangle (enclosing.x, y, step.width, step.height);
} else {
return null;
}
}
}
}
public static void testVegetationLMA(
boolean combine_segments,
CLTParameters clt_parameters,
int width,
double [] terrain_average, // full image average terrain (no nulls)
double [] vegetation_average, // full image average vegetation (with nulls)
double [][] terrain_rendered, // terrain rendered for scenes (has nulls)
double [][][] vegetation_offsets, // [num_scenes][pixel]{dx,dy} differential offsets of vegetation to terrain grid
String [] titles,
int debugLevel) {
boolean run_combine = combine_segments; // true; // if true, run combining instead of LMA
boolean tile_woi = true; // if false - use woi50;
boolean restore_mode = false;
boolean save_par_files = true; // false;
boolean diff_mode = true;
// Rectangle woi_enclosing = new Rectangle(130, 270, 150, 110); // will be tiled, using width/height from woi_step;
// Rectangle woi_enclosing = new Rectangle(150, 310, 50, 40); // will be tiled, using width/height from woi_step;
// Rectangle woi_enclosing = new Rectangle(160, 310, 30, 20); // will be tiled, using width/height from woi_step;
Rectangle woi_enclosing = new Rectangle(80, 210, 210, 230); // will be tiled, using width/height from woi_step;
Rectangle woi_step = new Rectangle(10,10,20,20);
Rectangle woi50 = new Rectangle(160,310,20,20); // 170
boolean skip_existing_woi = true; // skip existing woi/parameters, already saved.
String segments_dir = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/segments";
int min_scenes = 1; // 10; // for new scenes only, for old ones use 10
double default_alpha = 0.5; // 0.8;
double reg_weights = 0.25; // fraction of the total weight used for regularization
double alpha_loss = 100.0; // 10.0; /// 100.0; // 10.0; // 10000.0; // 1000.0; // 100.; // 10.0; // quadratic loss when alpha reaches -1.0 or 2.0
double alpha_offset = 0.0; // 0.02; // 0.03; // if >0, start losses above 0.0 and below 1.0;
double alpha_lpf = 2.5; // 5; /// 2; // 5; /// 10; /// 15; // 10.0; // 5.0; // 10.0; // 3; // 10; // 20; // 6.0; // 3.0; // 2.0; // 1.5; // 5.0; // 0.5; // pull to average of 4 neighbors
boolean alpha_piece_linear = true; // false; // true;
double alpha_scale_avg = 1.0; // 1.1; // 0.9; // 2.0; // 1.5; // scale average alpha (around 0.5) when pulling to it
double alpha_push = 12; // 10.0; // 15.0; // push from alpha==0.5
double alpha_push_neutral = 0.5; // 0.6; // 0.8; // alpha point from which push (closer to opaque)
double alpha_push_center = 1.5; // weight of center alpha pixel relative to each of the 4 ortho ones
double alpha_mm_hole = 0.1; // NaN to disable. Local "almost minimum" (lower than this fraction between min and max neighbor) is not subject to alpha_lpf
double terr_lpf = 0.1; // 0.15; /// 0.2; /// 0.1; // pull terrain to average of 4 neighbors (very small)
double veget_lpf = 0.2; //0.15; /// 0.2; //// 0.01; /// 0.1; // pull vegetation to average of 4 neighbors (very small - maybe not needed)
double terr_pull0 = 0.05; //0.03; ////// 0.05; ///// 0.1; //// 0.01; /// 0.2; /// 0.1; //pull terrain to zero (makes sense with UM
double veget_pull0 = 0.05; //0.1; // 0.03; ////// 0.05; ///// 0.1; //// 0.01; /// 0.1; // pull vegetation to zero (makes sense with UM
double boost_parallax = 3.0; /// 1.0; /////// 5.0; /// 1.0; // 5;
double max_parallax = 10;
// boolean next_run = false;
boolean read_pars = false; // true; /// false; /// true; // false; // true;
double threshold_terrain = 0.05;
double min_max_terrain= 0.1;
double min_terrain = 0.001;
double min_vegetation = 0.5;
boolean um_en = true;
double um_sigma = 1.0;
double um_weight = 0.8;
double lambda = 5.0; // 0.1;
double lambda_scale_good = 0.5;
double lambda_scale_bad = 8.0;
double lambda_max = 1000;
double rms_diff = 1e-8; // 0.0001; virtually forever
int num_iter = 25; // 100;
// combine parameters
int border_width = 6;
boolean render_open = true; // render open areas (no vegetation offset)
boolean render_no_alpha = true; // render where no opacity is available
double alpha_min = 0.1; // below - completely transparent vegetation
double alpha_max = 0.8; // above - completely opaque
double weight_opaque = 0.02; // render through completely opaque vegetation
double boost_parallax_render = 3; // increase weights of scenes with high parallax relative to the reference one
double max_parallax_render = 10; // do not consider maximal parallax above this (consider it a glitch)
int num_exaggerate = 3;
int min_total_scenes = 2;
int min_samples_scene = 10;
int min_pixels = 10;
// boolean exit_loop = debugLevel < 1000;
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/lma/parameters_vector_data_1000-0.03.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_1000-0.03.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-live_10000_0.02_3.0.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-al0.0-alo0.02-alp10.0-tl0.1-vl0.1-bp1.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-al10.0-alo0.0-alp10.0-tl0.1-vl0.1-bp1.0-um1.0_0.8-live.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";
Rectangle woi_last_done = null; // new Rectangle(150, 270, 20, 20); // null; // to be able to continue
boolean last_run = false;
if (um_en) {
double [][] um_data = new double [terrain_rendered.length+2][];
System.arraycopy(terrain_rendered, 0, um_data, 0, terrain_rendered.length);
um_data[terrain_rendered.length + 0] = terrain_average;
um_data[terrain_rendered.length + 1] = vegetation_average;
unsharpMaskMulti(
um_data, // final double [][] data, SHOULD not have NaN
width, // final int width,
um_sigma, // final double um_sigma,
um_weight); // final double um_weight)
}
if ((debugLevel > 3) || um_en) {
double [][][] dbg_img = new double[3][vegetation_offsets.length][vegetation_offsets[0].length];
for (int n = 0; n < 2; n++) {
for (int nscene = 0; nscene < vegetation_offsets.length; nscene++) {
Arrays.fill(dbg_img[n][nscene], Double.NaN);
}
}
for (int nscene = 0; nscene < vegetation_offsets.length; nscene++) {
for (int npix = 0; npix < vegetation_offsets[0].length; npix++) {
if (vegetation_offsets[nscene][npix] != null) {
double dx =vegetation_offsets[nscene][npix][0];
double dy =vegetation_offsets[nscene][npix][1];
dbg_img[0][nscene][npix] = Math.sqrt(dx*dx + dy*dy);
dbg_img[1][nscene][npix] = dx;
dbg_img[2][nscene][npix] = dy;
}
}
}
ShowDoubleFloatArrays.showArraysHyperstack(
dbg_img, // double[][][] pixels,
width, // int width,
"vegetation_offsets.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
new String[] {"dist","dx","dy"}, // String [] frame_titles, // frame titles or null
true); // boolean show)
ShowDoubleFloatArrays.showArrays(
terrain_rendered,
width,
terrain_rendered[0].length/width,
true,
"terrain_rendered.tiff",
titles);
ShowDoubleFloatArrays.showArrays(
new double [][] {terrain_average,vegetation_average},
width,
terrain_rendered[0].length/width,
true,
"terrain_vegetation_averages.tiff",
new String[] {"terrain","vegetation"});
}
VegetationLMA vegetationLMA = new VegetationLMA (
width, // int width,
diff_mode, // boolean diff_mode,
terrain_average, // double [] terrain_average, // full image average terrain (no nulls)
vegetation_average, // double [] vegetation_average, // full image average vegetation (with nulls)
terrain_rendered, // double [][] terrain_rendered, // terrain rendered for scenes (has nulls)
vegetation_offsets); // double [][][] vegetation_offsets // [num_scenes][pixel]{dx,dy} differential offsets of vegetation to terrain grid
// Rectangle woi50 = new Rectangle(143,317,50,50);
// Rectangle woi50 = new Rectangle(143,317,25,25);
if (run_combine) {
VegetationSegment [] segments = vegetationLMA.readAllSegments(
segments_dir); // String dir_path)
vegetationLMA.combineSegments(
segments,
border_width, // int width);
render_open, // boolean render_open, // render open areas (no vegetation offset)
render_no_alpha, // boolean render_no_alpha, // render where no opacity is available
alpha_min, // double alpha_min, // below - completely transparent vegetation
alpha_max, // double alpha_max, // above - completely opaque
weight_opaque, // double weight_opaque, // render through completely opaque vegetation
boost_parallax_render, // double boost_parallax) { // increase weights of scenes with high parallax relative to the reference one
max_parallax_render, // final double max_parallax,
num_exaggerate); // final int num_exaggerate) { // show amplified difference from filtering
return;
}
Rectangle woi = woi_last_done;
while (true) {
woi = nextTileWoi(
woi_enclosing, // Rectangle enclosing,
woi_step, // Rectangle step,
woi50, // Rectangle single,
woi, // Rectangle current,
tile_woi); // boolean tile_woi)
if (woi == null) {
System.out.println ("===== No WOIs to process left, exiting");
break;
}
String par_path = restore_mode? "RESTORE": (read_pars ? parameters_path : null);
System.out.println("===== Will process WOI ("+woi.x+", "+woi.y+", "+woi.width+", "+woi.height+") of the enclosing WOI ("+
+woi_enclosing.x+", "+woi_enclosing.y+", "+woi_enclosing.width+", "+woi_enclosing.height+").");
int num_samples = vegetationLMA.prepareLMA(
false, // final boolean keep_parameters,
woi, // final Rectangle woi,
min_scenes, // final int min_scenes, // minimal number of scenes (inside woi) vegetation pixel must influence
min_total_scenes, // final int min_total_scenes,
min_samples_scene, //final int min_samples_scene, // 10
min_pixels, // final int min_pixels,
default_alpha, // final double default_alpha,
reg_weights, // final double reg_weights, // fraction of the total weight used for regularization
alpha_loss, // final double alpha_loss, // quadratic loss when alpha reaches -1.0 or 2.0
alpha_offset, // final double alpha_offset, // quadratic loss when alpha reaches -1.0 or 2.0
alpha_lpf, // final double alpha_lpf, // pull to average of 4 neighbors
alpha_piece_linear, // final boolean alpha_piece_linear, // true - piece-linear, false - half-cosine
alpha_scale_avg, // final double alpha_scale_avg, // = 1.2; // scale average alpha (around 0.5) when pulling to it
alpha_push, // final double alpha_push, // 5.0; // push from alpha==0.5
alpha_push_neutral, // double alpha_push_neutral = 0.8; // alpha point from which push (closer to opaque)
alpha_push_center,// final double alpha_push_center,// 1.5; // weight of center alpha pixel relative to each of the 4 ortho ones
alpha_mm_hole, // double alpha_mm_hole = 0.1; // NaN to disable. Local "almost minimum" (lower than this fraction between min and max neighbor) is not subject to alpha_lpf
terr_lpf, // final double terr_lpf, // pull terrain to average of 4 neighbors (very small)
veget_lpf, // final double veget_lpf, // pull vegetation to average of 4 neighbors (very small - maybe not needed)
terr_pull0, // final double terr_pull0, // pull terrain to zero (makes sense with UM
veget_pull0, // final double veget_pull0, // pull vegetation to zero (makes sense with UM
boost_parallax, // final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene
max_parallax, //final double max_parallax, // do not consider maximal parallax above this (consider it a glitch)
um_sigma, // final double um_sigma, // just use in debug image names
(um_en? um_weight: 0.0), // final double um_weight,
par_path, // final String parameters_read_path,
debugLevel); // final int debugLevel);
if (num_samples <= 0) {
System.out.println("Insufficient data in this segment, skipping it.");
continue;
}
if (save_par_files && skip_existing_woi) { // check that segment already exists
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 already exists, skipping this woi");
continue;
}
if (new File (save_path.replace("-new-","-file-")).exists()) {
System.out.println("File "+save_path+"\n already exists, skipping this woi");
continue;
}
vegetation_average, // double [] vegetation_average, // full image average vegetation (with nulls)
terrain_rendered, // double [][] terrain_rendered, // terrain rendered for scenes (has nulls)
veg_to_terr, // double [][][] vegetation_offsets, // [num_scenes][pixel]{dx,dy} differential offsets of vegetation to terrain grid
titles, // String [] titles,
debugLevel); // int debugLevel)
}
public static void unsharpMaskMulti(
final double [][] data,
final int width,
final double um_sigma,
final double um_weight) {
final int height = data[0].length / width;
final int num_images = data.length;
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [] data_orig = new double [width * height];
for (int nimg = ai.getAndIncrement(); nimg < num_images; nimg = ai.getAndIncrement()) {
double [] data_slice = data[nimg];
System.arraycopy(data_slice, 0, data_orig,0,data_orig.length);
(new DoubleGaussianBlur()).blurDouble(
data_slice, //
width,
height,
um_sigma, // double sigmaX,
um_sigma, // double sigmaY,
0.01); // double accuracy)
for (int i = 0; i < data_orig.length; i++) {
data_slice[i] = data_orig[i] - um_weight * data_slice[i];
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
public static Rectangle nextTileWoi(
Rectangle enclosing,
Rectangle step,
Rectangle single,
Rectangle current,
boolean tile_woi) {
if (!tile_woi) {
if (current == null) {
return single;
} else {
return null;
}
} else {
if (current == null) {
return new Rectangle (enclosing.x, enclosing.y, step.width, step.height);
} else {
int x = current.x + step.x;
int y = current.y + step.y;
if (x < enclosing.x + enclosing.width) {
return new Rectangle (x, current.y, step.width, step.height);
} else if (y < enclosing.y + enclosing.height) {
return new Rectangle (enclosing.x, y, step.width, step.height);
} else {
return null;
if ("RESTORE".equals(par_path)) {
System.out.println("Reading fitted parameters from file");
if (save_par_files) {
String restore_dir = vegetationLMA.debug_path;
String debug_title = vegetationLMA.getParametersDebugTitle();
vegetationLMA.saveParametersFile(
restore_dir, // String dir,
debug_title, // String title, // no .par-tiff
null); // double [] vector)
continue;
}
}
if (debugLevel > 0) { // make save w/o showing?
vegetationLMA.showYfX(
null, // double [] vector,
"reconstructed_model-x"+woi.x+"-y"+woi.y+"-w"+woi.width+"-h"+woi.height); // String title)
vegetationLMA.showResults(
"terr_split-x"+woi.x+"-y"+woi.y+"-w"+woi.width+"-h"+woi.height, // String title,
vegetationLMA.getParametersVector(), // double [] vector,
threshold_terrain, // double threshold_terrain,
min_max_terrain, // double min_max_terrain, //0.1
min_terrain, //double min_terrain, //0.001
min_vegetation); // double min_vegetation) { // 0.5
}
/// next_run = true;
vegetationLMA.debug_index = 0;
vegetationLMA.debug_image = new double [num_iter][];
int lma_rslt= vegetationLMA.runLma( // <0 - failed, >=0 iteration number (1 - immediately)
lambda, // double lambda, // 0.1
lambda_scale_good,// double lambda_scale_good,// 0.5
lambda_scale_bad, // double lambda_scale_bad, // 8.0
lambda_max, // double lambda_max, // 100
rms_diff, // double rms_diff, // 0.001
num_iter, //int num_iter, // 20
last_run, // boolean last_run,
null, // String dbg_prefix,
debugLevel); // int debug_level)
// save results
if (save_par_files) {
String restore_dir = segments_dir; // vegetationLMA.debug_path;
String debug_title = vegetationLMA.getParametersDebugTitle();
vegetationLMA.saveParametersFile(
restore_dir, // String dir,
debug_title, // String title, // no .par-tiff
null); // double [] vector)
// continue;
}
}
/*
if (debugLevel >-2) {
vegetationLMA.showYfX(
null, // double [] vector,
"reconstructed_model_adjusted"); // String title)
}
*/
return; //
}
public static void testVegetationLMA(
public void testVegetationLMA(
boolean combine_segments,
int width,
double [] terrain_average, // full image average terrain (no nulls)
double [] vegetation_average, // full image average vegetation (with nulls)
double [][] terrain_rendered, // terrain rendered for scenes (has nulls)
double [][][] vegetation_offsets, // [num_scenes][pixel]{dx,dy} differential offsets of vegetation to terrain grid
String [] titles,
CLTParameters clt_parameters,
int debugLevel) {
boolean run_combine = combine_segments; // true; // if true, run combining instead of LMA
boolean tile_woi = true; // if false - use woi50;
......@@ -716,13 +1567,13 @@ public class VegetationModel {
// Rectangle woi_enclosing = new Rectangle(130, 270, 150, 110); // will be tiled, using width/height from woi_step;
// Rectangle woi_enclosing = new Rectangle(150, 310, 50, 40); // will be tiled, using width/height from woi_step;
// Rectangle woi_enclosing = new Rectangle(160, 310, 30, 20); // will be tiled, using width/height from woi_step;
Rectangle woi_enclosing = new Rectangle(80, 210, 210, 230); // will be tiled, using width/height from woi_step;
// Rectangle woi_enclosing = new Rectangle(80, 210, 210, 230); // will be tiled, using width/height from woi_step;
Rectangle woi_enclosing = new Rectangle(0, 0, 200, 160); // will be tiled, using width/height from woi_step;
Rectangle woi_step = new Rectangle(10,10,20,20);
Rectangle woi_last_done = null; // new Rectangle(150, 270, 20, 20); // null; // to be able to continue
Rectangle woi50 = new Rectangle(160,310,20,20); // 170
boolean skip_existing_woi = true; // skip existing woi/parameters, already saved.
String segments_dir = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/segments";
String segments_dir = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/segments_new/";
int min_scenes = 1; // 10; // for new scenes only, for old ones use 10
double default_alpha = 0.5; // 0.8;
......@@ -742,6 +1593,8 @@ public class VegetationModel {
double terr_pull0 = 0.05; //0.03; ////// 0.05; ///// 0.1; //// 0.01; /// 0.2; /// 0.1; //pull terrain to zero (makes sense with UM
double veget_pull0 = 0.05; //0.1; // 0.03; ////// 0.05; ///// 0.1; //// 0.01; /// 0.1; // pull vegetation to zero (makes sense with UM
double boost_parallax = 3.0; /// 1.0; /////// 5.0; /// 1.0; // 5;
double max_parallax = 10;
// boolean next_run = false;
boolean read_pars = false; // true; /// false; /// true; // false; // true;
double threshold_terrain = 0.05;
......@@ -751,6 +1604,11 @@ public class VegetationModel {
boolean um_en = true;
double um_sigma = 1.0;
double um_weight = 0.8;
double nan_tolerance = 0.001;
int nan_grow = 20;
double lambda = 5.0; // 0.1;
double lambda_scale_good = 0.5;
......@@ -758,9 +1616,6 @@ public class VegetationModel {
double lambda_max = 1000;
double rms_diff = 1e-8; // 0.0001; virtually forever
int num_iter = 25; // 100;
// combine parameters
......@@ -772,49 +1627,52 @@ public class VegetationModel {
double alpha_max = 0.8; // above - completely opaque
double weight_opaque = 0.02; // render through completely opaque vegetation
double boost_parallax_render = 3; // increase weights of scenes with high parallax relative to the reference one
double max_parallax_render = 10; // do not consider maximal parallax above this (consider it a glitch)
int num_exaggerate = 3;
int min_total_scenes = 2;
int min_samples_scene = 10;
int min_pixels = 10;
// boolean exit_loop = debugLevel < 1000;
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/lma/parameters_vector_data_1000-0.03.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_1000-0.03.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-live_10000_0.02_3.0.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-al0.0-alo0.02-alp10.0-tl0.1-vl0.1-bp1.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-al10.0-alo0.0-alp10.0-tl0.1-vl0.1-bp1.0-um1.0_0.8-live.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";
Rectangle woi_last_done = null; // new Rectangle(150, 270, 20, 20); // null; // to be able to continue
boolean last_run = false;
if (um_en) {
double [][] um_data = new double [terrain_rendered.length+2][];
System.arraycopy(terrain_rendered, 0, um_data, 0, terrain_rendered.length);
um_data[terrain_rendered.length + 0] = terrain_average;
um_data[terrain_rendered.length + 1] = vegetation_average;
double [][] um_data = new double [terrain_scenes_render.length+2][];
System.arraycopy(terrain_scenes_render, 0, um_data, 0, terrain_scenes_render.length);
um_data[terrain_scenes_render.length + 0] = terrain_average_render;
um_data[terrain_scenes_render.length + 1] = vegetation_average_render;
unsharpMaskMulti(
um_data, // final double [][] data, SHOULD not have NaN
width, // final int width,
um_sigma, // final double um_sigma,
um_weight); // final double um_weight)
um_data, // final double [][] data, SHOULD not have NaN
full.width, // final int width,
um_sigma, // final double um_sigma,
um_weight); // final double um_weight)
}
// maybe it is better to set NaN before UM and then use UM with fillNaN
zerosToNans (
terrain_scenes_render, // final double [][] data,
full.width, // final int width,
nan_tolerance, // final double tolerance,
nan_grow); // final int grow)
if ((debugLevel > 3) || um_en) {
double [][][] dbg_img = new double[3][vegetation_offsets.length][vegetation_offsets[0].length];
for (int n = 0; n < 2; n++) {
for (int nscene = 0; nscene < vegetation_offsets.length; nscene++) {
double [][][] dbg_img = new double[3][vegetation_warp.length][vegetation_warp[0].length];
for (int n = 0; n < dbg_img.length; n++) {
for (int nscene = 0; nscene < vegetation_warp.length; nscene++) {
Arrays.fill(dbg_img[n][nscene], Double.NaN);
}
}
for (int nscene = 0; nscene < vegetation_offsets.length; nscene++) {
for (int npix = 0; npix < vegetation_offsets[0].length; npix++) {
if (vegetation_offsets[nscene][npix] != null) {
double dx =vegetation_offsets[nscene][npix][0];
double dy =vegetation_offsets[nscene][npix][1];
for (int nscene = 0; nscene < vegetation_warp.length; nscene++) {
for (int npix = 0; npix < vegetation_warp[0].length; npix++) {
if (vegetation_warp[nscene][npix] != null) {
double dx =vegetation_warp[nscene][npix][0];
double dy =vegetation_warp[nscene][npix][1];
dbg_img[0][nscene][npix] = Math.sqrt(dx*dx + dy*dy);
dbg_img[1][nscene][npix] = dx;
dbg_img[2][nscene][npix] = dy;
......@@ -824,39 +1682,29 @@ public class VegetationModel {
ShowDoubleFloatArrays.showArraysHyperstack(
dbg_img, // double[][][] pixels,
width, // int width,
full.width, // int width,
"vegetation_offsets.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
scene_names, // String [] titles, // all slices*frames titles or just slice titles or null
new String[] {"dist","dx","dy"}, // String [] frame_titles, // frame titles or null
true); // boolean show)
ShowDoubleFloatArrays.showArrays(
terrain_rendered,
width,
terrain_rendered[0].length/width,
terrain_scenes_render,
full.width,
full.height,
true,
"terrain_rendered.tiff",
titles);
scene_names);
ShowDoubleFloatArrays.showArrays(
new double [][] {terrain_average,vegetation_average},
width,
terrain_rendered[0].length/width,
new double [][] {terrain_average_render,vegetation_average_render},
full.width,
full.height,
true,
"terrain_vegetation_averages.tiff",
new String[] {"terrain","vegetation"});
}
VegetationLMA vegetationLMA = new VegetationLMA (
width, // int width,
diff_mode, // boolean diff_mode,
terrain_average, // double [] terrain_average, // full image average terrain (no nulls)
vegetation_average, // double [] vegetation_average, // full image average vegetation (with nulls)
terrain_rendered, // double [][] terrain_rendered, // terrain rendered for scenes (has nulls)
vegetation_offsets); // double [][][] vegetation_offsets // [num_scenes][pixel]{dx,dy} differential offsets of vegetation to terrain grid
// Rectangle woi50 = new Rectangle(143,317,50,50);
// Rectangle woi50 = new Rectangle(143,317,25,25);
VegetationLMA vegetationLMA = new VegetationLMA (this);
if (run_combine) {
......@@ -871,6 +1719,7 @@ public class VegetationModel {
alpha_max, // double alpha_max, // above - completely opaque
weight_opaque, // double weight_opaque, // render through completely opaque vegetation
boost_parallax_render, // double boost_parallax) { // increase weights of scenes with high parallax relative to the reference one
max_parallax_render, // final double max_parallax,
num_exaggerate); // final int num_exaggerate) { // show amplified difference from filtering
return;
}
......@@ -893,6 +1742,11 @@ public class VegetationModel {
false, // final boolean keep_parameters,
woi, // final Rectangle woi,
min_scenes, // final int min_scenes, // minimal number of scenes (inside woi) vegetation pixel must influence
min_total_scenes, // final int min_total_scenes,
min_samples_scene, //final int min_samples_scene, // 10
min_pixels, // final int min_pixels,
default_alpha, // final double default_alpha,
reg_weights, // final double reg_weights, // fraction of the total weight used for regularization
alpha_loss, // final double alpha_loss, // quadratic loss when alpha reaches -1.0 or 2.0
......@@ -910,10 +1764,16 @@ public class VegetationModel {
terr_pull0, // final double terr_pull0, // pull terrain to zero (makes sense with UM
veget_pull0, // final double veget_pull0, // pull vegetation to zero (makes sense with UM
boost_parallax,// final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene
max_parallax, //final double max_parallax, // do not consider maximal parallax above this (consider it a glitch)
um_sigma, // final double um_sigma, // just use in debug image names
(um_en? um_weight: 0.0), // final double um_weight,
par_path, // final String parameters_read_path,
debugLevel); // final int debugLevel);
if (num_samples <= 0) {
System.out.println("Insufficient data in this segment, skipping it.");
continue;
}
if (save_par_files && skip_existing_woi) { // check that segment already exists
String save_path = VegetationLMA.getSavePath(
segments_dir, // String dir,
......@@ -926,9 +1786,6 @@ public class VegetationModel {
System.out.println("File "+save_path+"\n already exists, skipping this woi");
continue;
}
}
if ("RESTORE".equals(par_path)) {
......@@ -985,17 +1842,12 @@ public class VegetationModel {
}
/*
if (debugLevel >-2) {
vegetationLMA.showYfX(
null, // double [] vector,
"reconstructed_model_adjusted"); // String title)
}
*/
return; //
}
public static ImagePlus showOffsetsCombo(
final double [][][] map_combo,
......@@ -1847,7 +2699,17 @@ public class VegetationModel {
final double [][][] pXpYD,
final int ref_index){
final int num_scenes = pXpYD.length;
final int num_pixels = pXpYD[0].length;
int npix = 0;
for (int i = 0; i < pXpYD.length; i++) if (pXpYD[i] != null){
npix = pXpYD[i].length;
break;
}
if (npix == 0) {
System.out.println("diffPxPyDs(): no data available!");
return null;
}
final int num_pixels = npix;
final double [][][] diff_pXpYD = new double [num_scenes][num_pixels][];
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
......@@ -1968,6 +2830,60 @@ public class VegetationModel {
}
public static void zerosToNans (
final double [][] data,
final int width,
final double tolerance,
final int grow) {
final Thread[] threads = ImageDtt.newThreadArray();
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 n = ai.getAndIncrement(); n < data.length; n = ai.getAndIncrement()) {
zerosToNans ( // not threaded to be used by threads
data[n], // double [] data,
width, // int width,
tolerance, // double tolerance,
grow); //int grow)
}
}
};
}
ImageDtt.startAndJoin(threads);
}
public static void zerosToNans ( // not threaded to be used by threads
double [] data,
int width,
double tolerance,
int grow) {
int length = data.length;
int height = length/width;
TileNeibs tn = new TileNeibs(width,height);
boolean [] zeros = new boolean[length];
for (int pix = 0; pix < length; pix++) if (Math.abs(data[pix]) <= tolerance){
check_zero: {
for (int dir = 0; dir < TileNeibs.DIRS; dir++) { //
int pix1 = tn.getNeibIndex(pix, dir);
if ((pix1 >=0) && (Math.abs(data[pix1]) > tolerance)) {
break check_zero;
}
}
zeros[pix] = true;
}
}
tn.growSelection(
grow, // int grow, // grow tile selection by 1 over non-background tiles 1: 4 directions, 2 - 8 directions, 3 - 8 by 1, 4 by 1 more
zeros, // final boolean [] tiles,
null); // final boolean [] prohibit)
for (int pix = 0; pix < length; pix++) if (zeros[pix]){
data[pix] = Double.NaN;
}
return;
}
}
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