Commit 9ba553bb authored by Andrey Filippov's avatar Andrey Filippov

prepared elevation data, starting elevation LMA fitting

parent 5980d194
...@@ -5802,11 +5802,11 @@ public class Eyesis_Correction implements PlugIn, ActionListener { ...@@ -5802,11 +5802,11 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
} else if (label.equals("Process Merged")) { } else if (label.equals("Process Merged")) {
OrangeTest.processMerged(); OrangeTest.processMerged();
} else if (label.equals("Vegetation LMA")) { } else if (label.equals("Vegetation LMA")) {
VegetationModel.testVegetationLMA( VegetationModel.processVegetationLMA(
CLT_PARAMETERS, //CLTParameters clt_parameters, CLT_PARAMETERS, //CLTParameters clt_parameters,
false); //boolean combine_segments); false); //boolean combine_segments);
} else if (label.equals("Combine LMA Segments")) { } else if (label.equals("Combine LMA Segments")) {
VegetationModel.testVegetationLMA( VegetationModel.processVegetationLMA(
CLT_PARAMETERS, //CLTParameters clt_parameters, CLT_PARAMETERS, //CLTParameters clt_parameters,
true); //boolean combine_segments); true); //boolean combine_segments);
} }
......
...@@ -760,7 +760,9 @@ min_str_neib_fpn 0.35 ...@@ -760,7 +760,9 @@ min_str_neib_fpn 0.35
public double terr_difference = 100.0; // vegetation is 100 warmer (target) public double terr_difference = 100.0; // vegetation is 100 warmer (target)
public double terr_pull_cold = 0.001; // pull vegetations to warm, terrain to cold public double terr_pull_cold = 0.001; // pull vegetations to warm, terrain to cold
public double terr_alpha_dflt = 0.5;
public double terr_alpha_contrast = 1.0; // initial alpha contrast (>=1.0)
public double terr_alpha_dflt = 0.5; // now unused
public double terr_alpha_loss = 100.0; public double terr_alpha_loss = 100.0;
public double terr_alpha_offset = 0.0; public double terr_alpha_offset = 0.0;
public double terr_alpha_lpf = 2.5; // pull to average of 4 neighbors public double terr_alpha_lpf = 2.5; // pull to average of 4 neighbors
...@@ -775,6 +777,7 @@ min_str_neib_fpn 0.35 ...@@ -775,6 +777,7 @@ min_str_neib_fpn 0.35
public double terr_veget_lpf = 0.2; // pull vegetation to average of 4 neighbors (very small - maybe not needed) 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_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 public double terr_veget_pull0 = 0.05; // pull vegetation to zero (makes sense with UM
public double terr_scenes_pull0 = 1.0; // pull average scene offset to zero
// LMA parameters // LMA parameters
public double terr_boost_parallax = 3.0; // public double terr_boost_parallax = 3.0; //
...@@ -2013,15 +2016,19 @@ min_str_neib_fpn 0.35 ...@@ -2013,15 +2016,19 @@ min_str_neib_fpn 0.35
gd.addNumericField("Min influenced scenes",terr_min_scenes, 0,3, "", "Minimal number of scenes (inside woi) vegetation pixel must influence."); gd.addNumericField("Min influenced scenes",terr_min_scenes, 0,3, "", "Minimal number of scenes (inside woi) vegetation pixel must influence.");
gd.addNumericField("Minimal samples/scene",terr_min_samples_scene, 0,3,"","Minimal samples per scene used for fitting (skip scene if less)."); gd.addNumericField("Minimal samples/scene",terr_min_samples_scene, 0,3,"","Minimal samples per scene used for fitting (skip scene if less).");
gd.addNumericField("Minimum scenes used", terr_min_total_scenes, 0,3,"", "Minimal total number of scenes used (skip segment if less)."); gd.addNumericField("Minimum scenes used", terr_min_total_scenes, 0,3,"", "Minimal total number of scenes used (skip segment if less).");
gd.addNumericField("Minimal pixels fitted",terr_min_pixels, 0,3,"", "Minimal number of terrain and vegetation pixels used for fitting in this segment(skip segment if less)."); gd.addNumericField("Minimal pixels fitted",terr_min_pixels, 0,3,"", "Minimal number of terrain and vegetation pixels used for fitting in this segment(skip segment if less).");
gd.addCheckbox ("Start by temperature", terr_warm_veget, "Start with vegetation warmer than terrain."); gd.addCheckbox ("Start by temperature", terr_warm_veget, "Start with vegetation warmer than terrain.");
gd.addNumericField("Warmest terrain", terr_warmest, 5,7,"", "Above - vegetation. below - terrain."); gd.addNumericField("Warmest terrain", terr_warmest, 5,7,"", "Above - vegetation. below - terrain.");
gd.addNumericField("Initial split", terr_initial_split, 5,7,"", "Initial alpha: terrain 0.0+, vegetation 1.0-."); gd.addNumericField("Initial split", terr_initial_split, 5,7,"", "Initial alpha: terrain 0.0+, vegetation 1.0-.");
gd.addNumericField("Min. split fraction", terr_min_split_frac, 5,7,"", "minimal modality fraction to use split by temperature (otherwise use default alpha)."); gd.addNumericField("Min. split fraction", terr_min_split_frac, 5,7,"", "minimal modality fraction to use split by temperature (otherwise use default alpha).");
gd.addNumericField("Vegetation warmer", terr_difference, 5,7,"", "Pull vegetation to be this warmer."); gd.addNumericField("Vegetation warmer", terr_difference, 5,7,"", "Pull vegetation to be this warmer.");
gd.addNumericField("Pull terrain cold", terr_pull_cold, 5,7,"", "Pull vegetations to warm, terrain to cold."); gd.addNumericField("Pull terrain cold", terr_pull_cold, 5,7,"", "Pull vegetations to warm, terrain to cold.");
gd.addNumericField("Alpha initial contrast",terr_alpha_contrast, 5,7,"","Initial alpha contrast (>= 1.0).");
gd.addNumericField("Defalt alpha", terr_alpha_dflt, 5,7,"", "Default vegetation alpha."); 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 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 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.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.addCheckbox ("Alpha piece-linear", terr_alpha_piece_linear, "Piece-linear alpha (_/\u203E, false - 0.0-cosine-1.0.");
...@@ -2035,6 +2042,7 @@ min_str_neib_fpn 0.35 ...@@ -2035,6 +2042,7 @@ min_str_neib_fpn 0.35
gd.addNumericField("Vegetation diffusion", terr_veget_lpf, 5,7,"", "LPF for vegetation 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("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.addNumericField("Vegetation pull zero", terr_veget_pull0, 5,7,"", "Vegetation pixels pull to 0 (makes sense with UM).");
gd.addNumericField("Pull scene offset", terr_scenes_pull0, 5,7,"", "Pull average scene offset to zero.");
gd.addMessage ("LMA parameters"); 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("Boost parallax", terr_boost_parallax, 5,7,"", "Increase weight of scenes that have high parallax to the reference one.");
...@@ -2721,6 +2729,7 @@ min_str_neib_fpn 0.35 ...@@ -2721,6 +2729,7 @@ min_str_neib_fpn 0.35
terr_min_split_frac = gd.getNextNumber();// double terr_min_split_frac = gd.getNextNumber();// double
terr_difference = gd.getNextNumber();// double terr_difference = gd.getNextNumber();// double
terr_pull_cold = gd.getNextNumber();// double terr_pull_cold = gd.getNextNumber();// double
terr_alpha_contrast = gd.getNextNumber();// double
terr_alpha_dflt = gd.getNextNumber();// double terr_alpha_dflt = gd.getNextNumber();// double
terr_alpha_loss = gd.getNextNumber();// double terr_alpha_loss = gd.getNextNumber();// double
terr_alpha_offset = gd.getNextNumber();// double terr_alpha_offset = gd.getNextNumber();// double
...@@ -2737,7 +2746,7 @@ min_str_neib_fpn 0.35 ...@@ -2737,7 +2746,7 @@ min_str_neib_fpn 0.35
terr_veget_lpf = gd.getNextNumber();// double terr_veget_lpf = gd.getNextNumber();// double
terr_terr_pull0 = gd.getNextNumber();// double terr_terr_pull0 = gd.getNextNumber();// double
terr_veget_pull0 = gd.getNextNumber();// double terr_veget_pull0 = gd.getNextNumber();// double
terr_scenes_pull0 = gd.getNextNumber();// double
terr_boost_parallax = gd.getNextNumber();// double terr_boost_parallax = gd.getNextNumber();// double
terr_max_parallax = gd.getNextNumber();// double terr_max_parallax = gd.getNextNumber();// double
terr_hifreq_weight = gd.getNextNumber();// double terr_hifreq_weight = gd.getNextNumber();// double
...@@ -3392,6 +3401,8 @@ min_str_neib_fpn 0.35 ...@@ -3392,6 +3401,8 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"terr_difference", terr_difference+""); // double properties.setProperty(prefix+"terr_difference", terr_difference+""); // double
properties.setProperty(prefix+"terr_pull_cold", terr_pull_cold+""); // double properties.setProperty(prefix+"terr_pull_cold", terr_pull_cold+""); // double
properties.setProperty(prefix+"terr_alpha_contrast", terr_alpha_contrast+""); // double
properties.setProperty(prefix+"terr_alpha_dflt", terr_alpha_dflt+""); // double 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_loss", terr_alpha_loss+""); // double
properties.setProperty(prefix+"terr_alpha_offset", terr_alpha_offset+""); // double properties.setProperty(prefix+"terr_alpha_offset", terr_alpha_offset+""); // double
...@@ -3406,6 +3417,7 @@ min_str_neib_fpn 0.35 ...@@ -3406,6 +3417,7 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"terr_veget_lpf", terr_veget_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_terr_pull0", terr_terr_pull0+""); // double
properties.setProperty(prefix+"terr_veget_pull0", terr_veget_pull0+""); // double properties.setProperty(prefix+"terr_veget_pull0", terr_veget_pull0+""); // double
properties.setProperty(prefix+"terr_scenes_pull0", terr_scenes_pull0+""); // double
properties.setProperty(prefix+"terr_boost_parallax", terr_boost_parallax+""); // double properties.setProperty(prefix+"terr_boost_parallax", terr_boost_parallax+""); // double
properties.setProperty(prefix+"terr_max_parallax", terr_max_parallax+""); // double properties.setProperty(prefix+"terr_max_parallax", terr_max_parallax+""); // double
...@@ -4082,6 +4094,8 @@ min_str_neib_fpn 0.35 ...@@ -4082,6 +4094,8 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"terr_difference")!= null) terr_difference=Double.parseDouble(properties.getProperty(prefix+"terr_difference")); if (properties.getProperty(prefix+"terr_difference")!= null) terr_difference=Double.parseDouble(properties.getProperty(prefix+"terr_difference"));
if (properties.getProperty(prefix+"terr_pull_cold")!= null) terr_pull_cold=Double.parseDouble(properties.getProperty(prefix+"terr_pull_cold")); if (properties.getProperty(prefix+"terr_pull_cold")!= null) terr_pull_cold=Double.parseDouble(properties.getProperty(prefix+"terr_pull_cold"));
if (properties.getProperty(prefix+"terr_alpha_contrast")!= null) terr_alpha_contrast=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_contrast"));
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_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_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_offset")!= null) terr_alpha_offset=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_offset"));
...@@ -4097,6 +4111,7 @@ min_str_neib_fpn 0.35 ...@@ -4097,6 +4111,7 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"terr_veget_lpf")!= null) terr_veget_lpf=Double.parseDouble(properties.getProperty(prefix+"terr_veget_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_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_veget_pull0")!= null) terr_veget_pull0=Double.parseDouble(properties.getProperty(prefix+"terr_veget_pull0"));
if (properties.getProperty(prefix+"terr_scenes_pull0")!= null) terr_scenes_pull0=Double.parseDouble(properties.getProperty(prefix+"terr_scenes_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_boost_parallax")!= null) terr_boost_parallax=Double.parseDouble(properties.getProperty(prefix+"terr_boost_parallax"));
if (properties.getProperty(prefix+"terr_max_parallax")!= null) terr_max_parallax=Double.parseDouble(properties.getProperty(prefix+"terr_max_parallax")); if (properties.getProperty(prefix+"terr_max_parallax")!= null) terr_max_parallax=Double.parseDouble(properties.getProperty(prefix+"terr_max_parallax"));
...@@ -4741,6 +4756,7 @@ min_str_neib_fpn 0.35 ...@@ -4741,6 +4756,7 @@ min_str_neib_fpn 0.35
imp.terr_min_split_frac = this.terr_min_split_frac; imp.terr_min_split_frac = this.terr_min_split_frac;
imp.terr_difference = this.terr_difference; imp.terr_difference = this.terr_difference;
imp.terr_pull_cold = this.terr_pull_cold; imp.terr_pull_cold = this.terr_pull_cold;
imp.terr_alpha_contrast = this.terr_alpha_contrast;
imp.terr_alpha_dflt = this.terr_alpha_dflt; imp.terr_alpha_dflt = this.terr_alpha_dflt;
imp.terr_alpha_loss = this.terr_alpha_loss; imp.terr_alpha_loss = this.terr_alpha_loss;
imp.terr_alpha_offset = this.terr_alpha_offset; imp.terr_alpha_offset = this.terr_alpha_offset;
...@@ -4756,6 +4772,7 @@ min_str_neib_fpn 0.35 ...@@ -4756,6 +4772,7 @@ min_str_neib_fpn 0.35
imp.terr_veget_lpf = this.terr_veget_lpf; imp.terr_veget_lpf = this.terr_veget_lpf;
imp.terr_terr_pull0 = this.terr_terr_pull0; imp.terr_terr_pull0 = this.terr_terr_pull0;
imp.terr_veget_pull0 = this.terr_veget_pull0; imp.terr_veget_pull0 = this.terr_veget_pull0;
imp.terr_scenes_pull0 = this.terr_scenes_pull0;
imp.terr_boost_parallax = this.terr_boost_parallax; imp.terr_boost_parallax = this.terr_boost_parallax;
imp.terr_max_parallax = this.terr_max_parallax; imp.terr_max_parallax = this.terr_max_parallax;
......
...@@ -6368,7 +6368,7 @@ public class OpticalFlow { ...@@ -6368,7 +6368,7 @@ public class OpticalFlow {
// int [] first_last = quadCLTs[ref_index].getFirstLastIndex(quadCLTs); // int [] first_last = quadCLTs[ref_index].getFirstLastIndex(quadCLTs);
QuadCLT [] quadCLT_tail = new QuadCLT [quadCLTs.length - earliest_scene]; QuadCLT [] quadCLT_tail = new QuadCLT [quadCLTs.length - earliest_scene];
System.arraycopy(quadCLTs, earliest_scene, quadCLT_tail, 0, quadCLT_tail.length); System.arraycopy(quadCLTs, earliest_scene, quadCLT_tail, 0, quadCLT_tail.length);
VegetationModel.test_vegetation( VegetationModel.prepareVegetationData(
clt_parameters, // CLTParameters clt_parameters, clt_parameters, // CLTParameters clt_parameters,
quadCLT_tail, // QuadCLT [] quadCLTs, quadCLT_tail, // QuadCLT [] quadCLTs,
ref_index-earliest_scene, // int ref_index, ref_index-earliest_scene, // int ref_index,
......
...@@ -8786,6 +8786,27 @@ ImageDtt.startAndJoin(threads); ...@@ -8786,6 +8786,27 @@ ImageDtt.startAndJoin(threads);
* @return data array made of input data with replaced NaN limited by * @return data array made of input data with replaced NaN limited by
* optional prohibit array and amount of growth. * optional prohibit array and amount of growth.
*/ */
public static double [] fillNaNs(
final double [] data,
final boolean [] prohibit,
int width,
final int grow,
double diagonal_weight, // relative to ortho
int num_passes,
final double max_rchange) // = 0.01
{
return fillNaNs(
data, // final double [] data,
null, // final double [] data_nan,
prohibit, // final boolean [] prohibit_in,
width, // int width,
grow, // final int grow,
diagonal_weight, //double diagonal_weight, // relative to ortho
num_passes, // int num_passes,
max_rchange, // final double max_rchange, // = 0.01
ImageDtt.THREADS_MAX); // final int threadsMax)
}
public static double [] fillNaNs( public static double [] fillNaNs(
final double [] data, final double [] data,
final boolean [] prohibit, final boolean [] prohibit,
......
...@@ -61,7 +61,7 @@ public class VegetationLMA { ...@@ -61,7 +61,7 @@ public class VegetationLMA {
public double [][] tvao; // [0][image_length] - terrain, [1][image_length] - vegetation, public double [][] tvao; // [0][image_length] - terrain, [1][image_length] - vegetation,
// public double [][] tva_hf; // [0][image_length] - terrain, [1][image_length] - vegetation, - laplacian // public double [][] tva_hf; // [0][image_length] - terrain, [1][image_length] - vegetation, - laplacian
public double [][][] scales_xy; // [scene][pixel{scale_x,scale_y}
public VegetationModel vegetationModel = null; public VegetationModel vegetationModel = null;
/* /*
// copy from Vegetation model // copy from Vegetation model
...@@ -99,7 +99,7 @@ public class VegetationLMA { ...@@ -99,7 +99,7 @@ public class VegetationLMA {
// private int num_used_scenes; // -> num_par_scenes // private int num_used_scenes; // -> num_par_scenes
private boolean [] used_scenes; // encode unused as NaN private boolean [] used_scenes; // encode unused as NaN
// private int [] used_scenes_indices; // private int [] used_scenes_indices;
public final double [] scene_weights;
private double [] parameters_vector = null; private double [] parameters_vector = null;
...@@ -126,7 +126,7 @@ public class VegetationLMA { ...@@ -126,7 +126,7 @@ public class VegetationLMA {
public boolean fit_scenes = true; public boolean fit_scenes = true;
public boolean fit_elevations = false; public boolean fit_elevations = false;
*/ */
public double alpha_initial_contrast = 1.0; // >=1.0
public double alpha_loss = 0; // not used with cosine alpha public double alpha_loss = 0; // not used with cosine alpha
public double alpha_offset = 0; // if >0, start losses above 0.0 and below 1.0; public double alpha_offset = 0; // if >0, start losses above 0.0 and below 1.0;
public double alpha_lpf = 0; public double alpha_lpf = 0;
...@@ -149,6 +149,9 @@ public class VegetationLMA { ...@@ -149,6 +149,9 @@ public class VegetationLMA {
// when unsharp mask is applied , pulling to 0 (when alpha is 0 (for vegetation) or 1.0 (for terrain) makes sense // when unsharp mask is applied , pulling to 0 (when alpha is 0 (for vegetation) or 1.0 (for terrain) makes sense
public double terr_pull0 = 0; // now - pull to filled terrain - terrain_average public double terr_pull0 = 0; // now - pull to filled terrain - terrain_average
public double veget_pull0 = 0; // now - pull to vegetation_pull (extended vegetation) public double veget_pull0 = 0; // now - pull to vegetation_pull (extended vegetation)
public double scenes_pull0 = 0; // pull average scene offset to 0;
public boolean use_scenes_pull0 = true; // derivative, set in setWeights
public double scale_scenes_pull = 0; // used in getFxDerivs to scale scene offsets as their weight will be reg_weights / extra_samples
public double boost_parallax = 1; public double boost_parallax = 1;
...@@ -176,6 +179,8 @@ public class VegetationLMA { ...@@ -176,6 +179,8 @@ public class VegetationLMA {
private double [] last_ymfx = null; private double [] last_ymfx = null;
private double [][] last_jt = null; private double [][] last_jt = null;
public boolean skip_ref_scene = false;
public boolean debug_deriv = true; public boolean debug_deriv = true;
public int debug_width = 12; public int debug_width = 12;
public int debug_decimals = 9; public int debug_decimals = 9;
...@@ -206,9 +211,14 @@ public class VegetationLMA { ...@@ -206,9 +211,14 @@ public class VegetationLMA {
tvao[TVAO_SCENE_OFFSET] = new double [num_scenes]; tvao[TVAO_SCENE_OFFSET] = new double [num_scenes];
setupLaplacians(0.0); // double weight_diag) setupLaplacians(0.0); // double weight_diag)
scene_weights = new double [num_scenes];
} }
public VegetationLMA (VegetationModel vegetationModel) { public VegetationLMA (
VegetationModel vegetationModel,
double alpha_initial_contrast) {
this.alpha_initial_contrast = alpha_initial_contrast;
full = vegetationModel.full; full = vegetationModel.full;
image_length = full.width * full.height; image_length = full.width * full.height;
num_scenes = vegetationModel.terrain_scenes_render.length; num_scenes = vegetationModel.terrain_scenes_render.length;
...@@ -221,17 +231,53 @@ public class VegetationLMA { ...@@ -221,17 +231,53 @@ public class VegetationLMA {
tvao = new double[TVAO_TYPES][]; tvao = new double[TVAO_TYPES][];
tvao[TVAO_TERRAIN] = this.terrain_average.clone(); tvao[TVAO_TERRAIN] = this.terrain_average.clone();
tvao[TVAO_VEGETATION] = this.vegetation_average.clone(); tvao[TVAO_VEGETATION] = this.vegetation_average.clone();
// tvao[TVAO_ALPHA] = new double [image_length]; // 0 - use terrain
tvao[TVAO_SCENE_OFFSET] = new double [num_scenes]; tvao[TVAO_SCENE_OFFSET] = new double [num_scenes];
setupInitialTerrainVegetationAlpha(
alpha_initial_contrast, // double alpha_contrast,
vegetationModel.terrain_filled, // double [] terrain_filled,
vegetationModel.vegetation_pull, // double [] vegetation_extended,
vegetationModel.vegetation_full); // double [] vegetation) { // best guess
/*
tvao[TVAO_ALPHA] =getInitialAlpha( tvao[TVAO_ALPHA] =getInitialAlpha(
vegetation_filtered, // double [] vegetation_filtered, vegetation_filtered, // double [] vegetation_filtered,
vegetationModel.initial_transparent, // double transparent, vegetationModel.initial_transparent, // double transparent,
vegetationModel.initial_opaque); // double opaque) vegetationModel.initial_opaque); // double opaque)
*/
setupLaplacians(0.0); // double weight_diag) setupLaplacians(0.0); // double weight_diag)
diff_offsets = vegetationModel.diff_mode; diff_offsets = vegetationModel.diff_mode;
this.vegetationModel = vegetationModel; // to access scene names, directories, reference index this.vegetationModel = vegetationModel; // to access scene names, directories, reference index
scene_weights = new double [num_scenes];
scales_xy = getScalesXY(vegetationModel.scale_dirs);
tvao[TVAO_ELEVATION] = vegetationModel.elevations.clone();
return; return;
} }
private static double [][][] getScalesXY(
final double [][][] scales_mag_dir) {
final int num_scenes = scales_mag_dir.length;
final int num_pixels = scales_mag_dir[0].length;
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
final double [][][] scales_xy = new double [num_scenes][num_pixels][];
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 npix = 0; npix < num_pixels; npix++) if (scales_mag_dir[nScene][npix] != null) {
double scale = scales_mag_dir[nScene][npix][0];
double angle = scales_mag_dir[nScene][npix][1];
scales_xy[nScene][npix] = new double [] {
scale*Math.cos(angle),
scale*Math.sin(angle)};
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return scales_xy;
}
private void setupLaplacians(double weight_diag) { private void setupLaplacians(double weight_diag) {
terrain_rendered_hf = new double [terrain_rendered.length][]; terrain_rendered_hf = new double [terrain_rendered.length][];
...@@ -243,7 +289,46 @@ public class VegetationLMA { ...@@ -243,7 +289,46 @@ public class VegetationLMA {
weight_diag); // final double weight_diag) weight_diag); // final double weight_diag)
} }
} }
private void setupInitialTerrainVegetationAlpha(
double alpha_contrast,
double [] terrain_filled,
double [] vegetation_extended,
double [] vegetation) { // best guess
double dbg_lim = 0.01;
tvao[TVAO_TERRAIN] = terrain_filled.clone(); // == vegetationModel.terrain_filled
tvao[TVAO_VEGETATION] = vegetation_extended.clone();
tvao[TVAO_ALPHA] = new double [image_length];
for (int npix = 0; npix < image_length; npix++) {
double t = terrain_filled[npix];
double v = vegetation[npix];
double vp = vegetation_extended[npix];
double a = 0; // Double.NaN; // .isNaN(vegetation_filtered[npix])? 0.0:1.0; // not needed
if (!Double.isNaN(t) && !Double.isNaN(v) && !Double.isNaN(vp)) {
if (v < t) {
a = 0.0;
} else if (v > vp) {
a = 1.0;
} else {
a = (v-t)/(vp-t);
if (alpha_contrast != 1.0) {
a = 0.5 + (a - 0.5)*alpha_contrast;
if (a < 0) a = 0;
else if (a > 1.0) a = 1;
}
}
// if (a < dbg_lim) a = dbg_lim;
// if ( a > 1.0-dbg_lim) a = 1.0-dbg_lim;
// tvao[TVAO_ALPHA][npix] = a;
}
if (a < dbg_lim) a = dbg_lim;
if ( a > 1.0-dbg_lim) a = 1.0-dbg_lim;
tvao[TVAO_ALPHA][npix] = a;
}
}
@SuppressWarnings("unused")
private static double [] getInitialAlpha( private static double [] getInitialAlpha(
double [] vegetation_filtered, double [] vegetation_filtered,
double transparent, double transparent,
...@@ -305,6 +390,7 @@ public class VegetationLMA { ...@@ -305,6 +390,7 @@ public class VegetationLMA {
final double veget_lpf, // pull vegetation to average of 4 neighbors (very small - maybe not needed) final double veget_lpf, // pull vegetation to average of 4 neighbors (very small - maybe not needed)
final double terr_pull0, // pull terrain to zero (makes sense with UM 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 veget_pull0, // pull vegetation to zero (makes sense with UM
final double scenes_pull0,
final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene 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 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_sigma, // just use in debug image names
...@@ -343,6 +429,7 @@ public class VegetationLMA { ...@@ -343,6 +429,7 @@ public class VegetationLMA {
this.veget_lpf = veget_lpf; this.veget_lpf = veget_lpf;
this.terr_pull0 = terr_pull0; this.terr_pull0 = terr_pull0;
this.veget_pull0 = veget_pull0; this.veget_pull0 = veget_pull0;
this.scenes_pull0 = scenes_pull0;
this.boost_parallax = boost_parallax; this.boost_parallax = boost_parallax;
this.um_sigma = um_sigma; // just use in debug image names this.um_sigma = um_sigma; // just use in debug image names
this.um_weight = um_weight; this.um_weight = um_weight;
...@@ -367,6 +454,9 @@ public class VegetationLMA { ...@@ -367,6 +454,9 @@ public class VegetationLMA {
int min_scenes_uses = min_scenes; int min_scenes_uses = min_scenes;
int min_scenes_used = min_scenes * 4; int min_scenes_used = min_scenes * 4;
boolean all_terrain = true; // use all terrain tiles even not used with vegetation
boolean [][] valid_woi = filterValidWoi ( boolean [][] valid_woi = filterValidWoi (
min_scenes_uses, // int min_scenes_uses, min_scenes_uses, // int min_scenes_uses,
min_scenes_used, // int min_scenes_used, min_scenes_used, // int min_scenes_used,
...@@ -377,7 +467,9 @@ public class VegetationLMA { ...@@ -377,7 +467,9 @@ public class VegetationLMA {
return -1; return -1;
} }
setupParametersIndices(valid_woi); // needs to know number of used scenes // all but scenes setupParametersIndices(
valid_woi, // needs to know number of used scenes // all but scenes
all_terrain); // boolean all_terrain
alpha_neibs = getNeighbors( alpha_neibs = getNeighbors(
TVAO_ALPHA, // final int tvao, // TVAO_VEGETATION_ALPHA TVAO_ALPHA, // final int tvao, // TVAO_VEGETATION_ALPHA
...@@ -413,11 +505,14 @@ public class VegetationLMA { ...@@ -413,11 +505,14 @@ public class VegetationLMA {
default_alpha); // final double default_alpha // use in areas where both terrain and vegetation are available default_alpha); // final double default_alpha // use in areas where both terrain and vegetation are available
*/ */
// new version - uses preset alpha for the full image // new version - uses preset alpha for the full image
setupParametersVector (); // moved tweaking to constructor;
/*
if (alpha_contrast == 0) { if (alpha_contrast == 0) {
setupParametersVector (); setupParametersVector ();
} else { } else {
setupParametersVector(alpha_contrast); // double alpha_contrast); setupParametersVector(alpha_contrast); // double alpha_contrast);
} }
*/
} }
from_file = false; from_file = false;
if (parameters_read_path != null) { if (parameters_read_path != null) {
...@@ -1354,9 +1449,22 @@ public class VegetationLMA { ...@@ -1354,9 +1449,22 @@ public class VegetationLMA {
// TODO: calculate high-frequency (laplacians) // TODO: calculate high-frequency (laplacians)
// regularization weights and derivatives // regularization weights and derivatives
// splitting alpha_lpf from alpha_loss+alpha_push
int ind_next = y_vector.length; int ind_next = y_vector.length;
if (use_scenes_pull0) { // single sample after differences
fX[ind_next] =0.0;
for (int n = 0; n < num_pars_scenes; n++) { // only count adjustable scene offsets
int np = ind_pars_scenes + n; // index of the alpha parameter
int nscene = par_rindex[np][1];
double sw=scene_weights[nscene] * scale_scenes_pull;
fX[ind_next] += sw * vector[np];
if (jt != null) {
jt[np][ind_next] = sw;
}
}
ind_next++;
}
// splitting alpha_lpf from alpha_loss+alpha_push
if (fits[TVAO_ALPHA] && ((alpha_loss > 0) || (alpha_push > 0))) { if (fits[TVAO_ALPHA] && ((alpha_loss > 0) || (alpha_push > 0))) {
int dbg_nx = -76340; int dbg_nx = -76340;
final int ind_y_alpha_loss = ind_next; final int ind_y_alpha_loss = ind_next;
...@@ -1679,7 +1787,7 @@ public class VegetationLMA { ...@@ -1679,7 +1787,7 @@ public class VegetationLMA {
double [] vector, double [] vector,
final double delta, final double delta,
final int debug_level) { final int debug_level) {
int dbg_n = -2486; int dbg_n = -2256; // 1698; // -2486;
double [][] jt = new double [vector.length][weights.length]; double [][] jt = new double [vector.length][weights.length];
for (int nv = 0; nv < vector.length; nv++) { for (int nv = 0; nv < vector.length; nv++) {
if (nv == dbg_n) { if (nv == dbg_n) {
...@@ -2698,6 +2806,9 @@ public class VegetationLMA { ...@@ -2698,6 +2806,9 @@ public class VegetationLMA {
if (Math.abs(jt_diff[n][w]) > max_err) { if (Math.abs(jt_diff[n][w]) > max_err) {
System.out.println("debugDerivs(): n="+n+", w = "+w +", diff="+jt_diff[n][w]); System.out.println("debugDerivs(): n="+n+", w = "+w +", diff="+jt_diff[n][w]);
} }
if (Math.abs(jt_diff[n][w]) > .1) {
System.out.println("debugDerivs(): n="+n+", w = "+w +", diff="+jt_diff[n][w]+" jt="+jt[n][w]+" jt_delta="+jt_delta[n][w]);
}
max_err = Math.max(max_err, Math.abs(jt_diff[n][w])); max_err = Math.max(max_err, Math.abs(jt_diff[n][w]));
} }
} }
...@@ -2714,47 +2825,71 @@ public class VegetationLMA { ...@@ -2714,47 +2825,71 @@ public class VegetationLMA {
private void setupWeights( // after setupParametersIndices private void setupWeights( // after setupParametersIndices
final double [] scene_weights, final double [] scene_weights_in,
final double reg_weights, final double reg_weights,
final double hifreq_weight) { final double hifreq_weight) {
boolean use_hf = (hifreq_weight > 0); boolean use_hf = (hifreq_weight > 0);
use_scenes_pull0 = (scenes_pull0 >=0);
// int extra_samples = num_pars_vegetation_alpha; // in the future may be more regularization // int extra_samples = num_pars_vegetation_alpha; // in the future may be more regularization
// int hf_samples = use_hf ? data_source.length : 0; // int hf_samples = use_hf ? data_source.length : 0;
int extra_samples = 0; int extra_samples = 0;
// using >=0 no use 0 as NOP but reserve space, <0 - do not reserve space // using >=0 no use 0 as NOP but reserve space, <0 - do not reserve space
//(alpha_loss > 0) //(alpha_loss > 0)
if (use_scenes_pull0) extra_samples += 1;
if ((alpha_loss > 0) || (alpha_push > 0)) extra_samples+= num_pars_alpha; // need to split loss (always positive) from alpha_lpf if ((alpha_loss > 0) || (alpha_push > 0)) extra_samples+= num_pars_alpha; // need to split loss (always positive) from alpha_lpf
if (alpha_lpf >= 0) extra_samples+= num_pars_alpha; if (alpha_lpf >= 0) extra_samples+= num_pars_alpha;
if (terr_lpf >= 0) extra_samples+= num_pars_terrain; if (terr_lpf >= 0) extra_samples+= num_pars_terrain;
if (veget_lpf >= 0) extra_samples+= num_pars_vegetation; if (veget_lpf >= 0) extra_samples+= num_pars_vegetation;
double reg_sample_weight = reg_weights/extra_samples; // weight of each regularization sample double reg_sample_weight = reg_weights/extra_samples; // weight of each regularization sample
final double [] sw = (scene_weights != null) ? scene_weights : new double [num_scenes]; if (scene_weights_in != null) {
if (scene_weights == null) { System.arraycopy(
Arrays.fill (sw, 1.0); scene_weights_in,
0,
scene_weights,
0,
num_scenes);
} else {
Arrays.fill (scene_weights, 1.0);
} }
// weights = new double [data_source.length + extra_samples]; // weights = new double [data_source.length + extra_samples];
weights = new double [y_vector.length + extra_samples]; weights = new double [y_vector.length + extra_samples];
double s = 0; double s = 0;
for (int ny = 0; ny < data_source.length; ny++) { for (int ny = 0; ny < data_source.length; ny++) {
int nscene = data_source[ny][DATA_SOURCE_HEAD][DATA_SOURCE_HEAD_SCENE]; int nscene = data_source[ny][DATA_SOURCE_HEAD][DATA_SOURCE_HEAD_SCENE];
s += sw[nscene]; if (data_source[ny][DATA_SOURCE_HEAD][DATA_SOURCE_HEAD_SINDEX] >=0) {
s += scene_weights[nscene];
}
} }
double s_scenes = s; // sum of all scene weight. Maybe skip scenes that do not exist?
if (use_hf) { // second pass, repeating for possible future modifications if (use_hf) { // second pass, repeating for possible future modifications
for (int ny = 0; ny < data_source.length; ny++) { for (int ny = 0; ny < data_source.length; ny++) {
int nscene = data_source[ny][DATA_SOURCE_HEAD][DATA_SOURCE_HEAD_SCENE]; int nscene = data_source[ny][DATA_SOURCE_HEAD][DATA_SOURCE_HEAD_SCENE];
s += sw[nscene] * hifreq_weight ; if (data_source[ny][DATA_SOURCE_HEAD][DATA_SOURCE_HEAD_SINDEX] >=0) {
s += scene_weights[nscene] * hifreq_weight ;
} }
} }
}
double s_pull_0 = s_scenes * scenes_pull0 * woi.width*woi.height;
final double s0 = s; final double s0 = s;
// final double s0 = s + s_pull_0;
s *= (1+ reg_weights); s *= (1+ reg_weights);
final double k = 1.0/s; final double k = 1.0/s;
weight_pure = s0/s; weight_pure = s0/s;
// scale_scenes_pull = scenes_pull0 * woi.width*woi.height / s_scenes; // or use extra_samples instead of woi.width*woi.height ?
scale_scenes_pull = scenes_pull0 * extra_samples / s_scenes; // or use extra_samples instead of woi.width*woi.height ?
//scale_scenes_pull = 0; // used in getFxDerivs to scale scene offsets as their weight will be reg_weights / extra_samples
// weight of pull0 will be 1/(3*woi area) * reg_weight
// in fX will be multiplied by scene_weight*scene_offset. should be additionally multiplied by scene_pull0 * (3*woi_area) / sum scene weights
// for (int i = 0; i < extra_samples; i++) { // for (int i = 0; i < extra_samples; i++) {
// s+=extra_weights; // s+=extra_weights;
// } // }
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) {
...@@ -2762,13 +2897,13 @@ public class VegetationLMA { ...@@ -2762,13 +2897,13 @@ public class VegetationLMA {
public void run() { public void run() {
for (int nw = ai.getAndIncrement(); nw < weights.length; nw = ai.getAndIncrement()) { for (int nw = ai.getAndIncrement(); nw < weights.length; nw = ai.getAndIncrement()) {
if (nw < data_source.length) { // DC differences if (nw < data_source.length) { // DC differences
weights[nw] = sw[data_source[nw][DATA_SOURCE_HEAD][DATA_SOURCE_HEAD_SCENE]] * k; weights[nw] = scene_weights[data_source[nw][DATA_SOURCE_HEAD][DATA_SOURCE_HEAD_SCENE]] * k;
if (Double.isNaN(weights[nw])) { if (Double.isNaN(weights[nw])) {
System.out.println("weights["+nw+"]=NaN"); System.out.println("weights["+nw+"]=NaN");
} }
} else if (nw < y_vector.length) { // HF differences if exist } else if (nw < y_vector.length) { // HF differences if exist
weights[nw] = sw[data_source[nw-data_source.length][DATA_SOURCE_HEAD][DATA_SOURCE_HEAD_SCENE]] * k * hifreq_weight; weights[nw] = scene_weights[data_source[nw-data_source.length][DATA_SOURCE_HEAD][DATA_SOURCE_HEAD_SCENE]] * k * hifreq_weight;
if (Double.isNaN(weights[nw])) { if (Double.isNaN(weights[nw])) {
System.out.println("weights["+nw+"]=NaN"); System.out.println("weights["+nw+"]=NaN");
} }
...@@ -2786,7 +2921,8 @@ public class VegetationLMA { ...@@ -2786,7 +2921,8 @@ public class VegetationLMA {
return; return;
} }
private void setupYVector(boolean use_hf) { private void setupYVector(
boolean use_hf) {
int ds_length = (use_hf? 2 : 1) * data_source.length; int ds_length = (use_hf? 2 : 1) * data_source.length;
y_vector = new double [ds_length]; y_vector = new double [ds_length];
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
...@@ -3013,7 +3149,7 @@ public class VegetationLMA { ...@@ -3013,7 +3149,7 @@ public class VegetationLMA {
used_scenes[nscene] = true; used_scenes[nscene] = true;
num_samples+= scene_samples[nscene]; num_samples+= scene_samples[nscene];
scene_samples[nscene] = num_prev; // start index scene_samples[nscene] = num_prev; // start index
if (nscene != vegetationModel.reference_index) { if (keepScene(nscene)) {
num_used_scenes++; num_used_scenes++;
} else { } else {
used_scene_indices[nscene] = -1; used_scene_indices[nscene] = -1;
...@@ -3293,7 +3429,8 @@ public class VegetationLMA { ...@@ -3293,7 +3429,8 @@ public class VegetationLMA {
private void setupParametersIndices( private void setupParametersIndices(
boolean [][] valid_woi) { // [0] - valid terrain pixels, [1] valid vegetation and alpha pixels; boolean [][] valid_woi, // [0] - valid terrain pixels, [1] valid vegetation and alpha pixels;
boolean all_terrain) {
par_index = new int [TVAO_TYPES][]; par_index = new int [TVAO_TYPES][];
par_index[TVAO_TERRAIN] = new int [image_length]; par_index[TVAO_TERRAIN] = new int [image_length];
par_index[TVAO_VEGETATION] = new int [image_length]; par_index[TVAO_VEGETATION] = new int [image_length];
...@@ -3327,8 +3464,8 @@ public class VegetationLMA { ...@@ -3327,8 +3464,8 @@ public class VegetationLMA {
for (int dcol = 0; dcol < woi.width; dcol++) { for (int dcol = 0; dcol < woi.width; dcol++) {
int col = woi.x + dcol; int col = woi.x + dcol;
int windx =dcol + drow * woi.width; int windx =dcol + drow * woi.width;
if (valid_woi[0][windx]) {
int indx = row*full.width + col; int indx = row*full.width + col;
if ((all_terrain && !Double.isNaN(tvao[TVAO_TERRAIN][indx])) || valid_woi[0][windx]) {
par_rindex[par_num][0] = TVAO_TERRAIN; par_rindex[par_num][0] = TVAO_TERRAIN;
par_rindex[par_num][1] = indx; par_rindex[par_num][1] = indx;
par_index[TVAO_TERRAIN][indx] = par_num++; par_index[TVAO_TERRAIN][indx] = par_num++;
...@@ -3411,7 +3548,7 @@ public class VegetationLMA { ...@@ -3411,7 +3548,7 @@ public class VegetationLMA {
int par_num = ind_pars_scenes; int par_num = ind_pars_scenes;
int [][] par_rindex = this.par_rindex; int [][] par_rindex = this.par_rindex;
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 (used_scenes[i] && !isReferenceScene(i)) { if (used_scenes[i] && keepScene(i)) {
par_rindex[par_num][0] = TVAO_SCENE_OFFSET; par_rindex[par_num][0] = TVAO_SCENE_OFFSET;
par_rindex[par_num][1] = i; par_rindex[par_num][1] = i;
par_index[TVAO_SCENE_OFFSET][i] = par_num++; par_index[TVAO_SCENE_OFFSET][i] = par_num++;
...@@ -3430,6 +3567,15 @@ public class VegetationLMA { ...@@ -3430,6 +3567,15 @@ public class VegetationLMA {
return vegetationModel.reference_index == scene; return vegetationModel.reference_index == scene;
} }
/**
* Keep scene as it is not a reference one or do not need to skip it
* @param scene
* @return
*/
private boolean keepScene(int scene) {
return !skip_ref_scene || !isReferenceScene(scene);
}
private boolean [][] filterValidWoi ( private boolean [][] filterValidWoi (
int min_scenes_uses, int min_scenes_uses,
int min_scenes_used, int min_scenes_used,
......
...@@ -19,6 +19,7 @@ import com.elphel.imagej.tileprocessor.QuadCLT; ...@@ -19,6 +19,7 @@ import com.elphel.imagej.tileprocessor.QuadCLT;
import com.elphel.imagej.tileprocessor.TileNeibs; import com.elphel.imagej.tileprocessor.TileNeibs;
import com.elphel.imagej.tileprocessor.TileProcessor; import com.elphel.imagej.tileprocessor.TileProcessor;
import ij.IJ;
import ij.ImagePlus; import ij.ImagePlus;
import ij.ImageStack; import ij.ImageStack;
import ij.io.FileSaver; import ij.io.FileSaver;
...@@ -63,8 +64,18 @@ public class VegetationModel { ...@@ -63,8 +64,18 @@ public class VegetationModel {
public double [][][] vegetation_warp = null; public double [][][] vegetation_warp = null;
public double [][][] vegetation_inv_warp = null;
public double [][][] vegetation_warp_md = null; // magnitude+direction public double [][][] vegetation_warp_md = null; // magnitude+direction
public double [][][] vegetation_inv_warp_md = null; // magnitude+direction
public double [] elevations= null;
public double [][][] scale_dirs= null;
public String [] scene_names = null; // TODO: Implement! public String [] scene_names = null; // TODO: Implement!
public boolean diff_mode = true; public boolean diff_mode = true;
public Rectangle full; public Rectangle full;
public boolean failed = false; public boolean failed = false;
...@@ -73,6 +84,11 @@ public class VegetationModel { ...@@ -73,6 +84,11 @@ public class VegetationModel {
public String reference_scene; // timestamp public String reference_scene; // timestamp
public int reference_index; // timestamp public int reference_index; // timestamp
// Source directory and title where this instance was read from to be able to write back more data
public String src_dir = null;
public String src_title = null;
public double [][] tva; public double [][] tva;
...@@ -85,12 +101,25 @@ public class VegetationModel { ...@@ -85,12 +101,25 @@ public class VegetationModel {
String title) { String title) {
int num_scenes = terrain_scenes_render.length; // == vegetation_warp.length int num_scenes = terrain_scenes_render.length; // == vegetation_warp.length
final int full_length = full.width*full.height; final int full_length = full.width*full.height;
String [] titles = new String[3*num_scenes + 2];
final int num_slices1 = num_scenes * 5 + 2;
final int num_slices2 = num_scenes * 7 + 2 + 1;
final boolean mode2 = (elevations != null) && (scale_dirs != null);
final int num_slices = mode2? num_slices2 : num_slices1;
// String [] titles = new String[5*num_scenes + 2]; //[3*num_scenes + 2];
String [] titles = new String[num_slices]; //[3*num_scenes + 2];
final double [][] data = new double [titles.length][]; final double [][] data = new double [titles.length][];
titles[0] = "terrain_accumulated"; titles[0] = "terrain_accumulated";
data[0] = terrain_average_render; data[0] = terrain_average_render;
titles[1] = "vegetation_accumulated"; titles[1] = "vegetation_accumulated";
data [1] = vegetation_average_render; data [1] = vegetation_average_render;
if (mode2) {
System.out.println("saveState(): writing in mode2 (with elevations and scales/directions).");
titles[num_slices1 + 0] = "elevations";
data [num_slices1 + 0] = elevations;
} else {
System.out.println("saveState(): writing mode1 (without elevations and scales/directions).");
}
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
for (int n = 0; n < num_scenes; n++) { for (int n = 0; n < num_scenes; n++) {
...@@ -101,6 +130,19 @@ public class VegetationModel { ...@@ -101,6 +130,19 @@ public class VegetationModel {
titles[fslice + 1] = "vegetation_warp_"+n+"_y"; titles[fslice + 1] = "vegetation_warp_"+n+"_y";
data [fslice + 0] = new double [full_length]; data [fslice + 0] = new double [full_length];
data [fslice + 1] = new double [full_length]; data [fslice + 1] = new double [full_length];
final int fslice_inv = 2 + 3*num_scenes + 2*n;
titles[fslice_inv + 0] = "vegetation_iwarp_"+n+"_x";
titles[fslice_inv + 1] = "vegetation_iwarp_"+n+"_y";
data [fslice_inv + 0] = new double [full_length];
data [fslice_inv + 1] = new double [full_length];
final int fslice2 = mode2 ? ( num_slices1 + 1 + n) : 0;
if (mode2) {
titles[fslice2 + 0] = "elevation_"+n+"_scale";
titles[fslice2 + num_scenes] = "elevation_"+n+"_direction";
data [fslice2 + 0] = new double [full_length];
data [fslice2 + num_scenes] = new double [full_length];
}
ai.set(0); ai.set(0);
final int fscene = n; final int fscene = n;
for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) {
...@@ -114,6 +156,22 @@ public class VegetationModel { ...@@ -114,6 +156,22 @@ public class VegetationModel {
data [fslice + 0][nPix] = vegetation_warp[fscene][nPix][0]; data [fslice + 0][nPix] = vegetation_warp[fscene][nPix][0];
data [fslice + 1][nPix] = vegetation_warp[fscene][nPix][1]; data [fslice + 1][nPix] = vegetation_warp[fscene][nPix][1];
} }
if (vegetation_inv_warp[fscene][nPix] == null) {
data [fslice_inv + 0][nPix] = Double.NaN;
data [fslice_inv + 1][nPix] = Double.NaN;
} else {
data [fslice_inv + 0][nPix] = vegetation_inv_warp[fscene][nPix][0];
data [fslice_inv + 1][nPix] = vegetation_inv_warp[fscene][nPix][1];
}
if (mode2) {
if (scale_dirs[fscene][nPix] == null) {
data [fslice2 + 0] [nPix] = Double.NaN;
data [fslice2 + num_scenes][nPix] = Double.NaN;
} else {
data [fslice2 + 0] [nPix] = scale_dirs[fscene][nPix][0];
data [fslice2 + num_scenes][nPix] = scale_dirs[fscene][nPix][1];
}
}
} }
} }
}; };
...@@ -136,7 +194,7 @@ public class VegetationModel { ...@@ -136,7 +194,7 @@ public class VegetationModel {
imp.setProperty("MODEL_TOP_DIRECTORY", ""+model_top_directory); imp.setProperty("MODEL_TOP_DIRECTORY", ""+model_top_directory);
imp.setProperty("REFERENCE_SCENE", ""+reference_scene); imp.setProperty("REFERENCE_SCENE", ""+reference_scene);
imp.setProperty("REFERENCE_INDEX", ""+reference_index); imp.setProperty("REFERENCE_INDEX", ""+reference_index);
imp.setProperty("NUM_SCENES", ""+num_scenes);
String path = VegetationLMA.getSavePath( String path = VegetationLMA.getSavePath(
...@@ -166,6 +224,8 @@ public class VegetationModel { ...@@ -166,6 +224,8 @@ public class VegetationModel {
dir, // String dir, dir, // String dir,
title, // String title) title, // String title)
TERRVEG_EXT); // String ext) { TERRVEG_EXT); // String ext) {
src_dir = dir; // to be able to write back more data
src_title = title; // to be able to write back more data
ImagePlus imp_pars = new ImagePlus (path); ImagePlus imp_pars = new ImagePlus (path);
if (imp_pars.getWidth()==0) { if (imp_pars.getWidth()==0) {
throw new IllegalArgumentException("VegetationModel(): Could not read "+path); throw new IllegalArgumentException("VegetationModel(): Could not read "+path);
...@@ -173,20 +233,42 @@ public class VegetationModel { ...@@ -173,20 +233,42 @@ public class VegetationModel {
int num_slices = imp_pars.getStack().getSize(); int num_slices = imp_pars.getStack().getSize();
JP46_Reader_camera.decodeProperiesFromInfo(imp_pars); JP46_Reader_camera.decodeProperiesFromInfo(imp_pars);
// imp.setProperty("NUM_SCENES", ""+num_scenes);
// if (imp_pars.getProperty("MODEL_DIRECTORY") != null) model_directory = (String) imp_pars.getProperty("MODEL_DIRECTORY");
full = new Rectangle ( full = new Rectangle (
Integer.parseInt((String) imp_pars.getProperty("FULL_X")), Integer.parseInt((String) imp_pars.getProperty("FULL_X")),
Integer.parseInt((String) imp_pars.getProperty("FULL_Y")), Integer.parseInt((String) imp_pars.getProperty("FULL_Y")),
Integer.parseInt((String) imp_pars.getProperty("FULL_WIDTH")), Integer.parseInt((String) imp_pars.getProperty("FULL_WIDTH")),
Integer.parseInt((String) imp_pars.getProperty("FULL_HEIGHT"))); Integer.parseInt((String) imp_pars.getProperty("FULL_HEIGHT")));
int file_num_scenes = -1;
final int num_scenes = (num_slices - 2) / 3; if (imp_pars.getProperty("NUM_SCENES") != null) file_num_scenes = Integer.parseInt((String) imp_pars.getProperty("NUM_SCENES"));
final int num_scenes = (file_num_scenes > 0)? file_num_scenes: ((num_slices - 2) / 5);
final int full_length = full.width*full.height; final int full_length = full.width*full.height;
int num_slices1 = num_scenes * 5 + 2;
int num_slices2 = num_scenes * 7 + 2 + 1;
boolean mode1 = num_slices == num_slices1;
boolean mode2 = num_slices == num_slices2;
if (mode2) {
System.out.println("VegetationModel(): reading in mode2 (with elevations and scales/directions).");
} else {
System.out.println("VegetationModel(): reading in mode1 (without elevations and scales/directions).");
}
if (!mode1 && ! mode2) {
throw new IllegalArgumentException("VegetationModel(): Wrong number of slices: expected "+num_slices1+
" or "+num_slices2+", got "+num_slices);
}
diff_mode = Boolean.parseBoolean((String) imp_pars.getProperty("DIFF_MODE")); diff_mode = Boolean.parseBoolean((String) imp_pars.getProperty("DIFF_MODE"));
terrain_scenes_render = new double [num_scenes][full_length]; terrain_scenes_render = new double [num_scenes][full_length];
terrain_average_render= new double [full_length]; terrain_average_render= new double [full_length];
vegetation_average_render= new double [full_length]; vegetation_average_render= new double [full_length];
vegetation_warp = new double [num_scenes][full_length][]; vegetation_warp = new double [num_scenes][full_length][];
vegetation_inv_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_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"); if (imp_pars.getProperty("MODEL_TOP_DIRECTORY") != null) model_top_directory = (String) imp_pars.getProperty("MODEL_TOP_DIRECTORY");
if (imp_pars.getProperty("REFERENCE_SCENE") != null) reference_scene = (String) imp_pars.getProperty("REFERENCE_SCENE"); if (imp_pars.getProperty("REFERENCE_SCENE") != null) reference_scene = (String) imp_pars.getProperty("REFERENCE_SCENE");
...@@ -232,6 +314,59 @@ public class VegetationModel { ...@@ -232,6 +314,59 @@ public class VegetationModel {
}; };
} }
ImageDtt.startAndJoin(threads); 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_inv_warp[n];
float [] pixels_x = (float[]) imp_pars.getStack().getPixels(2 + 3* num_scenes + 2 * n + 1);
float [] pixels_y = (float[]) imp_pars.getStack().getPixels(2 + 3* 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);
if (mode2) {
elevations= new double [full_length];
final float [] fpix_elev = (float[]) imp_pars.getStack().getPixels(2 + 5* num_scenes + 1);
ai.set(0);
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()) {
elevations[nPix] = fpix_elev[nPix];
}
}
};
}
ImageDtt.startAndJoin(threads);
scale_dirs = new double [num_scenes][full_length][];
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 = scale_dirs[n];
float [] pixels_scale = (float[]) imp_pars.getStack().getPixels(3 + 5* num_scenes + n + 1);
float [] pixels_dir = (float[]) imp_pars.getStack().getPixels(3 + 6* num_scenes + n + 1);
for (int i = 0; i < full_length; i++) {
if (!Float.isNaN(pixels_scale[i]) && !Float.isNaN(pixels_dir[i])) {
data[i] = new double [] {pixels_scale[i],pixels_dir[i]};
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
return; return;
} }
...@@ -459,34 +594,45 @@ public class VegetationModel { ...@@ -459,34 +594,45 @@ public class VegetationModel {
} }
double [][][] vegetation_inv = new double [num_scenes][][]; double [][][] vegetation_inv = new double [num_scenes][][];
double [][][] terrain_inv = new double [num_scenes][][];
full = new Rectangle(0,0,640,512); full = new Rectangle(0,0,640,512);
diff_mode = true; diff_mode = true;
boolean out_diff = diff_mode; boolean out_diff = diff_mode;
Rectangle out_window =full; Rectangle out_window =full;
int patch_min_neibs = 6; int patch_min_neibs = 6;
int [] pnum_patched = new int[1]; int [] pnum_patched_v = new int[1];
int [] pnum_patched_t = new int[1];
for (int nscene = 0; nscene < num_scenes; nscene++) { for (int nscene = 0; nscene < num_scenes; nscene++) {
if (nscene == dbg_scene) { if (nscene == dbg_scene) {
System.out.println("test_vegetation(): nscene="+nscene); System.out.println("test_vegetation(): nscene="+nscene);
} }
vegetation_inv[nscene] = invertMap( vegetation_inv[nscene] = invertMap( // used earlier
vegetation_pix[nscene], // final double [][] map_in, vegetation_pix[nscene], // final double [][] map_in,
tilesX*tileSize, // final int width, tilesX*tileSize, // final int width,
out_window, // final Rectangle out_window, out_window, // final Rectangle out_window,
true, // final boolean in_diff, true, // final boolean in_diff,
out_diff, // final boolean out_diff) out_diff, // final boolean out_diff)
patch_min_neibs, // final int patch_min_neibs) patch_min_neibs, // final int patch_min_neibs)
pnum_patched); // final int [] pnum_patched) pnum_patched_v); // final int [] pnum_patched)
terrain_inv[nscene] = invertMap( // added
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_t); // final int [] pnum_patched)
} }
/* */ /* */
double [][][] veg_to_terr = new double [num_scenes][][]; double [][][] veg_to_terr = new double [num_scenes][][];
double [][][] terr_to_veg = new double [num_scenes][][];
Rectangle window1 = new Rectangle(0,0,640,512); Rectangle window1 = new Rectangle(0,0,640,512);
Rectangle window2 = out_window; Rectangle window2 = out_window;
boolean map_diff1 = true; boolean map_diff1 = true;
boolean map_diff2 = out_diff; // true; boolean map_diff2 = out_diff; // true;
boolean map_diff_out = true; boolean map_diff_out = true;
for (int nscene = 0; nscene < num_scenes; nscene++) { for (int nscene = 0; nscene < num_scenes; nscene++) {
veg_to_terr[nscene] = combineMaps( veg_to_terr[nscene] = combineMaps( // used earlier
terrain_pix[nscene], // final double [][] map1, terrain_pix[nscene], // final double [][] map1,
window1, // final Rectangle window1, window1, // final Rectangle window1,
map_diff1, // final boolean map_diff1, map_diff1, // final boolean map_diff1,
...@@ -494,9 +640,18 @@ public class VegetationModel { ...@@ -494,9 +640,18 @@ public class VegetationModel {
window2, // final Rectangle window2, window2, // final Rectangle window2,
map_diff2, // final boolean map_diff2, map_diff2, // final boolean map_diff2,
map_diff_out); // final boolean map_diff_out) map_diff_out); // final boolean map_diff_out)
terr_to_veg[nscene] = combineMaps( // added for inverse
vegetation_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; vegetation_warp = veg_to_terr;
vegetation_inv_warp = terr_to_veg;
full = out_window; full = out_window;
/* USED */ /* USED */
...@@ -619,8 +774,14 @@ public class VegetationModel { ...@@ -619,8 +774,14 @@ public class VegetationModel {
/**
public static void test_vegetation( * Run from batch process for multi-scene sequences, prepare data for vegetation processing
* @param clt_parameters
* @param quadCLTs
* @param ref_index
* @param debugLevel
*/
public static void prepareVegetationData(
CLTParameters clt_parameters, CLTParameters clt_parameters,
QuadCLT [] quadCLTs, QuadCLT [] quadCLTs,
int ref_index, int ref_index,
...@@ -1097,7 +1258,7 @@ public class VegetationModel { ...@@ -1097,7 +1258,7 @@ public class VegetationModel {
public static void testVegetationLMA( public static void processVegetationLMA(
CLTParameters clt_parameters, CLTParameters clt_parameters,
boolean combine_segments) boolean combine_segments)
{ {
...@@ -1107,10 +1268,12 @@ public class VegetationModel { ...@@ -1107,10 +1268,12 @@ public class VegetationModel {
// Temporary , it is actually a model directory // 1697877487_245877-TERR-VEG-STATE.terrveg-tiff // 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_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"; // String model_state_file = "1697877487_245877-TERR-VEG-STATE";
if (model_state_file != null) { if (model_state_file == null) {
System.out.println("model_state_file==null, old test version removed" );
}
VegetationModel vegetationModel = new VegetationModel( VegetationModel vegetationModel = new VegetationModel(
model_directory, // String dir, model_directory, // String dir,
model_state_file); // String title) model_state_file); // String title)
...@@ -1118,95 +1281,12 @@ public class VegetationModel { ...@@ -1118,95 +1281,12 @@ public class VegetationModel {
combine_segments, // boolean combine_segments, combine_segments, // boolean combine_segments,
clt_parameters, // CLTParameters clt_parameters, clt_parameters, // CLTParameters clt_parameters,
-1); // int debugLevel) { -1); // int debugLevel) {
return;
} }
// old version below
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( public static void unsharpMaskMulti(
final double [][] data, final double [][] data,
...@@ -1270,358 +1350,6 @@ public class VegetationModel { ...@@ -1270,358 +1350,6 @@ public class VegetationModel {
} }
} }
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
boolean start_warm_veget = clt_parameters.imp.terr_warm_veget; // start with vegetation warmer than terrain
double terrain_warmest = clt_parameters.imp.terr_warmest; // pull vegetations to warm, terrain to cold
double initial_split = clt_parameters.imp.terr_initial_split; // pull vegetations to warm, terrain to cold
double min_split_frac = clt_parameters.imp.terr_min_split_frac;// 0.15;
double terr_difference = clt_parameters.imp.terr_difference; // Pull vegetation to be this warmer
double terr_pull_cold = clt_parameters.imp.terr_pull_cold; // pull vegetations to warm, terrain to cold
double default_alpha = 0.5; // 0.8;
double hifreq_weight = 22.5; // 0 - do not use high-freq. Relative weight of laplacian components
boolean fit_terr = clt_parameters.imp.terr_fit_terr; // true; // adjust terrain pixels
boolean fit_veget = clt_parameters.imp.terr_fit_veget; // true; // adjust vegetation pixels
boolean fit_alpha = clt_parameters.imp.terr_fit_alpha; // true; // adjust vegetation alpha pixels
boolean fit_scenes = clt_parameters.imp.terr_fit_scenes; // true; // adjust scene offsets (start from 0 always?)
boolean fit_elevations = clt_parameters.imp.terr_fit_elevations; // false; // adjust elevation pixels (not yet implemented)
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
boolean alpha_en_holes = true;
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 show_final_result = true;
// 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,
start_warm_veget, // final boolean start_warm_veget, // start with vegetation warmer than terrain
terrain_warmest, // final double terrain_warmest, // warmest terrain (above is initially vegetation)
initial_split, // final double initial_split, // initial alpha: terrain 0.0+, vegetation 1.0-.
min_split_frac, // final double min_frac, // minimal modality fraction to use split by temperature
terr_difference, // final double terr_difference, // pull vegetation to be this warmer
terr_pull_cold, // final double terr_pull_cold, // pull vegetations to warm, terrain to cold
default_alpha, // final double default_alpha,
hifreq_weight, //final double hifreq_weight, // 22.5 0 - do not use high-freq. Relative weight of laplacian components
fit_terr, // final boolean adjust_terr,
fit_veget, // final boolean adjust_veget,
fit_alpha, // final boolean adjust_alpha,
fit_scenes, // final boolean adjust_scenes,
fit_elevations, // final boolean adjust_elevations,
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_en_holes, // final boolean alpha_en_holes, // Search for small semi-transparent holes, disable diffusion of local alpha minimums
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;
}
}
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 (show_final_result) {
vegetationLMA.showYfX(
null, // double [] vector,
"reconstructed_model_adjusted"); // String title)
}
}
return; //
}
public void testVegetationLMA( public void testVegetationLMA(
boolean combine_segments, boolean combine_segments,
CLTParameters clt_parameters, CLTParameters clt_parameters,
...@@ -1665,6 +1393,7 @@ public class VegetationModel { ...@@ -1665,6 +1393,7 @@ public class VegetationModel {
double terr_difference = clt_parameters.imp.terr_difference; // Pull vegetation to be this warmer double terr_difference = clt_parameters.imp.terr_difference; // Pull vegetation to be this warmer
double terr_pull_cold = clt_parameters.imp.terr_pull_cold; // pull vegetations to warm, terrain to cold double terr_pull_cold = clt_parameters.imp.terr_pull_cold; // pull vegetations to warm, terrain to cold
double alpha_initial_contrast = clt_parameters.imp.terr_alpha_contrast; // initial alpha contrast (>=1.0)
double default_alpha = clt_parameters.imp.terr_alpha_dflt; // 0.5; // 0.8; double default_alpha = clt_parameters.imp.terr_alpha_dflt; // 0.5; // 0.8;
double alpha_loss = clt_parameters.imp.terr_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_loss = clt_parameters.imp.terr_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 = clt_parameters.imp.terr_alpha_offset; // 0.0; // 0.02; // 0.03; // if >0, start losses above 0.0 and below 1.0; double alpha_offset = clt_parameters.imp.terr_alpha_offset; // 0.0; // 0.02; // 0.03; // if >0, start losses above 0.0 and below 1.0;
...@@ -1680,6 +1409,7 @@ public class VegetationModel { ...@@ -1680,6 +1409,7 @@ public class VegetationModel {
double veget_lpf = clt_parameters.imp.terr_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 veget_lpf = clt_parameters.imp.terr_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 = clt_parameters.imp.terr_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 terr_pull0 = clt_parameters.imp.terr_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 = clt_parameters.imp.terr_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 veget_pull0 = clt_parameters.imp.terr_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 scenes_pull0 = clt_parameters.imp.terr_scenes_pull0; // 1.0
// LMA parameters // LMA parameters
double boost_parallax = clt_parameters.imp.terr_boost_parallax; // 3.0; /// 1.0; /////// 5.0; /// 1.0; // 5; double boost_parallax = clt_parameters.imp.terr_boost_parallax; // 3.0; /// 1.0; /////// 5.0; /// 1.0; // 5;
...@@ -1791,6 +1521,7 @@ public class VegetationModel { ...@@ -1791,6 +1521,7 @@ public class VegetationModel {
} }
} }
double [][] initial_terrain_vegetation = getInitialTerrainVegetation( double [][] initial_terrain_vegetation = getInitialTerrainVegetation(
terrain_average_render, // double [] terrain_average_zeros, terrain_average_render, // double [] terrain_average_zeros,
vegetation_average_render, // double [] vegetation_average_zeros, vegetation_average_render, // double [] vegetation_average_zeros,
...@@ -1802,7 +1533,7 @@ public class VegetationModel { ...@@ -1802,7 +1533,7 @@ public class VegetationModel {
filter_veget, //int filter_vegetation) // shrink+grow filtered vegetation to remove small clusters filter_veget, //int filter_vegetation) // shrink+grow filtered vegetation to remove small clusters
100); // final int extra_pull_vegetation){ 100); // final int extra_pull_vegetation){
if (debugLevel > -2){ if (debugLevel > 3) { // -2){
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
initial_terrain_vegetation, initial_terrain_vegetation,
full.width, full.width,
...@@ -1825,7 +1556,6 @@ public class VegetationModel { ...@@ -1825,7 +1556,6 @@ public class VegetationModel {
nan_grow); // final int grow) nan_grow); // final int grow)
// maybe it is better to set NaN before UM and then use UM with fillNaN // maybe it is better to set NaN before UM and then use UM with fillNaN
...@@ -1842,15 +1572,213 @@ public class VegetationModel { ...@@ -1842,15 +1572,213 @@ public class VegetationModel {
} }
double dir_sigma = 16; double dir_sigma = 16;
/*
vegetation_warp_md = new double [vegetation_warp.length][][];
for (int nscene = 0; nscene < vegetation_warp.length; nscene++) {
// if (nscene == reference_index) {
// vegetation_warp_md[nscene] = new double [full.width * full.height][];
// } else {
boolean after_ref = (nscene > reference_index);
vegetation_warp_md[nscene ]= warpMagnitudeDirection(
vegetation_warp[nscene], // final double [][] warp_dxy,
full.width, // final int width,
dir_sigma, // final double dir_sigma,// Gaussian blur sigma to smooth direction variations
after_ref); // final boolean after_ref);
// }
}
vegetation_inv_warp_md = new double [vegetation_warp.length][][];
for (int nscene = 0; nscene < vegetation_warp.length; nscene++) {
// if (nscene == reference_index) {
// vegetation_inv_warp_md[nscene] = new double [full.width * full.height][];
// } else {
boolean after_ref = (nscene > reference_index);
vegetation_inv_warp_md[nscene ]= warpMagnitudeDirection(
vegetation_inv_warp[nscene], // final double [][] warp_dxy,
full.width, // final int width,
dir_sigma, // final double dir_sigma,// Gaussian blur sigma to smooth direction variations
after_ref); // final boolean after_ref);
// }
}
*/
// TODO: remove some of the above
if ((elevations == null) || (scale_dirs == null)){
// boolean use_min = false;
int reliable_shrink = 30;
boolean [][] reliable_scene_pix = farFromNan(
terrain_scenes_render, // final double [][] data,
full.width, // final int width,
reliable_shrink); // final int shrink)
double [] max_offsets = getScenesOverlap(
vegetation_inv_warp_md, // final double [][][] mag_dirs,
reliable_scene_pix, // final boolean [][] reliable, // or null
false, // final boolean use_min,
0, // final int start_scene,
vegetation_inv_warp_md.length); // final int endplus1_scene)
double [] min_offsets = getScenesOverlap(
vegetation_inv_warp_md, // final double [][][] mag_dirs,
reliable_scene_pix, // final boolean [][] reliable, // or null
true, // final boolean use_min,
0, // final int start_scene,
vegetation_inv_warp_md.length); // final int endplus1_scene)
ShowDoubleFloatArrays.showArrays(
new double [][] {max_offsets, min_offsets},
full.width,
full.height,
true,
reference_scene+"-max_min_offsets.tiff",
new String[] {"max_offsets", "min_offsets"});
int elevations1_grow = 20; // 64
double dir_sigma_scales = 128; // 8; //
int radius_outliers = 8; // 8;
double min_frac = 0.02; // 0.2; // minimal fraction of the full square to keep (0.25 for the corners
double remove_frac_hi = 0.25; // 0.2;
double remove_frac_lo = 0.25; // 0.2; // total,
boolean debug_enhance_elevations = true;
double min_elevation = 2.0; // for scales - use only elevations avove this.
// double [][] elevation_scales = new double[vegetation_inv_warp_md.length][];
double [][][] elevation_scale_dirs = new double[vegetation_inv_warp_md.length][][];
double [] elevations = enhanceElevations(
max_offsets, // final double [] elevations,
vegetation_inv_warp_md, // final double [][][] mag_dirs,
reliable_scene_pix, // final boolean [][] reliable, // or null
full.width, // final int width,
elevations1_grow, // final int grow,
min_elevation, // final double min_elevation,
dir_sigma_scales, // final double dir_sigma,// Gaussian blur sigma to smooth direction variations
radius_outliers, // final int radius,
min_frac, // final double min_frac, // minimal fraction of the full square to keep (0.25 for the corners
remove_frac_hi, // final double remove_frac_hi,
remove_frac_lo, // final double remove_frac_lo, // total,
elevation_scale_dirs, // final double [][] elevation_scale_dirs,
debug_enhance_elevations);
this.elevations = elevations;
this.scale_dirs = elevation_scale_dirs;
/*
double [] elevations2 = enhanceElevations(
elevations, // final double [] elevations,
vegetation_inv_warp_md, // final double [][][] mag_dirs,
reliable_scene_pix, // final boolean [][] reliable, // or null
full.width, // final int width,
elevations1_grow, // final int grow,
min_elevation, // final double min_elevation,
dir_sigma_scales, // final double dir_sigma,// Gaussian blur sigma to smooth direction variations
radius_outliers, // final int radius,
min_frac, // final double min_frac, // minimal fraction of the full square to keep (0.25 for the corners
remove_frac_hi, // final double remove_frac_hi,
remove_frac_lo, // final double remove_frac_lo, // total,
elevation_scales, // final double [][] elevation_scales,
debug_enhance_elevations);
double [] elevations3 = enhanceElevations(
elevations2, // final double [] elevations,
vegetation_inv_warp_md, // final double [][][] mag_dirs,
reliable_scene_pix, // final boolean [][] reliable, // or null
full.width, // final int width,
elevations1_grow, // final int grow,
min_elevation, // final double min_elevation,
dir_sigma_scales, // final double dir_sigma,// Gaussian blur sigma to smooth direction variations
radius_outliers, // final int radius,
min_frac, // final double min_frac, // minimal fraction of the full square to keep (0.25 for the corners
remove_frac_hi, // final double remove_frac_hi,
remove_frac_lo, // final double remove_frac_lo, // total,
elevation_scales, // final double [][] elevation_scales,
debug_enhance_elevations);
double [] elevations4 = enhanceElevations(
elevations3, // final double [] elevations,
vegetation_inv_warp_md, // final double [][][] mag_dirs,
reliable_scene_pix, // final boolean [][] reliable, // or null
full.width, // final int width,
elevations1_grow, // final int grow,
min_elevation, // final double min_elevation,
dir_sigma_scales, // final double dir_sigma,// Gaussian blur sigma to smooth direction variations
radius_outliers, // final int radius,
min_frac, // final double min_frac, // minimal fraction of the full square to keep (0.25 for the corners
remove_frac_hi, // final double remove_frac_hi,
remove_frac_lo, // final double remove_frac_lo, // total,
elevation_scales, // final double [][] elevation_scales,
debug_enhance_elevations);
// final boolean debug)
*
*/
//
if (debugLevel > -2) {
ShowDoubleFloatArrays.showArrays(
new double [][] {max_offsets, elevations},// elevations2, elevations3, elevations4},
full.width,
full.height,
true,
reference_scene+"-elevations_enhanced.tiff",
new String[] {"max_offsets", "enhanced"});//, "enhanced2", "enhanced3", "enhanced4"});
int num_pixels = full.width*full.height;
int num_scenes = vegetation_inv_warp_md.length;
String [] compare_titles = {"direction","offsets","simulated_offsets","offset_difference"};
double [][][] compare_offsets = new double [compare_titles.length][num_scenes][num_pixels];
for (int nscene = 0; nscene < vegetation_inv_warp_md.length; nscene ++) {
for (int n = 0; n < compare_offsets.length; n++) {
Arrays.fill(compare_offsets[n][nscene], Double.NaN);
}
for (int npix = 0; npix < num_pixels; npix++) {
if (vegetation_inv_warp_md[nscene][npix] != null) {
// compare_offsets[0][nscene][npix] = vegetation_inv_warp_md[nscene][npix][1]; // direction
compare_offsets[1][nscene][npix] = vegetation_inv_warp_md[nscene][npix][0];
}
// if (!Double.isNaN(elevation_scales[nscene][npix])) {
if (elevation_scale_dirs[nscene][npix] != null) {
compare_offsets[0][nscene][npix] = elevation_scale_dirs[nscene][npix][1]; // direction
compare_offsets[2][nscene][npix] = elevation_scale_dirs[nscene][npix][0] * elevations[npix];
}
compare_offsets[3][nscene][npix] = compare_offsets[2][nscene][npix]-compare_offsets[1][nscene][npix];
}
}
ShowDoubleFloatArrays.showArraysHyperstack(
compare_offsets, // double[][][] pixels,
full.width, // int width,
reference_scene+"-compare_offsets.tiff", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
scene_names, // String [] titles, // all slices*frames titles or just slice titles or null
compare_titles, // String [] frame_titles, // frame titles or null
true); // boolean show)
}
// if ((debugLevel > 3) || um_en) {
if (debugLevel > 3) { //-2) {
// probably will not use these, but as optional
vegetation_warp_md = new double [vegetation_warp.length][][];
for (int nscene = 0; nscene < vegetation_warp.length; nscene++) { for (int nscene = 0; nscene < vegetation_warp.length; nscene++) {
// if (nscene == reference_index) {
// vegetation_warp_md[nscene] = new double [full.width * full.height][];
// } else {
boolean after_ref = (nscene > reference_index);
vegetation_warp_md[nscene ]= warpMagnitudeDirection( vegetation_warp_md[nscene ]= warpMagnitudeDirection(
vegetation_warp[nscene], // final double [][] warp_dxy, vegetation_warp[nscene], // final double [][] warp_dxy,
full.width, // final int width, full.width, // final int width,
dir_sigma ); // final double dir_sigma,// Gaussian blur sigma to smooth direction variations dir_sigma, // final double dir_sigma,// Gaussian blur sigma to smooth direction variations
after_ref); // final boolean after_ref);
// }
}
vegetation_inv_warp_md = new double [vegetation_warp.length][][];
for (int nscene = 0; nscene < vegetation_warp.length; nscene++) {
// if (nscene == reference_index) {
// vegetation_inv_warp_md[nscene] = new double [full.width * full.height][];
// } else {
boolean after_ref = (nscene > reference_index);
vegetation_inv_warp_md[nscene ]= warpMagnitudeDirection(
vegetation_inv_warp[nscene], // final double [][] warp_dxy,
full.width, // final int width,
dir_sigma, // final double dir_sigma,// Gaussian blur sigma to smooth direction variations
after_ref); // final boolean after_ref);
// }
} }
if ((debugLevel > 3) || um_en) { double [][][] dbg_img = new double[12][vegetation_warp.length][vegetation_warp[0].length];
double [][][] dbg_img = new double[6][vegetation_warp.length][vegetation_warp[0].length];
for (int n = 0; n < dbg_img.length; n++) { for (int n = 0; n < dbg_img.length; n++) {
for (int nscene = 0; nscene < vegetation_warp.length; nscene++) { for (int nscene = 0; nscene < vegetation_warp.length; nscene++) {
Arrays.fill(dbg_img[n][nscene], Double.NaN); Arrays.fill(dbg_img[n][nscene], Double.NaN);
...@@ -1870,6 +1798,21 @@ public class VegetationModel { ...@@ -1870,6 +1798,21 @@ public class VegetationModel {
dbg_img[4][nscene][npix] = vegetation_warp_md[nscene][npix][0]; // magnitude dbg_img[4][nscene][npix] = vegetation_warp_md[nscene][npix][0]; // magnitude
dbg_img[5][nscene][npix] = vegetation_warp_md[nscene][npix][1]; // direction dbg_img[5][nscene][npix] = vegetation_warp_md[nscene][npix][1]; // direction
} }
if (vegetation_inv_warp[nscene][npix] != null) {
double dx =vegetation_inv_warp[nscene][npix][0];
double dy =vegetation_inv_warp[nscene][npix][1];
dbg_img[6][nscene][npix] = Math.sqrt(dx*dx + dy*dy);
dbg_img[7][nscene][npix] = Math.atan2(dy, dx);
dbg_img[8][nscene][npix] = dx;
dbg_img[9][nscene][npix] = dy;
}
if (vegetation_inv_warp_md[nscene][npix] != null) {
dbg_img[10][nscene][npix] = vegetation_inv_warp_md[nscene][npix][0]; // magnitude
dbg_img[11][nscene][npix] = vegetation_inv_warp_md[nscene][npix][1]; // direction
}
} }
} }
...@@ -1878,7 +1821,7 @@ public class VegetationModel { ...@@ -1878,7 +1821,7 @@ public class VegetationModel {
full.width, // int width, full.width, // int width,
reference_scene+"-vegetation_offsets.tiff", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy, reference_scene+"-vegetation_offsets.tiff", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
scene_names, // 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","angle","dx","dy","mag","dir"}, // String [] frame_titles, // frame titles or null new String[] {"dist","angle","dx","dy","mag","dir","inv-dist","inv-angle","inv-dx","inv-dy","inv-mag","inv-dir"}, // String [] frame_titles, // frame titles or null
true); // boolean show) true); // boolean show)
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
...@@ -1890,19 +1833,50 @@ public class VegetationModel { ...@@ -1890,19 +1833,50 @@ public class VegetationModel {
scene_names); scene_names);
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
new double [][] {terrain_average_render,vegetation_average_render}, new double [][] {terrain_average_render,vegetation_average_render},
full.width,
full.height,
true,
reference_scene+"-terrain_vegetation_averages.tiff",
new String[] {"terrain","vegetation"});
}
if ((src_dir != null) && (src_title != null)) {
System.out.println("Saving augmented data to model directory "+src_dir); //
saveState(
src_dir, // String dir,
src_title); // String title)
}
} // if ((elevations == null) || (scale_dirs == null)){
// directions should not be averaged over scenes as the flight direction may change
// if (debugLevel < 1000) {
// return; //
// }
initial_transparent = initial_split;
initial_opaque = 1.0 - initial_split;
VegetationLMA vegetationLMA = new VegetationLMA (
this,
alpha_initial_contrast); // double alpha_initial_contrast)
if (debugLevel > -2) {
double [][] dbg_img = {
vegetationLMA.tvao[VegetationLMA.TVAO_TERRAIN],
vegetationLMA.tvao[VegetationLMA.TVAO_VEGETATION],
vegetationLMA.tvao[VegetationLMA.TVAO_ALPHA]};
ShowDoubleFloatArrays.showArrays(
dbg_img,
full.width, full.width,
full.height, full.height,
true, true,
reference_scene+"-terrain_vegetation_averages.tiff", reference_scene+"-terrain_vegetation_alpha.tiff",
new String[] {"terrain","vegetation"}); new String[] {"terrain", "vegetation", "alpha"});
} }
initial_transparent = initial_split;
initial_opaque = 1.0 - initial_split;
VegetationLMA vegetationLMA = new VegetationLMA (this);
if (run_combine) { if (run_combine) {
...@@ -1975,6 +1949,7 @@ public class VegetationModel { ...@@ -1975,6 +1949,7 @@ public class VegetationModel {
veget_lpf, // final double veget_lpf, // pull vegetation to average of 4 neighbors (very small - maybe not needed) 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 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 veget_pull0, // final double veget_pull0, // pull vegetation to zero (makes sense with UM
scenes_pull0, // final double scenes_pull0,
boost_parallax,// final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene 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) 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_sigma, // final double um_sigma, // just use in debug image names
...@@ -2068,12 +2043,374 @@ public class VegetationModel { ...@@ -2068,12 +2043,374 @@ public class VegetationModel {
} }
return; // return; //
}
/*
public static double [] getInitialElevations(
final double [][] mag_dirs,
final int width) {
}
*/
public static boolean [] removeLocalOutliers(
final double [] data,
final int width,
final int radius,
final double min_frac, // minimal fraction of the full square to keep (0.25 for the corners
final double remove_frac_hi,
final double remove_frac_lo, // total,
final boolean nan_removed) { // make removed data NaN
final int num_pixels = data.length;
final int height = num_pixels/width;
final int size = radius*2+1;
final int area = size* size;
final int min_num = (int) Math.round(area * min_frac);
final boolean [] keep = new boolean [num_pixels];
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() {
TileNeibs tn = new TileNeibs(width, height);
public void run() {
for (int nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) if (!Double.isNaN(data[nPix])){
int num_below = 0, num_above=0, num=0;
double d = data[nPix];
for (int dy = -radius; dy <= radius; dy++) {
for (int dx = -radius; dx <= radius; dx++) {
int npix1 = tn.getNeibIndex(nPix, dx, dy);
if (npix1 >= 0) {
num++;
double d1 = data[npix1];
if (d1 >= d) num_above++; // equal should go to both
if (d1 <= d) num_below++; // equal should go to both
}
}
if ((num >= min_num) && (num_above >= num*remove_frac_hi) && (num_below >= num * remove_frac_lo)){
keep[nPix] = true;
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (nan_removed) {
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) if (!keep[nPix]){
data[nPix] = Double.NaN;
}
}
};
}
ImageDtt.startAndJoin(threads);
}
return keep;
}
public static double [] enhanceElevations(
final double [] elevations,
final double [][][] mag_dirs,
final boolean [][] reliable, // or null
final int width,
final int grow,
final double min_elevation,
final double dir_sigma,// Gaussian blur sigma to smooth direction variations
final int radius,
final double min_frac, // minimal fraction of the full square to keep (0.25 for the corners
final double remove_frac_hi,
final double remove_frac_lo, // total,
final double [][][] elevation_scale_dirs,
final boolean debug) {
final int num_scenes = mag_dirs.length;
final int num_pixels = elevations.length;
final String [] titles_top = {"scales","outliers_removed","ext_scales", "smooth_scales"};
final String [] titles_scene = debug? new String[num_scenes]:null;
if (titles_scene != null) {
for (int nscene = 0; nscene < num_scenes; nscene++) {
titles_scene[nscene] = "scene_"+nscene;
}
}
final double [][][] dbg_img = debug? new double [titles_top.length][num_scenes][] : null;
final double [][] scales = new double [num_scenes][num_pixels];
for (int nscene = 0; nscene < num_scenes; nscene++) {
Arrays.fill(scales[nscene], Double.NaN);
}
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 nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) if (!Double.isNaN(elevations[nPix])){
for (int nscene = 0; nscene < num_scenes; nscene++) if (mag_dirs[nscene][nPix] != null){
if ((reliable == null) || reliable[nscene][nPix]) {
if (elevations[nPix] > min_elevation) {
scales[nscene][nPix] = mag_dirs[nscene][nPix][0] / elevations[nPix];
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (dbg_img != null) {
for (int nscene = 0; nscene < num_scenes; nscene++) if (scales[nscene] != null){
dbg_img[0][nscene] = scales[nscene].clone();
}
}
if ((grow > 0) || (radius > 0)) {
for (int nscene = 0; nscene < num_scenes; nscene++) if (scales[nscene] != null){
removeLocalOutliers(
scales[nscene], // final double [] data,
width, // final int width,
radius, // final int radius,
min_frac, // final double min_frac, // minimal fraction of the full square to keep (0.25 for the corners
remove_frac_hi, // final double remove_frac_hi,
remove_frac_lo, // final double remove_frac_lo, // total,
true); // final boolean nan_removed) { // make removed data NaN
if (dbg_img != null) {
dbg_img[1][nscene] = scales[nscene].clone();
}
scales[nscene] = TileProcessor.fillNaNs(
scales[nscene], // final double [] data,
null, // final boolean [] prohibit,
width, // int width,
// CAREFUL ! Remaining NaN is grown by unsharp mask filter ************* !
grow, // 100, // 2*width, // 16, // final int grow,
0.7, // double diagonal_weight, // relative to ortho
100, // int num_passes,
0.03); // final double max_rchange, // = 0.01 - does not need to be accurate
if (debug) {
System.out.println("enhanceElevations() nscene="+nscene);
}
}
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nScene = ai.getAndIncrement(); nScene < num_scenes; nScene = ai.getAndIncrement()){
double sw = 0, swd = 0;
for (int npix=0;npix < num_pixels; npix++) if (!Double.isNaN(scales[nScene][npix])) {
sw+=1.0;
swd += scales[nScene][npix];
}
double mean = swd/sw;
for (int npix=0;npix < num_pixels; npix++) if (Double.isNaN(scales[nScene][npix])) {
scales[nScene][npix] = mean;
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (debug) {
System.out.println("enhanceElevations() Grow done.");
}
}
if (dbg_img != null) {
for (int nscene = 0; nscene < num_scenes; nscene++) if (scales[nscene] != null){
dbg_img[2][nscene] = scales[nscene].clone();
}
}
if (dir_sigma > 0) {
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nScene = ai.getAndIncrement(); nScene < num_scenes; nScene = ai.getAndIncrement()){
(new DoubleGaussianBlur()).blurDouble(
scales[nScene], //
width,
num_pixels/width,
dir_sigma, // double sigmaX,
dir_sigma, // double sigmaY,
0.01); // double accuracy)
}
}
};
}
ImageDtt.startAndJoin(threads);
if (debug) {
System.out.println("enhanceElevations() GB done.");
}
}
if (dbg_img != null) {
for (int nscene = 0; nscene < num_scenes; nscene++) if (scales[nscene] != null){
dbg_img[3][nscene] = scales[nscene].clone();
}
}
if (dbg_img != null) {
ShowDoubleFloatArrays.showArraysHyperstack(
dbg_img, // double[][][] pixels,
width, // int width,
"scene_scales.tiff", // "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_top, // String [] frame_titles, // frame titles or null
true); // boolean show)
System.out.println("enhanceElevations() shown.");
} }
public static double [][] warpMagnitudeDirection( final double [] sum_offs= new double[num_pixels];
final double [] sum_scales= new double[num_pixels];
final double [] elevations_out= new double[num_pixels];
Arrays.fill(elevations_out, Double.NaN);
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()){
for (int nscene = 0; nscene < num_scenes; nscene++) { // if (mag_dirs[nscene][nPix] != null){
double s = scales[nscene][nPix];
if (mag_dirs[nscene][nPix] != null){
if (s > 0) {
sum_scales[nPix] += s;
sum_offs[nPix] += mag_dirs[nscene][nPix][0];
} else if (s < 0) {
sum_scales[nPix] -= s;
sum_offs[nPix] -= mag_dirs[nscene][nPix][0];
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()){
for (int nscene = 0; nscene < num_scenes; nscene++) if (sum_scales[nPix] > 0) {
elevations_out[nPix] = sum_offs[nPix]/sum_scales[nPix];
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (elevation_scale_dirs != null) {
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nScene = ai.getAndIncrement(); nScene < num_scenes; nScene = ai.getAndIncrement()){
elevation_scale_dirs[nScene] = new double[num_pixels][];
for (int npix = 0; npix < num_pixels; npix++) if ((mag_dirs[nScene][npix] != null) &&( !Double.isNaN(scales[nScene][npix]))) {
elevation_scale_dirs[nScene][npix] = new double [] {scales[nScene][npix],mag_dirs[nScene][npix][1]};
}
}
}
};
}
ImageDtt.startAndJoin(threads);
// System.arraycopy(scales, 0, elevation_scales, 0, num_scenes);
}
// IJ.getNumber("Any number", 0);
return elevations_out;
}
public static double [] getScenesOverlap(
final double [][][] mag_dirs,
final boolean [][] reliable, // or null
final boolean use_min,
final int start_scene,
final int endplus1_scene) {
final int num_scenes = mag_dirs.length;
final int num_pixels = mag_dirs[start_scene].length;
final double [] max_offset = new double [num_pixels];
Arrays.fill(max_offset, Double.NaN);
final AtomicInteger [] anum_max = new AtomicInteger[num_scenes];
for (int nscene = 0; nscene < num_scenes; nscene++) {
anum_max[nscene] = new AtomicInteger(0);
}
final int scene0 = Math.max(0, start_scene);
final int scene1 = Math.min(num_scenes, endplus1_scene);
final boolean [] in_all_scenes = new boolean [num_pixels];
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 nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) {
int scene_max = -1;
double mx = 0;
look_all: {
for (int nscene = scene0; nscene < scene1; nscene++) {
if ((mag_dirs[nscene]== null) || (mag_dirs[nscene][nPix] == null)) {
break look_all;
}
if ((reliable != null) && !reliable[nscene][nPix]) {
break look_all;
}
double d = mag_dirs[nscene][nPix][0]; // magnitude, may be negative
if (use_min) {
d = -d;
}
if (d > mx) {
mx = d;
scene_max = nscene;
}
}
if (scene_max >= 0) {
anum_max[scene_max].getAndIncrement();
}
in_all_scenes[nPix] = true;
}
}
}
};
}
ImageDtt.startAndJoin(threads);
int nmax = 0;
int scene_max = -1;
for (int nscene = scene0; nscene < scene1; nscene++) {
if (anum_max[nscene].get() > nmax) {
nmax = anum_max[nscene].get();
scene_max = nscene;
}
}
final int fscene_max = scene_max;
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) if (in_all_scenes[nPix]){
max_offset[nPix] = mag_dirs[fscene_max][nPix][0];
}
}
};
}
ImageDtt.startAndJoin(threads);
return max_offset;
}
public static double [][] warpMagnitudeDirection(
final double [][] warp_dxy, final double [][] warp_dxy,
final int width, final int width,
final double dir_sigma){// Gaussian blur sigma to smooth direction variations final double dir_sigma,// Gaussian blur sigma to smooth direction variations
final boolean after_ref){
// Assuming objects have positive elevation, so dx, dy sign does not change // Assuming objects have positive elevation, so dx, dy sign does not change
final int num_pixels = warp_dxy.length; final int num_pixels = warp_dxy.length;
final double [][] warp_md = new double [warp_dxy.length][]; final double [][] warp_md = new double [warp_dxy.length][];
...@@ -2107,7 +2444,7 @@ public static double [][] warpMagnitudeDirection( ...@@ -2107,7 +2444,7 @@ public static double [][] warpMagnitudeDirection(
} }
final double avg_dir = Math.atan2(sdy, sdx); // average angle to avoid crossing full rotation final double avg_dir = Math.atan2(sdy, sdx); // average angle to avoid crossing full rotation
final double [] mags = new double[num_pixels], dirs = new double[num_pixels], mag_dirs=new double[num_pixels]; final double [] mags = new double[num_pixels], dirs = new double[num_pixels], mag_dirs=new double[num_pixels];
// Arrays.fill(dirs, Double.NaN); // Arrays.fill(dirs, Double.NaN);
ai.set(0); ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() { threads[ithread] = new Thread() {
...@@ -2116,6 +2453,7 @@ public static double [][] warpMagnitudeDirection( ...@@ -2116,6 +2453,7 @@ public static double [][] warpMagnitudeDirection(
double [] dxy = warp_dxy[nPix]; double [] dxy = warp_dxy[nPix];
if (dxy != null) { if (dxy != null) {
double m = Math.sqrt(dxy[0]*dxy[0]+dxy[1]*dxy[1]); double m = Math.sqrt(dxy[0]*dxy[0]+dxy[1]*dxy[1]);
if (!Double.isNaN(m)) {
mags[nPix] = m; mags[nPix] = m;
double angle = Math.atan2(dxy[1],dxy[0]) - avg_dir; double angle = Math.atan2(dxy[1],dxy[0]) - avg_dir;
if (angle > Math.PI) { if (angle > Math.PI) {
...@@ -2128,6 +2466,7 @@ public static double [][] warpMagnitudeDirection( ...@@ -2128,6 +2466,7 @@ public static double [][] warpMagnitudeDirection(
} }
} }
} }
}
}; };
} }
ImageDtt.startAndJoin(threads); ImageDtt.startAndJoin(threads);
...@@ -2153,16 +2492,27 @@ public static double [][] warpMagnitudeDirection( ...@@ -2153,16 +2492,27 @@ public static double [][] warpMagnitudeDirection(
for (int nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) { for (int nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) {
double [] dxy = warp_dxy[nPix]; double [] dxy = warp_dxy[nPix];
if (dxy != null) { if (dxy != null) {
double mag = mags[nPix];
double angle = mag_dirs[nPix]/mag_blur[nPix] + avg_dir; double angle = mag_dirs[nPix]/mag_blur[nPix] + avg_dir;
if (Double.isNaN(angle) || Double.isNaN(mag)) {
warp_md[nPix] = new double [2];
} else {
if (after_ref) {
angle += Math.PI;
mag = -mag;
}
if (angle > Math.PI) { if (angle > Math.PI) {
while (angle > Math.PI) {
angle -= 2 * Math.PI; angle -= 2 * Math.PI;
}
} else if (angle < -Math.PI){ } else if (angle < -Math.PI){
angle += 2 * Math.PI; angle += 2 * Math.PI;
} }
if (Double.isNaN(angle)) { if (Double.isNaN(angle)) {
angle = 0; angle = 0;
} }
warp_md[nPix] = new double [] {mags[nPix], angle}; warp_md[nPix] = new double [] {mag, angle};
}
} }
} }
} }
...@@ -2170,7 +2520,7 @@ public static double [][] warpMagnitudeDirection( ...@@ -2170,7 +2520,7 @@ public static double [][] warpMagnitudeDirection(
} }
ImageDtt.startAndJoin(threads); ImageDtt.startAndJoin(threads);
return warp_md; return warp_md;
} }
...@@ -3156,6 +3506,77 @@ public static double [][] warpMagnitudeDirection( ...@@ -3156,6 +3506,77 @@ public static double [][] warpMagnitudeDirection(
return double_render; return double_render;
} }
public static boolean [][] farFromNan(
final double [][] data,
final int width,
final int shrink) { // 50
final int num_scenes = data.length;
final boolean [][] reliable = new boolean[num_scenes][];
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 nscene = ai.getAndIncrement(); nscene < num_scenes; nscene = ai.getAndIncrement()) {
reliable[nscene] = farFromNanSingle(
data[nscene], // final double [] data,
width, // final int width,
shrink); // final int shrink)
}
}
};
}
ImageDtt.startAndJoin(threads);
return reliable;
}
public static boolean [] farFromNan(
final double [] data,
final int width,
final int shrink) {
final int num_pixels = data.length;
final boolean [] reliable = new boolean[num_pixels];
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 nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) if (!Double.isNaN(data[nPix])) {
reliable[nPix] = true;
}
}
};
}
ImageDtt.startAndJoin(threads);
TileNeibs tn = new TileNeibs(width, num_pixels/width);
tn.shrinkSelection(
shrink, // final int shrink, // grow tile selection by 1 over non-background tiles 1: 4 directions, 2 - 8 directions, 3 - 8 by 1, 4 by 1 more
reliable, // final boolean [] tiles,
null); // final boolean [] prohibit)
return reliable;
}
public static boolean [] farFromNanSingle(
final double [] data,
final int width,
final int shrink) {
final int num_pixels = data.length;
final boolean [] reliable = new boolean[num_pixels];
for (int npix = 0; npix < num_pixels; npix++) if (!Double.isNaN(data[npix])) {
reliable[npix] = true;
}
TileNeibs tn = new TileNeibs(width, num_pixels/width);
tn.shrinkSelection(
shrink, // final int shrink, // grow tile selection by 1 over non-background tiles 1: 4 directions, 2 - 8 directions, 3 - 8 by 1, 4 by 1 more
reliable, // final boolean [] tiles,
null); // final boolean [] prohibit)
return reliable;
}
public static void zerosToNans ( public static void zerosToNans (
final double [][] data, final double [][] data,
...@@ -3249,12 +3670,6 @@ public static double [][] warpMagnitudeDirection( ...@@ -3249,12 +3670,6 @@ public static double [][] warpMagnitudeDirection(
} }
double [] terrain_dbg = debug_img? terrain_filled.clone() : null; double [] terrain_dbg = debug_img? terrain_filled.clone() : null;
/*
OrthoMap.fillNaNs(
terrain_holes, // double [] data,
tn, // TileNeibs tn,
3); // int min_neibs)
*/
terrain_filled = TileProcessor.fillNaNs( terrain_filled = TileProcessor.fillNaNs(
terrain_filled, // final double [] data, terrain_filled, // final double [] data,
null, // final boolean [] prohibit, null, // final boolean [] prohibit,
...@@ -3263,8 +3678,7 @@ public static double [][] warpMagnitudeDirection( ...@@ -3263,8 +3678,7 @@ public static double [][] warpMagnitudeDirection(
2* width, // 100, // 2*width, // 16, // final int grow, 2* width, // 100, // 2*width, // 16, // final int grow,
0.7, // double diagonal_weight, // relative to ortho 0.7, // double diagonal_weight, // relative to ortho
100, // int num_passes, 100, // int num_passes,
0.03, // final double max_rchange, // = 0.01 - does not need to be accurate 0.03); // final double max_rchange, // = 0.01 - does not need to be accurate
ImageDtt.THREADS_MAX); // final int threadsMax) // maximal number of threads to launch
if (debug_img) { if (debug_img) {
......
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