Commit e43d01e8 authored by Andrey Filippov's avatar Andrey Filippov

Implemented new version of combining of segments

parent 7c77ddba
......@@ -735,9 +735,13 @@ min_str_neib_fpn 0.35
public boolean terr_par_restore = false; // restore parameters from file
public int terr_step_restore = 2; // If restore, start with step after restored
// terrain/vegetation parameters
@Deprecated
public boolean terr_um_en = true;
public double terr_um_sigma = 1.0;
public double terr_um_weight = 0.8;
// @Deprecated
public double terr_um_sigma = 1.0; // use for render
// @Deprecated
public double terr_um_weight = 0.8; // use for render
@Deprecated
public double terr_nan_tolerance = 0.001; // set undefined terrain (out of capture area) to nan, it is almost zero after UM. if !terr_um_en will be forced ==0.0
public int terr_nan_grow = 20; // grow undefined scenes terrain after detection
public int terr_shrink_veget = 20; // shrink accumulated vegetation for filling terrain
......@@ -811,6 +815,7 @@ min_str_neib_fpn 0.35
public double terr_alpha_weight_center =1.5; // weight of center alpha pixel relative to each of the 4 ortho ones
public boolean terr_en_holes = true; // enable small holes // maybe second pass after good fit with vegetation and search for correct offset?
public double terr_alpha_mm_hole = 0.1; // NaN to disable. Local "almost minimum" (lower than this fraction between min and max neighbor) is not subject to alpha_lpf
public double terr_alpha_diff_hole = 0.01; // Minimal alpha difference between min and max neighbor to be considered a hole
public double terr_terr_lpf = 0.1; // pull terrain to average of 4 neighbors
public double terr_veget_lpf = 10.0; // pull vegetation to average of 4 neighbors
public double terr_elev_lpf = 50.0; // pull elevation to average of 4 neighbors
......@@ -2137,6 +2142,7 @@ min_str_neib_fpn 0.35
gd.addNumericField("Alpha center weight", terr_alpha_weight_center, 5,7,"","Weight of center alpha pixel relative to each of the 4 ortho ones.");
gd.addCheckbox ("Hole search enable", terr_en_holes, "Search for small semi-transparent holes, disable diffusion of local alpha minimums.");
gd.addNumericField("Alpha MM fraction", terr_alpha_mm_hole, 5,7,"", "Disable diffusion for local \"almost minimum\" (lower than this fraction between min and max neighbors).");
gd.addNumericField("Alpha hole difference",terr_alpha_diff_hole, 5,7,"", "Minimal alpha difference between min and max neighbor to be considered a hole.");
gd.addNumericField("Terrain diffusion", terr_terr_lpf, 5,7,"", "LPF for terrain pixels (diffusion to 4 neighbors).");
gd.addNumericField("Vegetation diffusion", terr_veget_lpf, 5,7,"", "LPF for vegetation pixels (diffusion to 4 neighbors).");
gd.addNumericField("Elevation diffusion", terr_elev_lpf, 5,7,"", "LPF for elevation pixels (diffusion to 4 neighbors).");
......@@ -2895,8 +2901,9 @@ min_str_neib_fpn 0.35
terr_alpha_push_neutral = gd.getNextNumber();// double
terr_alpha_weight_center = gd.getNextNumber();// double
terr_en_holes = gd.getNextBoolean();// boolean
terr_alpha_mm_hole = gd.getNextNumber();// double
terr_alpha_diff_hole = gd.getNextNumber();// double
terr_terr_lpf = gd.getNextNumber();// double
terr_veget_lpf = gd.getNextNumber();// double
terr_elev_lpf = gd.getNextNumber();// double
......@@ -3617,6 +3624,9 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"terr_alpha_push_neutral", terr_alpha_push_neutral+""); // double
properties.setProperty(prefix+"terr_alpha_weight_center", terr_alpha_weight_center+"");// double
properties.setProperty(prefix+"terr_en_holes", terr_en_holes+""); // boolean
properties.setProperty(prefix+"terr_alpha_mm_hole", terr_alpha_mm_hole+""); // double
properties.setProperty(prefix+"terr_alpha_diff_hole", terr_alpha_diff_hole+""); // double
properties.setProperty(prefix+"terr_terr_lpf", terr_terr_lpf+""); // double
properties.setProperty(prefix+"terr_veget_lpf", terr_veget_lpf+""); // double
properties.setProperty(prefix+"terr_elev_lpf", terr_elev_lpf+""); // double
......@@ -4358,6 +4368,8 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"terr_alpha_weight_center")!=null) terr_alpha_weight_center=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_weight_center"));
if (properties.getProperty(prefix+"terr_en_holes")!= null) terr_en_holes=Boolean.parseBoolean(properties.getProperty(prefix+"terr_en_holes"));
if (properties.getProperty(prefix+"terr_alpha_mm_hole")!= null) terr_alpha_mm_hole=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_mm_hole"));
if (properties.getProperty(prefix+"terr_alpha_diff_hole")!= null) terr_alpha_diff_hole=Double.parseDouble(properties.getProperty(prefix+"terr_alpha_diff_hole"));
if (properties.getProperty(prefix+"terr_terr_lpf")!= null) terr_terr_lpf=Double.parseDouble(properties.getProperty(prefix+"terr_terr_lpf"));
if (properties.getProperty(prefix+"terr_veget_lpf")!= null) terr_veget_lpf=Double.parseDouble(properties.getProperty(prefix+"terr_veget_lpf"));
if (properties.getProperty(prefix+"terr_elev_lpf")!= null) terr_elev_lpf=Double.parseDouble(properties.getProperty(prefix+"terr_elev_lpf"));
......@@ -5069,6 +5081,7 @@ min_str_neib_fpn 0.35
imp.terr_alpha_weight_center = this.terr_alpha_weight_center;
imp.terr_en_holes = this.terr_en_holes;
imp.terr_alpha_mm_hole = this.terr_alpha_mm_hole;
imp.terr_alpha_diff_hole = this.terr_alpha_diff_hole;
imp.terr_terr_lpf = this.terr_terr_lpf;
imp.terr_veget_lpf = this.terr_veget_lpf;
imp.terr_elev_lpf = this.terr_elev_lpf;
......
......@@ -104,7 +104,6 @@ public class VegetationLMA {
private int [][] y_src_hf; // subset of pointers that have all 4 neighbors
private int [][] y_src_scene; // [scene]{start_y_src, end_y_src+1} pointers to y_src per scene
private int [][] y_wsrc; // [scene][windex] ysrc index for scene, windex [num_scenes][woi_length]
private double terrain_correction;// weight of y_wavg
private double terrain_correction_weight = 1.0;
private double weight_to_scene_weight = 1;
private boolean recalc_average = false; //apply transparency to average mismatch
......@@ -148,7 +147,8 @@ public class VegetationLMA {
// @Deprecated
// private double terr_pull_cold = 0; // pull vegetations to warm, terrain to cold
boolean [] fits_disable; //
boolean [] fits_disable = new boolean[TVAO_TYPES]; // (+)
private double terrain_correction = 0.02; // (+) weight of y_wavg
// Parameters saved/resored in a file
private final int num_scenes; // (+)
......@@ -156,7 +156,7 @@ public class VegetationLMA {
private Rectangle woi_veg = null; // (*) extended woi to include offset vegetation
private double hifreq_weight; // (+) 22.5 0 - do not use high-freq. Relative weight of laplacian components
private double reg_weights; // (+) fraction of the total weight used for regularization
private boolean [] fits; // (+)
private boolean [] fits = new boolean[TVAO_TYPES];// (+)
private double alpha_loss = 0; // (+) quadratic loss
private double alpha_loss_lin = 0.5; // (+) linear loss
private double alpha_offset = 0; // (+) if >0, start losses above 0.0 and below 1.0;
......@@ -198,6 +198,10 @@ public class VegetationLMA {
private double scenes_pull0 = 0; // (*) pull average scene offset to 0;
private 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 max_parallax = 10; // (+)
public double max_warp = 3.8; // 1.8 - do not use scenes where distance between vegetation projection exceeds this
public int max_elevation = 22; // maximal "elevation" to consider
public double elevation_radius = 1.5; // Radius of elevation/vegetation influence.
// data used to calculate lpf pull of the alpha pixel to average of four neighbors. Below similar (weaker pull) for terrain and vegetation
// to smooth areas where there is no data from available images.
......@@ -232,6 +236,18 @@ public class VegetationLMA {
private double [] last_ymfx = null;
private double [][] last_jt = null;
public double terrain_offset = Double.NaN; // average offset from the initial
public Rectangle getFull() {
return full;
}
public Rectangle getWoi() {
return woi;
}
public Rectangle getWoiVeg() {
return woi_veg;
}
public VegetationModel getModel() {
return vegetationModel;
}
public VegetationLMA (
int width,
......@@ -490,9 +506,8 @@ public class VegetationLMA {
final boolean keep_parameters,
final Rectangle woi,
final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this
final int max_offset, // maximal "elevation" to consider
final int max_elevation, // maximal "elevation" to consider
final double elevation_radius, //Radius of elevation/vegetation influence.
final double default_alpha,
final double hifreq_weight, // 22.5 0 - do not use high-freq. Relative weight of laplacian components
final double terrain_correction,
final boolean fit_terr,
......@@ -514,6 +529,7 @@ public class VegetationLMA {
final double alpha_push_center,// 1.5; // weight of center alpha pixel relative to each of the 4 ortho ones
final boolean alpha_en_holes, // Search for small semi-transparent holes, disable diffusion of local alpha minimums
final 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
final double alpha_diff_hole, // 0.01; // Minimal alpha difference between min and max neighbor to be considered a hole
final double terr_lpf, // pull terrain to average of 4 neighbors (very small)
final double veget_lpf, // pull vegetation to average of 4 neighbors (very small - maybe not needed)
final double elevation_lpf,
......@@ -529,16 +545,16 @@ public class VegetationLMA {
final double scenes_pull0,
final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene
final double max_parallax, // do not consider maximal parallax above this (consider it a glitch)
final double um_sigma, // just use in debug image names
final double um_weight,
String parameters_read_path,
// final double um_sigma, // just use in debug image names
// final double um_weight,
// String parameters_read_path,
final int debugLevel,
final boolean debug_save_improved, // Save debug image after successful LMA step.");
final boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step.");
this.woi = woi;
this.hifreq_weight = hifreq_weight; // 22.5 0 - do not use high-freq. Relative weight of laplacian components
this.terrain_correction = terrain_correction;
fits = new boolean[TVAO_TYPES];
// fits = new boolean[TVAO_TYPES];
fits[TVAO_TERRAIN] = fit_terr;
fits[TVAO_VEGETATION] = fit_veget;
fits[TVAO_ALPHA] = fit_alpha;
......@@ -572,8 +588,15 @@ public class VegetationLMA {
this.low_veget = low_veget;
this.scenes_pull0 = scenes_pull0;
this.boost_parallax = boost_parallax;
this.debug_save_improved =debug_save_improved;
this.max_parallax = max_parallax; // parallax limit when evaluating boost parallax
this.max_warp = max_warp;
this.max_elevation = max_elevation;
this.elevation_radius = elevation_radius;
this.debug_save_improved = debug_save_improved;
this.debug_save_worsened = debug_save_worsened;
this.elev_sum_weights = null; // calculate elevations on next getFxDErivsrun
// this.um_sigma = um_sigma; // just use in debug image names
// this.um_weight = um_weight;
......@@ -608,7 +631,7 @@ public class VegetationLMA {
warps, // final double[][][] warps,
max_warp, // final double max_warp,
valid_pixels_in, // final boolean [] valid_pixels_in, // should be initialized to woi, normally set to all true
max_offset, // final int max_offset,
max_elevation, // final int max_offset,
elev_radius, // final double [] elev_radius, // this.elevation_radius
max_sacrifice, // final int max_sacrifice,
valid_stats, // final int [] stats,
......@@ -702,7 +725,7 @@ public class VegetationLMA {
titles);
}
// used_veg = valid_scene_pix[2];
/*
if ("RESTORE".equals(parameters_read_path)) {
from_file = false;
String restore_dir = debug_path;
......@@ -714,7 +737,7 @@ public class VegetationLMA {
String restore_path=restore_dir + debug_title+"-live.tiff";
parameters_read_path = restore_path;
}
*/
// final double [] scene_weights = //sets this.scene_weights too
double [] scene_weights0 = //sets this.scene_weights too
......@@ -781,6 +804,7 @@ public class VegetationLMA {
}
from_file = false;
/*
if (parameters_read_path != null) {
readParametersFromImage(
parameters_read_path, // String path,
......@@ -788,7 +812,7 @@ public class VegetationLMA {
show_extra, // boolean extra,
1) ;// int gap)
}
*/
boolean use_terr_corr = (terrain_correction>=0); // maybe not needed
setupYVector(
use_terr_corr, // boolean use_terr_corr); //(hifreq_weight > 0)); // boolean use_hf);
......@@ -4186,13 +4210,21 @@ public class VegetationLMA {
imp.setProperty("FULL_HEIGHT", ""+full.height);
imp.setProperty("HIGHFREQ_WEIGHT", ""+hifreq_weight);
imp.setProperty("TERRAIN_CORRECTION", ""+terrain_correction);
imp.setProperty("REG_WEIGHTS", ""+reg_weights);
imp.setProperty("FIT_TERRAIN", ""+fits[TVAO_TERRAIN]);
imp.setProperty("FIT_VEGETATION", ""+fits[TVAO_VEGETATION]);
imp.setProperty("FIT_ALPHA", ""+fits[TVAO_ALPHA]);
imp.setProperty("FIT_ELEVATION", ""+fits[TVAO_ELEVATION]);
imp.setProperty("FIT_SCENE_OFFSET", ""+fits[TVAO_SCENE_OFFSET]);
imp.setProperty("FIT_DISABLE_TERRAIN", ""+fits_disable[TVAO_TERRAIN]);
imp.setProperty("FIT_DISABLE_VEGETATION", ""+fits_disable[TVAO_VEGETATION]);
imp.setProperty("FIT_DISABLE_ALPHA", ""+fits_disable[TVAO_ALPHA]);
imp.setProperty("FIT_DISABLE_ELEVATION", ""+fits_disable[TVAO_ELEVATION]);
imp.setProperty("FIT_DISABLE_SCENE_OFFSET", ""+fits_disable[TVAO_SCENE_OFFSET]);
imp.setProperty("ALPHA_LOSS", ""+alpha_loss);
imp.setProperty("ALPHA_LOSS_LIN", ""+alpha_loss_lin);
imp.setProperty("ALPHA_OFFSET", ""+alpha_offset);
imp.setProperty("ALPHA_MIN_VEG", ""+alpha_min_veg);
imp.setProperty("ALPHA_LPF", ""+alpha_lpf);
......@@ -4223,11 +4255,17 @@ public class VegetationLMA {
imp.setProperty("ELEV_ALPHA_EN", ""+elev_alpha_en);
imp.setProperty("ELEV_ALPHA", ""+elev_alpha);
imp.setProperty("ELEV_ALPHA_PWR", ""+elev_alpha_pwr);
imp.setProperty("ELEV_LOW_VEGET", ""+low_veget);
imp.setProperty("SCENES_PULL0", ""+scenes_pull0);
imp.setProperty("SCALE_SCENES_PULL", ""+scale_scenes_pull);
imp.setProperty("BOOST_PARALLAX", ""+boost_parallax);
imp.setProperty("MAX_PARALLAX", ""+max_parallax);
imp.setProperty("MAX_WARP", ""+max_warp);
imp.setProperty("MAX_ELEVATION", ""+max_elevation);
imp.setProperty("ELEVATION_RADIUS", ""+elevation_radius);
imp.setProperty("NUM_PARS_TERRAIN", ""+num_pars[TVAO_TERRAIN]);
imp.setProperty("NUM_PARS_VEGETATION", ""+num_pars[TVAO_VEGETATION]);
imp.setProperty("NUM_PARS_ALPHA", ""+num_pars[TVAO_ALPHA]);
......@@ -4359,6 +4397,7 @@ public class VegetationLMA {
this.woi = woi;
if (!keep_settings) {
hifreq_weight = Double.parseDouble((String) imp_pars.getProperty("HIGHFREQ_WEIGHT"));
terrain_correction = getProperty(imp_pars,"TERRAIN_CORRECTION", terrain_correction);
reg_weights = Double.parseDouble((String) imp_pars.getProperty("REG_WEIGHTS"));
fits = new boolean[TVAO_TYPES];
fits[TVAO_TERRAIN] = Boolean.parseBoolean((String) imp_pars.getProperty("FIT_TERRAIN"));
......@@ -4366,9 +4405,17 @@ public class VegetationLMA {
fits[TVAO_ALPHA] = Boolean.parseBoolean((String) imp_pars.getProperty("FIT_ALPHA"));
fits[TVAO_ELEVATION] = Boolean.parseBoolean((String) imp_pars.getProperty("FIT_ELEVATION"));
fits[TVAO_SCENE_OFFSET] = Boolean.parseBoolean((String) imp_pars.getProperty("FIT_SCENE_OFFSET"));
fits_disable[TVAO_TERRAIN] = getProperty(imp_pars,"FIT_DISABLE_TERRAIN", fits_disable[TVAO_TERRAIN]);
fits_disable[TVAO_VEGETATION] = getProperty(imp_pars,"FIT_DISABLE_VEGETATION", fits_disable[TVAO_VEGETATION]);
fits_disable[TVAO_ALPHA] = getProperty(imp_pars,"FIT_DISABLE_ALPHA", fits_disable[TVAO_ALPHA]);
fits_disable[TVAO_ELEVATION] = getProperty(imp_pars,"FIT_DISABLE_ELEVATION", fits_disable[TVAO_ELEVATION]);
fits_disable[TVAO_SCENE_OFFSET] = getProperty(imp_pars,"FIT_DISABLE_SCENE_OFFSET", fits_disable[TVAO_SCENE_OFFSET]);
alpha_loss = Double.parseDouble((String) imp_pars.getProperty("ALPHA_LOSS"));
alpha_loss_lin = getProperty(imp_pars,"ALPHA_LOSS_LIN", alpha_loss_lin);
alpha_offset = Double.parseDouble((String) imp_pars.getProperty("ALPHA_OFFSET"));
if (imp_pars.getProperty("ALPHA_MIN_VEG") != null) alpha_min_veg = Double.parseDouble((String) imp_pars.getProperty("ALPHA_MIN_VEG"));
alpha_min_veg = getProperty(imp_pars,"ALPHA_MIN_VEG",alpha_min_veg);
alpha_lpf = Double.parseDouble((String) imp_pars.getProperty("ALPHA_LPF"));
alpha_piece_linear = Boolean.parseBoolean((String) imp_pars.getProperty("ALPHA_PIECE_LINEAR"));
alpha_scale_avg = Double.parseDouble((String) imp_pars.getProperty("ALPHA_SCALE_AVG"));
......@@ -4401,7 +4448,14 @@ public class VegetationLMA {
scenes_pull0 = Double.parseDouble((String) imp_pars.getProperty("SCENES_PULL0"));
scale_scenes_pull = Double.parseDouble((String) imp_pars.getProperty("SCALE_SCENES_PULL"));
boost_parallax = Double.parseDouble((String) imp_pars.getProperty("BOOST_PARALLAX"));
if (imp_pars.getProperty("TERRAIN_OFFSET") != null) terrain_offset = Double.parseDouble((String) imp_pars.getProperty("TERRAIN_OFFSET"));
max_parallax = getProperty(imp_pars,"MAX_PARALLAX", max_parallax);
max_warp = getProperty(imp_pars,"MAX_WARP", max_warp);
max_elevation = getProperty(imp_pars,"MAX_ELEVATION", max_elevation);
elevation_radius = getProperty(imp_pars,"ELEVATION_RADIUS", elevation_radius);
terrain_offset = getProperty(imp_pars,"TERRAIN_OFFSET", terrain_offset);
// if (imp_pars.getProperty("TERRAIN_OFFSET") != null) terrain_offset = Double.parseDouble((String) imp_pars.getProperty("TERRAIN_OFFSET"));
}
num_pars[TVAO_TERRAIN] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_TERRAIN"));
num_pars[TVAO_VEGETATION] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_VEGETATION"));
......@@ -4432,16 +4486,6 @@ public class VegetationLMA {
num_pars[TVAO_ELEVATION],
num_pars[TVAO_SCENE_OFFSET]};
/*
par_index[TVAO_TERRAIN] = new int [num_pars[TVAO_TERRAIN]];
par_index[TVAO_VEGETATION] = new int [num_pars[TVAO_VEGETATION]];
par_index[TVAO_ALPHA] = new int [num_pars[TVAO_ALPHA]];
par_index[TVAO_ELEVATION] = new int [num_pars[TVAO_ELEVATION]];
par_index[TVAO_SCENE_OFFSET] = new int [num_pars[TVAO_SCENE_OFFSET]];
*/
// samples_pointers = new int [SAMPLES_SIZE][3];
int [][] samples_pointers_tmp = new int [SAMPLES_SIZE][3];
update_samples_pointers: {
for (int nsp = 0; nsp < SAMPLES_SIZE; nsp++) {
......@@ -4484,256 +4528,193 @@ public class VegetationLMA {
return data;
}
public void combineSegments(
VegetationSegment [] segments,
int width,
final boolean render_open, // render open areas (no vegetation offset)
final boolean render_no_alpha, // render where no opacity is available
final double alpha_min, // below - completely transparent vegetation
final double alpha_max, // above - completely opaque
final double weight_opaque, // render through completely opaque vegetation
final double boost_parallax, // increase weights of scenes with high parallax relative to the reference one
final double max_parallax,
final int num_exaggerate) { // show amplified difference from filtering
//FIXME: Handle woi separately!
public double[][] restoreParametersFile(
String path,
int debugLevel,
boolean debug_save_improved, // Save debug image after successful LMA step.");
boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step.");
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
double ksigma = 1.0;
double min_sw = 1e-4;
int full_length = full.width*full.height;
int accum_indx = segments.length;
double [][][] preview_data = new double [3][accum_indx+1][full_length];
String [] top_titles = {"terrain","vegetation","alpha"};
String [] titles = new String[accum_indx+1];
for (int ns = 0; ns < segments.length; ns++) {
Rectangle woi_veg = segments[ns].woi_veg;
titles[ns] = woi_veg.toString();
int woi_length = woi_veg.width * woi_veg.height;
double [][] woi_tva = segments[ns].tva;
for (int t = 0; t < 3; t++) {
Arrays.fill(preview_data[t][ns], Double.NaN);
for (int windx = 0; windx < woi_length; windx++) {
int x = windx % woi_veg.width + woi_veg.x;
int y = windx / woi_veg.width + woi_veg.y;
int indx = x + y * full.width;
preview_data[t][ns][indx] = woi_tva[t][windx];
}
}
}
titles[accum_indx] = "accum";
double [][] sum_w = new double [preview_data.length][full_length];
double [][] sum_wd = new double [preview_data.length][full_length];
for (int ns = 0; ns < segments.length; ns++) {
Rectangle woi_veg = segments[ns].woi_veg;
int woi_length = woi_veg.width*woi_veg.height;
double [][] woi_tva = segments[ns].tva;
double [] wnd = overlapCosineWindow (woi, width);
for (int windx = 0; windx < woi_length; windx++) {
int x = windx % woi_veg.width + woi_veg.x;
int y = windx / woi_veg.width + woi_veg.y;
int indx = x + y * full.width;
for (int t = 0; t < preview_data.length; t++) {
if (!Double.isNaN(woi_tva[t][windx])) {
double w = wnd[windx];
sum_w [t][indx] += w;
sum_wd[t][indx] += w * woi_tva[t][windx] ;
}
ImagePlus imp_pars = new ImagePlus (path);
if (imp_pars.getWidth()==0) {
throw new IllegalArgumentException("Could not read "+path);
}
int num_slices = imp_pars.getStack().getSize();
if (num_slices != 10) {
throw new IllegalArgumentException("Expecting an 10-slice file, got "+num_slices);
}
int width = imp_pars.getWidth(); // woi_veg.width
int height = imp_pars.getHeight(); // woi_veg.height
double [][] data = new double[TVAO_TYPES][width*height];
int [][] indices = new int[TVAO_TYPES][width*height];
for (int n = 0; n < TVAO_TYPES; n++) {
float [] pixels = (float[]) imp_pars.getStack().getPixels(n+1);
for (int i = 0; i < data[n].length; i++) {
data[n][i] = pixels[i];
}
for (int t = 0; t < preview_data.length; t++) {
for (int i = 0; i < full_length; i++) {
if (sum_w[t][i] == 0) {
preview_data[t][accum_indx][i] = Double.NaN;
} else {
preview_data[t][accum_indx][i] = sum_wd[t][i]/sum_w[t][i];
}
for (int n = 0; n < TVAO_TYPES; n++) {
float [] pixels = (float[]) imp_pars.getStack().getPixels(n+1+ TVAO_TYPES);
for (int i = 0; i < data[n].length; i++) {
indices[n][i] = (int) pixels[i];
}
}
// Combine offsets per scene
double [][] combined_offsets = new double [num_scenes][full_length];
String [] titles_scenes = new String [num_scenes];
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [] sw = new double [full_length];
for (int nscene = ai.getAndIncrement(); nscene < num_scenes; nscene = ai.getAndIncrement()) {
titles_scenes[nscene] = "scene "+nscene;
double [] swd = combined_offsets[nscene];
Arrays.fill(sw, 0);
for (int ns = 0; ns < segments.length; ns++) {
Rectangle woi_veg = segments[ns].woi;
int woi_length = woi_veg.width*woi_veg.height;
double scene_offset = segments[ns].scene_offsets[nscene];
if (!Double.isNaN(scene_offset)) {
double [] wnd = overlapCosineWindow (woi, width);
for (int windx = 0; windx < woi_length; windx++) {
int x = windx % woi_veg.width + woi_veg.x;
int y = windx / woi_veg.width + woi_veg.y;
int indx = x + y * full.width;
for (int t = 0; t < preview_data.length; t++) {
double w = wnd[windx];
sw [indx] += w;
swd[indx] += w * scene_offset ;
}
}
}
JP46_Reader_camera.decodeProperiesFromInfo(imp_pars);
Rectangle full = new Rectangle (
0,
0,
Integer.parseInt((String) imp_pars.getProperty("FULL_WIDTH")),
Integer.parseInt((String) imp_pars.getProperty("FULL_HEIGHT")));
if (!full.equals(this.full)) {
throw new IllegalArgumentException("Full image window differes, this is ("+this.full.width+" x "+this.full.height+"), file contains ("+
+full.width+" x "+full.height+")");
}
(new DoubleGaussianBlur()).blurDouble(
sw, //
full.width,
full.height,
ksigma*width, // double sigmaX,
ksigma*width, // double sigmaY,
0.01); // double accuracy)
(new DoubleGaussianBlur()).blurDouble(
swd, //
full.width,
full.height,
ksigma*width, // double sigmaX,
ksigma*width, // double sigmaY,
0.01); // double accuracy)
int num_scenes = Integer.parseInt((String) imp_pars.getProperty("NUM_SCENES"));
for (int i = 0; i < full_length; i++) {
if (sw[i] < min_sw) {
swd[i] = Double.NaN;
} else {
swd[i] /= sw[i];
}
}
}
}
};
if (num_scenes != this.num_scenes) {
throw new IllegalArgumentException("Number of scenes can not be changed, this has "+this.num_scenes+", file has "+
+num_scenes+".");
}
ImageDtt.startAndJoin(threads);
double [][] tva = {preview_data[0][accum_indx],preview_data[1][accum_indx],preview_data[2][accum_indx]};
vegetationModel.setTVA(tva);
// new String[] {"full average", "filtered average"});
String ref_scene = vegetationModel.reference_scene;
String render_title = "render-ro_"+render_open+"-rna_"+render_no_alpha+"-amn"+alpha_min+"-amx"+alpha_max+"-wo"+weight_opaque+"-bp"+boost_parallax+".tiff";
Rectangle woi = new Rectangle (
Integer.parseInt((String) imp_pars.getProperty("WOI_X")),
Integer.parseInt((String) imp_pars.getProperty("WOI_Y")),
Integer.parseInt((String) imp_pars.getProperty("WOI_WIDTH")),
Integer.parseInt((String) imp_pars.getProperty("WOI_HEIGHT")));
Rectangle woi_veg = new Rectangle (
Integer.parseInt((String) imp_pars.getProperty("WOI_VEG_X")),
Integer.parseInt((String) imp_pars.getProperty("WOI_VEG_Y")),
Integer.parseInt((String) imp_pars.getProperty("WOI_VEG_WIDTH")),
Integer.parseInt((String) imp_pars.getProperty("WOI_VEG_HEIGHT")));
{
// run prepareLMA from the file metadata
String [] disable_names = new String [TVAO_NAMES.length];
for (int i = 0; i < TVAO_NAMES.length; i++) {
disable_names[i]= "FIT_DISABLE_"+TVAO_NAMES[i];
}
// int num_samples =
prepareLMA(
false, // final boolean keep_parameters,
woi, // final Rectangle woi,
getProperty(imp_pars,"MAX_WARP", max_warp), // final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this
getProperty(imp_pars,"MAX_ELEVATION", max_elevation), // final int max_offset, // maximal "elevation" to consider
getProperty(imp_pars,"ELEVATION_RADIUS", elevation_radius), // final double elevation_radius, // Radius of elevation/vegetation influence.
getProperty(imp_pars, "HIGHFREQ_WEIGHT", hifreq_weight), // final double hifreq_weight, // 22.5 0 - do not use high-freq. Relative weight of laplacian components
getProperty(imp_pars, "TERRAIN_CORRECTION", terrain_correction), // final double terrain_correction,
getProperty(imp_pars, "FIT_TERRAIN", fits[TVAO_TERRAIN]), // final boolean adjust_terr,
getProperty(imp_pars, "FIT_VEGETATION", fits[TVAO_VEGETATION]), // final boolean adjust_veget,
getProperty(imp_pars, "FIT_ALPHA", fits[TVAO_ALPHA]), // final boolean adjust_alpha,
getProperty(imp_pars, "FIT_SCENE_OFFSET", fits[TVAO_SCENE_OFFSET]),// final boolean adjust_scenes,
getProperty(imp_pars, "FIT_ELEVATION", fits[TVAO_ELEVATION]), // final boolean adjust_elevations,
getProperty(imp_pars, disable_names, fits_disable), // final boolean [] fit_disable,
getProperty(imp_pars, "REG_WEIGHTS", reg_weights), // final double reg_weights, // fraction of the total weight used for regularization
getProperty(imp_pars, "ALPHA_LOSS", alpha_loss), // final double alpha_loss, // alpha quadratic growing loss for when out of [0,1] range
getProperty(imp_pars, "ALPHA_LOSS_LIN", alpha_loss_lin), // final double alpha_loss_lin, // alpha linear growing loss for when out of [0,1] range and below minimal vegetation alpha
getProperty(imp_pars, "ALPHA_OFFSET", alpha_offset), // final double alpha_offset, // quadratic loss when alpha reaches -1.0 or 2.0
getProperty(imp_pars, "ALPHA_MIN_VEG", alpha_min_veg), // final double alpha_min_veg, // 0.5; // if (alpha-alpha_offset)/(1-2*alpha_offset) < alpha_min_veg, pull down to lpha_offset
getProperty(imp_pars, "ALPHA_LPF", alpha_lpf), // final double alpha_lpf, // pull to average of 4 neighbors
getProperty(imp_pars, "ALPHA_PIECE_LINEAR", alpha_piece_linear), // final boolean alpha_piece_linear, // true - piece-linear, false - half-cosine
getProperty(imp_pars, "ALPHA_SCALE_AVG", alpha_scale_avg), // final double alpha_scale_avg, // = 1.2; // scale average alpha (around 0.5) when pulling to it
getProperty(imp_pars, "ALPHA_PUSH", alpha_push), // final double alpha_push, // 5.0; // push from alpha==0.5
getProperty(imp_pars, "ALPHA_PUSH_NEUTRAL", alpha_push_neutral), // double alpha_push_neutral = 0.8; // alpha point from which push (closer to opaque)
getProperty(imp_pars, "ALPHA_PUSH_CENTER", alpha_push_center), // final double alpha_push_center,// 1.5; // weight of center alpha pixel relative to each of the 4 ortho ones
getProperty(imp_pars, "ALPHA_EN_HOLES", alpha_en_holes), // final boolean alpha_en_holes, // Search for small semi-transparent holes, disable diffusion of local alpha minimums
getProperty(imp_pars, "ALPHA_MM_HOLE", 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
getProperty(imp_pars, "ALPHA_DIFF_HOLE", alpha_diff_hole), // final double alpha_diff_hole, // 0.01; // Minimal alpha difference between min and max neighbor to be considered a hole
getProperty(imp_pars, "TERR_LPF", terr_lpf), // final double terr_lpf, // pull terrain to average of 4 neighbors (very small)
getProperty(imp_pars, "VEGET_LPF", veget_lpf), // final double veget_lpf, // pull vegetation to average of 4 neighbors (very small - maybe not needed)
getProperty(imp_pars, "ELEVATION_LPF", elevation_lpf), // final double elevation_lpf,
getProperty(imp_pars, "TERR_PULL0", terr_pull0), // final double terr_pull0, // pull terrain to initial (pre-adjustment) values
getProperty(imp_pars, "TERR_PULL_UP", terr_pull_up), // final double terr_pull_up, // Terrain pixels pull to initial (pre-adjustment) values when it is colder than initial.
getProperty(imp_pars, "TERR_PULL_AVG", terr_pull_avg), // final double terr_pull_avg, // pull terrain to the initial offset by the average offset of all terrain pixels
getProperty(imp_pars, "VEGET_PULL0", veget_pull0), // final double veget_pull0, // pull vegetation to initial (pre-adjustment) values
getProperty(imp_pars, "ELEVATION_PULL0", elevation_pull0), // final double elev_pull0, // pull elevation to initial (pre-adjustment) values
getProperty(imp_pars, "ELEV_ALPHA_EN", elev_alpha_en), // final boolean elev_alpha_en, // false; // Enable loss for low vegetation with high opacity
getProperty(imp_pars, "ELEV_ALPHA", elev_alpha), // final double elev_alpha, // 1.0; // multiply alpha by under-low elevation for loss
getProperty(imp_pars, "ELEV_ALPHA_PWR", elev_alpha_pwr), // final double elev_alpha_pwr, // 2.0; // raise alpha to this power (when alpha > 0)
getProperty(imp_pars, "ELEV_LOW_VEGET", low_veget), // final double low_veget, // 2.0; // (pix) Elevation considered low (lower loss for high alpha)
getProperty(imp_pars, "SCENES_PULL0", scenes_pull0), // final double scenes_pull0,
getProperty(imp_pars, "BOOST_PARALLAX", boost_parallax), // final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene
getProperty(imp_pars, "MAX_PARALLAX", max_parallax), // final double max_parallax, // do not consider maximal parallax above this (consider it a glitch)
debugLevel, // final int debugLevel);
debug_save_improved, // final boolean debug_save_improved, // Save debug image after successful LMA step.");
debug_save_worsened); // final boolean debug_save_worsened) // Save debug image after unsuccessful LMA step.");
double [] render = renderWithAlpha(
preview_data[2][accum_indx], // final double [] alpha,
combined_offsets, // final double [][] scene_offsets, // subtract if not null
render_open, // final boolean render_open, // render open areas (no vegetation offset)
render_no_alpha, // final boolean render_no_alpha, // render where no opacity is available
alpha_min, // final double alpha_min, // below - completely transparent vegetation
alpha_max, // final double alpha_max, // above - completely opaque
weight_opaque, // final double weight_opaque, // render through completely opaque vegetation
boost_parallax, // final double boost_parallax) { // increase weights of scenes with high parallax relative to the reference one
max_parallax); // final double max_parallax)
num_pars[TVAO_TERRAIN] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_TERRAIN"));
num_pars[TVAO_VEGETATION] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_VEGETATION"));
num_pars[TVAO_ALPHA] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_ALPHA"));
num_pars[TVAO_ELEVATION] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_ELEVATION"));
num_pars[TVAO_SCENE_OFFSET] = Integer.parseInt((String) imp_pars.getProperty("NUM_PARS_SCENES"));
ind_pars[TVAO_TERRAIN] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_TERRAIN"));
ind_pars[TVAO_VEGETATION] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_VEGETATION"));
ind_pars[TVAO_ALPHA] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_ALPHA"));
ind_pars[TVAO_ELEVATION] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_ELEVATION"));
ind_pars[TVAO_SCENE_OFFSET] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_SCENES"));
// num_exaggerate
double [][] result_renders = new double [1+num_exaggerate][];
String [] result_titles = new String [result_renders.length];
result_titles[0] = "full average";
result_titles[1] = "filtered average";
result_renders[0] = terrain_average;
result_renders[1] = render;
for (int n = 2; n <= num_exaggerate; n++) {
result_titles[n]="exaggerate x "+n;
result_renders[n] = new double [full_length];
for (int i = 0; i < full_length; i++) {
result_renders[n][i] = terrain_average[i] + n * (render[i] - terrain_average[i]);
par_index = new int[TVAO_TYPES][];
for (int n = 0; n < par_index.length; n++) {
if (n < TVAO_SCENE_OFFSET) {
par_index[n] = new int[image_length];
} else {
par_index[n] = new int[num_scenes]; // same as when creating original
}
Arrays.fill(par_index[n], -1);
}
// private int [][] par_index; // indices - [0..4][full_pixel] - same as for tvao, value - parameter index
// private int [][] par_rindex; // parameter -> pair of type (0..4) and full window pixel index
int [] par_nums = {
num_pars[TVAO_TERRAIN],
num_pars[TVAO_VEGETATION],
num_pars[TVAO_ALPHA],
num_pars[TVAO_ELEVATION],
num_pars[TVAO_SCENE_OFFSET]};
ShowDoubleFloatArrays.showArrays(
combined_offsets,
full.width,
full.height,
true,
ref_scene+"-scene_offsets",
titles_scenes);
ShowDoubleFloatArrays.showArraysHyperstack(
preview_data, // double[][][] pixels,
full.width, // int width,
ref_scene+"-preview_segments", // 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
top_titles, // String [] frame_titles, // frame titles or null
true); // boolean show)
ShowDoubleFloatArrays.showArrays(
result_renders,
full.width,
full.height,
true,
ref_scene+"-"+render_title,
result_titles);
String [] synt_titles = {"render","synthetic", "synt_terrain", "synt vegetation","masked render", "render"};
final double [][][] synt_data = new double [synt_titles.length][num_scenes][];
final double terrain_max = alpha_min;
final double vegetation_min = 0.5; // alpha_max;
String synt_name = "synthetic-terr"+terrain_max+"-veg"+vegetation_min;
synt_data[0] = terrain_rendered;
synt_data[5] = terrain_rendered;
double [][][] synt_tv= renderSynthetic(
preview_data[2][accum_indx], // final double [] alpha,
combined_offsets, // final double [][] scene_offsets, // subtract if not null
terrain_max, // final double terrain_max, // below - terrain is visible
vegetation_min, // final double vegetation_min, // above - vegetation is visible
boost_parallax, // final double boost_parallax, // increase weights of scenes with high parallax relative to the reference one
max_parallax); //final double max_parallax) {
synt_data[2] = synt_tv[0];
synt_data[3] = synt_tv[1];
/*
for (int nscene = 0; nscene < num_scenes; nscene++) { // use threads
synt_data[1][nscene] = synt_tv[0][nscene].clone();
synt_data[4][nscene] = terrain_rendered[nscene].clone();
double [] veg_scene = synt_tv[1][nscene];
for (int i = 0; i < veg_scene.length; i++) {
if (!Double.isNaN(veg_scene[i])) {
synt_data[1][nscene][i] = veg_scene[i];
synt_data[4][nscene][i] = Double.NaN;
int [][] samples_pointers_tmp = new int [SAMPLES_SIZE][3];
update_samples_pointers: {
for (int nsp = 0; nsp < SAMPLES_SIZE; nsp++) {
for (int i = 0; i < samples_pointers_tmp[nsp].length; i++) {
if (imp_pars.getProperty("SAMPLES_POINTERS_"+nsp+"_"+i) == null) {
System.out.println("restoreParametersFile(): Incompatible samples_pointers[][], will not update");
break update_samples_pointers;
}
samples_pointers_tmp[nsp][i] = Integer.parseInt((String) imp_pars.getProperty("SAMPLES_POINTERS_"+nsp+"_"+i));
}
}
*/
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nscene = ai.getAndIncrement(); nscene < num_scenes; nscene = ai.getAndIncrement()) {
synt_data[1][nscene] = synt_tv[0][nscene].clone();
synt_data[4][nscene] = terrain_rendered[nscene].clone();
double [] veg_scene = synt_tv[1][nscene];
for (int i = 0; i < veg_scene.length; i++) {
if (!Double.isNaN(veg_scene[i])) {
synt_data[1][nscene][i] = veg_scene[i];
synt_data[4][nscene][i] = Double.NaN;
samples_pointers = samples_pointers_tmp;
}
// samples_pointers[SAMPLES_TOTAL][0] = total number of parameters
int num_pars = 0;
for (int n = 0; n < TVAO_TYPES; n++) {
num_pars += par_nums[n];
}
parameters_vector = new double [num_pars];
par_rindex = new int [num_pars][2];
for (int n = 0; n < TVAO_TYPES; n++) {
for (int indx = 0; ((indx < indices[n].length) && (indx < par_index[n].length)); indx++) { // woi_veg
int findx = indx;
int pindx = indices[n][indx];
if (n < TVAO_SCENE_OFFSET) {
int x = (indx % woi_veg.width) + woi_veg.x;
int y = (indx / woi_veg.width) + woi_veg.y;
findx = x + y * full.width;
}
par_index[n][findx] = pindx;
if (pindx >= 0) { // always? - not!
parameters_vector[pindx] = data[n][indx];
par_rindex[pindx][0] = n;
par_rindex[pindx][1] = findx;
}
}
};
}
ImageDtt.startAndJoin(threads);
ShowDoubleFloatArrays.showArraysHyperstack(
synt_data, // double[][][] pixels,
full.width, // int width,
ref_scene+"-"+synt_name, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scenes, // String [] titles, // all slices*frames titles or just slice titles or null
synt_titles, // String [] frame_titles, // frame titles or null
true); // boolean show)
// TODO: build other data structures and make instance consistent, without it this does not allow reading from file
}
return data;
}
return;
}
public double [][][] renderSynthetic(
final double [] alpha,
......@@ -4926,38 +4907,6 @@ public class VegetationLMA {
}
public static double [] overlapCosineWindow(
Rectangle woi,
int width){
if (width > woi.width/2) {
width = woi.width/2;
}
if (width > woi.height/2) {
width = woi.height/2;
}
double [] window = new double [woi.width*woi.height];
double [] wnd_x = new double [woi.width];
double [] wnd_y = new double [woi.height];
Arrays.fill(wnd_x, 1.0);
Arrays.fill(wnd_y, 1.0);
for (int i = 0; i < width; i++) {
double w = 0.5* (1 - Math.cos(Math.PI * (i + 0.5) / width));
wnd_x[i] = w;
wnd_x[woi.width - i - 1] = w;
wnd_y[i] = wnd_x[i];
wnd_y[woi.height - i - 1] = w;
}
int indx = 0;
for (int y = 0; y < woi.height; y++) {
for (int x = 0; x < woi.width; x++) {
window[indx++] = wnd_x[x] * wnd_y[y];
}
}
return window;
}
public VegetationSegment [] readAllSegments(
String dir_path,
String suffix) {
......@@ -4994,7 +4943,8 @@ public class VegetationLMA {
woi, // Rectangle woi,
other_pars[0], // terrain_offset,
tvao[TVAO_SCENE_OFFSET], // double [] scene_offsets,
new double [][] {tvao[0],tvao[1],tvao[2],tvao[2]}); // double [][] tva) {} {}
new double [][] {tvao[0],tvao[1],tvao[2],tvao[2]}, // double [][] tva) {} {}
null); // double [] confidence
}
// sort in line-scan order
Arrays.sort(segments, new Comparator<VegetationSegment>() {
......@@ -5008,32 +4958,102 @@ public class VegetationLMA {
}
public void readParametersFromImage(
String path,
double [] vector,
boolean extra,
int gap) {
int [][] indices = getParamDebugIndices (
extra, // boolean extra,
gap);
ImagePlus imp_pars = new ImagePlus (path);
if (imp_pars.getWidth()==0) {
throw new IllegalArgumentException("Could not read "+path);
}
// int woi_width3=woi.width*3 + 2 * gap;
// int woi_width4=woi_veg.width*4 + 3 * gap;
int num_img_cols = 5; // 4;
int woi_width= woi_veg.width * num_img_cols + (num_img_cols-1) * gap;
public VegetationSegment [] readAllSegments(
String dir_path,
String suffix,
double transparency_opaque,
double transparency_pedestal,
double transparency_frac,
double transparency_dist,
double transparency_pow,
double transparency_gb,
int debugLevel,
boolean debug_save_improved, // Save debug image after successful LMA step.");
boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step.");
FileFilter parFileFilter = new FileFilter()
{
//Override accept method
public boolean accept(File file) {
int height = indices.length/woi_width;
if ((woi_width != imp_pars.getWidth()) || (height != imp_pars.getHeight())) {
throw new IllegalArgumentException("Read image size does not match required: ("+imp_pars.getWidth()+"x"+imp_pars.getHeight()+
") != ("+woi_width+"x"+height+")");
//if the file extension is .log return true, else false
if (file.isFile() && file.getName().endsWith(suffix+PAR_EXT)) {
return true;
}
// float [] pixels = (float[]) imp_pars.getProcessor().getPixels();
return false;
}
};
File dir = new File(dir_path);
File [] par_files = dir.listFiles(parFileFilter);
VegetationSegment [] segments = new VegetationSegment [par_files.length];
for (int n = 0; n < par_files.length; n++) {
// updates this to match file
double [][] tvao = restoreParametersFile(
par_files[n].getPath(), // String path,
debugLevel, // int debugLevel,
debug_save_improved, // boolean debug_save_improved, // Save debug image after successful LMA step.");
debug_save_worsened); //boolean debug_save_worsened) // Save debug image after unsuccessful LMA step.");
double [] confidence = getTransparencyConfidence( // woi
null, // final double [] vector,
transparency_opaque, // final double transparency_opaque,
transparency_pedestal, // final double transparency_pedestal,
transparency_frac, // final double transparency_frac,
transparency_dist, // final double transparency_dist,
transparency_pow, // final double transparency_pow,
transparency_gb, // final double transparency_gb,
null); // transparency_data); // final double [][][] transparency_data) { // double [3][][]
segments[n] = new VegetationSegment(
par_files[n].getPath(), // String path,
woi_veg, // Rectangle woi_veg,
woi, // Rectangle woi,
terrain_offset, // terrain_offset,
tvao[TVAO_SCENE_OFFSET], // double [] scene_offsets,
new double [][] {tvao[0],tvao[1],tvao[2],tvao[3]}, // double [][] tva) {} {}
confidence); // double [] confidence
if (debugLevel>-2) {
Runtime runtime = Runtime.getRuntime();
runtime.gc();
System.out.println("----- readAllSegments() segment "+(n+1)+" (of "+par_files.length+") --- Free memory="+runtime.freeMemory()+" (of "+runtime.totalMemory()+")");
}
}
// sort in line-scan order
Arrays.sort(segments, new Comparator<VegetationSegment>() {
@Override
public int compare(VegetationSegment lhs, VegetationSegment rhs) {
return (rhs.woi.y > lhs.woi.y) ? -1 : (rhs.woi.y < lhs.woi.y) ? 1 :
((rhs.woi.x > lhs.woi.x) ? -1 : (rhs.woi.x < lhs.woi.x) ? 1 : 0); // increasing
}
});
return segments;
}
public void readParametersFromImage(
String path,
double [] vector,
boolean extra,
int gap) {
int [][] indices = getParamDebugIndices (
extra, // boolean extra,
gap);
ImagePlus imp_pars = new ImagePlus (path);
if (imp_pars.getWidth()==0) {
throw new IllegalArgumentException("Could not read "+path);
}
// int woi_width3=woi.width*3 + 2 * gap;
// int woi_width4=woi_veg.width*4 + 3 * gap;
int num_img_cols = 5; // 4;
int woi_width= woi_veg.width * num_img_cols + (num_img_cols-1) * gap;
int height = indices.length/woi_width;
if ((woi_width != imp_pars.getWidth()) || (height != imp_pars.getHeight())) {
throw new IllegalArgumentException("Read image size does not match required: ("+imp_pars.getWidth()+"x"+imp_pars.getHeight()+
") != ("+woi_width+"x"+height+")");
}
// float [] pixels = (float[]) imp_pars.getProcessor().getPixels();
int num_slices = imp_pars.getStack().getSize();
float [] pixels = (float[]) imp_pars.getStack().getPixels(num_slices); // last slice
......@@ -5384,8 +5404,270 @@ public class VegetationLMA {
}
public double [] getTransparencyConfidence(
final double [] vector,
final double transparency_opaque,
final double transparency_pedestal,
final double transparency_frac,
final double transparency_dist,
final double transparency_pow,
final double transparency_gb,
final double [][][] transparency_data) { // double [3][][]
double [][] transparency = getTransparency((vector==null)? parameters_vector:vector);
double [][] transparency_weights_preblur = getTransparenctWeights( // should be no NaNs!
transparency, // final double [][] transparency,
transparency_opaque, // final double transparency_opaque,
transparency_pedestal, // final double transparency_pedestal,
transparency_frac, // final double transparency_frac,
transparency_dist, // final double transparency_dist); //0 - do not apply
transparency_pow); // final double transparency_pow){
final double [][] transparency_weights = new double [num_scenes][];
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
if (transparency_gb <= 0) {
for (int n = 0; n < transparency_weights.length; n++) {
transparency_weights[n] = transparency_weights_preblur[n];
}
} else {
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
DoubleGaussianBlur gb = new DoubleGaussianBlur();
for (int nScene = ai.getAndIncrement(); nScene < num_scenes; nScene = ai.getAndIncrement()) {
transparency_weights[nScene] = transparency_weights_preblur[nScene].clone();
gb.blurDouble(
transparency_weights[nScene], //
woi.width, // terrain woi
woi.height,
transparency_gb, // double sigmaX,
transparency_gb, // double sigmaY,
0.01); // double accuracy)
}
}
};
}
ImageDtt.startAndJoin(threads);
}
if (transparency_data != null) {
transparency_data[0] = transparency;
transparency_data[1] = transparency_weights_preblur;
transparency_data[2] = transparency_weights;
}
double [] confidence = getTerrainConfidence(transparency_weights); // blurred
return confidence;
}
public void applyTransparency(
public double [] applyTransparency(
final double [] vector,
final double transparency_opaque,
final double transparency_pedestal,
final double transparency_frac,
final double transparency_dist,
final double transparency_pow,
final double transparency_gb,
final double transparency_boost_in,
final boolean recalc_average,
String prefix) {
this.recalc_average = recalc_average;
final int woi_length = woi.width*woi.height;
final double transparency_boost = Math.max(transparency_boost_in, 1.0);
boolean use_hf = (y_src_hf != null);
int y_avg_len = y_vector.length - (y_src.length + ((y_src_hf != null) ? y_src_hf.length : 0));
double [][][] transparency_data = new double [3][][];
double [] confidence = getTransparencyConfidence(
vector, // final double [] vector,
transparency_opaque, // final double transparency_opaque,
transparency_pedestal, // final double transparency_pedestal,
transparency_frac, // final double transparency_frac,
transparency_dist, // final double transparency_dist,
transparency_pow, // final double transparency_pow,
transparency_gb, // final double transparency_gb,
transparency_data); // final double [][][] transparency_data) { // double [3][][]
double [][] transparency = transparency_data[0];
double [][] transparency_weights_preblur = transparency_data[1];
double [][] transparency_weights = transparency_data[2];
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
double max_confidence = 0;
for (int i = 0; i < confidence.length; i++) if (confidence[i] > max_confidence) {
max_confidence = confidence[i];
}
double max_scaled = max_confidence / transparency_boost;
final double [] scales = new double [confidence.length];
for (int i = 0; i < confidence.length; i++) {
if (confidence[i] >= max_scaled) {
scales[i] = max_confidence / confidence[i];
} else {
scales[i] = transparency_boost;
}
}
final double [][] scaled_weights = new double [num_scenes][woi_length];
// normalize weights for confidence
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nScene = ai.getAndIncrement(); nScene < num_scenes; nScene = ai.getAndIncrement()) {
for (int windx = 0; windx < woi_length; windx++) {
scaled_weights[nScene][windx] = transparency_weights[nScene][windx] * scales[windx];
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (prefix != null) {
String title =prefix+String.format("-opq%3f-pdst%5f-frac%3f-dst%2f-pwr%4f-gb%4f-boost%4f-avg%1d.tiff",
transparency_opaque,transparency_pedestal,transparency_frac,
transparency_dist,transparency_pow,transparency_gb, transparency_boost, recalc_average?1:0);
int nscenes = transparency.length;
String [] titles_top = {"transparency","pre-blur","weights","normalized"};
String [] titles = new String[nscenes + 1];
double [][][] dbg_img = new double[titles_top.length][titles.length][]; // woi_length];
dbg_img[0][nscenes] = new double[woi_length];
dbg_img[1][nscenes] = getTerrainConfidence(transparency_weights_preblur);
dbg_img[2][nscenes] = getTerrainConfidence(transparency_weights);
dbg_img[3][nscenes] = scales;
for (int nscene = 0; nscene < transparency.length; nscene++) {
titles[nscene] = "scene-"+nscene;
dbg_img[0][nscene] = transparency[nscene];
dbg_img[1][nscene] = transparency_weights_preblur[nscene];
dbg_img[2][nscene] = transparency_weights[nscene];
dbg_img[3][nscene] = scaled_weights[nscene];
for (int wpix = 0;wpix < woi_length; wpix++) {
if (dbg_img[0][nscenes][wpix] > transparency[nscene][wpix]) { // takes care of NaN
transparency[nscene][wpix] = dbg_img[0][nscenes][wpix];
}
// dbg_img[0][nscenes][wpix] = Math.max(transparency[nscene][wpix],dbg_img[0][nscenes][wpix]);
}
}
titles[nscenes] = "max/conf";
ShowDoubleFloatArrays.showArraysHyperstack(
dbg_img, // double[][][] pixels,
woi.width, // int width,
title, // "terrain_vegetation_render.tiff", // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles, // String [] titles, // all slices*frames titles or just slice titles or null
titles_top, // String [] frame_titles, // frame titles or null
true); // boolean show)
}
double s = 0, ss=0;
for (int ny = 0; ny < y_src.length; ny++) {
int nscene = y_src[ny][YSRC_SCENE];
int findx = y_src[ny][YSRC_FINDEX];
int windx = getWindexFromFindex(findx);
double w = scaled_weights[nscene][windx];
if (Double.isNaN(w)) {
System.out.println("applyTransparency() 1: ny="+ny+", nscene="+nscene+", findx="+findx+", windx="+windx+", w="+w);
} else {
s += w;
}
ss += scene_weights[nscene];
}
// double s_scenes = s; // sum of all scene weight. Maybe skip scenes that do not exist?
double s_to_ss = s/ss;
if (use_hf) {
for (int ny = 0; ny < y_src_hf.length; ny++) {
int nscene = y_src_hf[ny][YSRC_SCENE];
int findx = y_src_hf[ny][YSRC_FINDEX];
int windx = getWindexFromFindex(findx);
double w = scaled_weights[nscene][windx] * hifreq_weight ;
if (Double.isNaN(w)) {
System.out.println("applyTransparency() 2: ny="+ny+", nscene="+nscene+", findx="+findx+", windx="+windx+", w="+w);
} else {
s += w;
}
}
}
// double s_y_yhf = s; //
// TODO: If using scaled_weights (in setupYVectorTransparency and getFxDerivs),
// then calculate following weights differently to keep ~ the same sum
// use recalc_average / this.recalc_average to change weights
if (y_avg_len > 0) {
for (int ny = 0; ny < y_avg_len; ny++) {
s += terrain_correction_weight; // scene_weights[nscene] is included in y_wavg and fX, jt
}
}
/// final double s0 = s;
s /= (1 - reg_weights); // *= (1+ reg_weights);s *= (1+ reg_weights);
final double k = 1.0/s; //corr_transp 10.85811847216958
weight_to_scene_weight = k * s_to_ss;
/// weight_pure = s0/s;
// final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
// final AtomicInteger ai = new AtomicInteger(0);
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nw = ai.getAndIncrement(); nw < weights.length; nw = ai.getAndIncrement()) {
if (nw < samples_pointers[SAMPLES_Y_HF][0]) { // DC differences
int ny = nw;
int nscene = y_src[ny][YSRC_SCENE];
int findx = y_src[ny][YSRC_FINDEX];
int windx = getWindexFromFindex(findx);
double w = scaled_weights[nscene][windx] * k;
if (!Double.isNaN(w)) {
weights[nw] = w;
} else {
System.out.println("weights["+nw+"]=NaN - 1");
}
} else if (nw < samples_pointers[SAMPLES_Y_AVG][0]) { // HF differences if exist
int ny = nw-y_src.length;
int nscene = y_src_hf[ny][YSRC_SCENE];
int findx = y_src_hf[ny][YSRC_FINDEX];
int windx = getWindexFromFindex(findx);
double w = scaled_weights[nscene][windx] * k * hifreq_weight; // scene_weights[nscene] * k * hifreq_weight;
if (!Double.isNaN(w)) {
weights[nw] = w;
} else {
System.out.println("weights["+nw+"]=NaN - 2");
}
} else if (nw < samples_pointers[SAMPLES_EXTRA][0]) { // y_wavg if exists
weights[nw] = k * terrain_correction_weight;
if (Double.isNaN(weights[nw])) {
System.out.println("weights["+nw+"]=NaN - 3");
}
/*
} else {
weights[nw] = reg_sample_weight;
if (Double.isNaN(weights[nw])) {
System.out.println("weights["+nw+"]=NaN - 4");
}
*/
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (y_src_hf != null) { // set average offset y - either old way with scene_weights[nscene] or new way with weights[ny]
setupYVectorTransparency();
}
if (prefix != null) {
double sw = 0;
for (int n = 0; n < (samples_pointers.length -1); n++) {
double swn = 0;
for (int i = samples_pointers[n][0]; i < (samples_pointers[n][0]+samples_pointers[n][1]); i++){
swn+= weights[i];
}
sw += swn;
System.out.println("sum weights["+n+"] = "+swn+", total = "+sw);
}
}
return confidence;
}
public double [] applyTransparency_old(
final double [] vector,
final double transparency_opaque,
final double transparency_pedestal,
......@@ -5438,6 +5720,7 @@ public class VegetationLMA {
ImageDtt.startAndJoin(threads);
}
double [] confidence = getTerrainConfidence(transparency_weights); // blurred
double max_confidence = 0;
for (int i = 0; i < confidence.length; i++) if (confidence[i] > max_confidence) {
max_confidence = confidence[i];
......@@ -5486,7 +5769,10 @@ public class VegetationLMA {
dbg_img[2][nscene] = transparency_weights[nscene];
dbg_img[3][nscene] = scaled_weights[nscene];
for (int wpix = 0;wpix < woi_length; wpix++) {
dbg_img[0][nscenes][wpix] = Math.max(transparency[nscene][wpix],dbg_img[0][nscenes][wpix]);
if (dbg_img[0][nscenes][wpix] > transparency[nscene][wpix]) { // takes care of NaN
transparency[nscene][wpix] = dbg_img[0][nscenes][wpix];
}
// dbg_img[0][nscenes][wpix] = Math.max(transparency[nscene][wpix],dbg_img[0][nscenes][wpix]);
}
}
titles[nscenes] = "max/conf";
......@@ -5608,10 +5894,9 @@ public class VegetationLMA {
System.out.println("sum weights["+n+"] = "+swn+", total = "+sw);
}
}
return;
return confidence;
}
private void setupYVector(
boolean use_terr_corr,
double [] scene_weights) {
......@@ -6566,7 +6851,7 @@ public class VegetationLMA {
}
ImageDtt.startAndJoin(threads);
if (abad_warp.get() > 0) {
System.out.println("getValidScenesPixels(): removing "+abad_warp.get()+" scenes as the have warp for used vegetation pixels > "+
System.out.println("getValidScenesPixels(): removing "+abad_warp.get()+" scenes as they have warp for used vegetation pixels > "+
max_warp);
for (int nscene = 0; nscene < num_scenes; nscene++) if (valid_prewarp[nscene] && !valid_scenes[nscene]){
System.out.println("Removing scene "+nscene);
......@@ -6878,4 +7163,55 @@ public class VegetationLMA {
return data_full;
}
public static double getProperty(
ImagePlus imp,
String name,
double dflt) {
if (imp.getProperty(name) == null) return dflt;
else return Double.parseDouble((String) imp.getProperty(name));
}
public static int getProperty(
ImagePlus imp,
String name,
int dflt) {
if (imp.getProperty(name) == null) return dflt;
else return Integer.parseInt((String) imp.getProperty(name));
}
public static boolean getProperty(
ImagePlus imp,
String name,
boolean dflt) {
if (imp.getProperty(name) == null) return dflt;
else return Boolean.parseBoolean((String) imp.getProperty(name));
}
public static double [] getProperty(
ImagePlus imp,
String [] names,
double [] current) {
for (int i = 0; i < names.length; i++) {
current[i] = getProperty(imp, names[i], current[i]);
}
return current;
}
public static int [] getProperty(
ImagePlus imp,
String [] names,
int [] current) {
for (int i = 0; i < names.length; i++) {
current[i] = getProperty(imp, names[i], current[i]);
}
return current;
}
public static boolean [] getProperty(
ImagePlus imp,
String [] names,
boolean [] current) {
for (int i = 0; i < names.length; i++) {
current[i] = getProperty(imp, names[i], current[i]);
}
return current;
}
}
......@@ -1350,8 +1350,32 @@ public class VegetationModel {
};
}
ImageDtt.startAndJoin(threads);
return;
}
public static void unsharpMask(
final double [] data,
final int width,
final double um_sigma,
final double um_weight) {
final int height = data.length / width;
double [] data_orig = new double [width * height];
System.arraycopy(data, 0, data_orig, 0, data_orig.length);
(new DoubleGaussianBlur()).blurDouble(
data, //
width,
height,
um_sigma, // double sigmaX,
um_sigma, // double sigmaY,
0.01); // double accuracy)
for (int i = 0; i < data_orig.length; i++) {
data[i] = data_orig[i] - um_weight * data[i];
}
}
public static Rectangle nextTileWoi(
Rectangle enclosing,
Rectangle step,
......@@ -1443,10 +1467,10 @@ public class VegetationModel {
// int
step_restore= par_restore? clt_parameters.imp.terr_step_restore : 0;
boolean um_en = clt_parameters.imp.terr_um_en; // true;
double um_sigma = clt_parameters.imp.terr_um_sigma; // 1.0;
// boolean um_en = clt_parameters.imp.terr_um_en; // true;
double um_sigma = clt_parameters.imp.terr_um_sigma; // 1.0; // use for render
double um_weight = clt_parameters.imp.terr_um_weight; // 0.8;
double nan_tolerance = um_en ? clt_parameters.imp.terr_nan_tolerance : 0; // 0.001;
double nan_tolerance = 0; // um_en ? clt_parameters.imp.terr_nan_tolerance : 0; // 0.001;
int nan_grow = clt_parameters.imp.terr_nan_grow; // 20;
int shrink_veget = clt_parameters.imp.terr_shrink_veget; // 20;
int shrink_terrain = clt_parameters.imp.terr_shrink_terrain; // 20;
......@@ -1485,7 +1509,7 @@ public class VegetationModel {
double alpha_init_max= clt_parameters.imp.terr_alpha_init_max; // 0.9; // Initial alpha: fraction for opaque
double alpha_init_offs= clt_parameters.imp.terr_alpha_init_offs; // 0.01; // Initial alpha: opaque/transparent offset from 1.0/0.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; // alpha quadratic growing loss for when out of [0,1] range
double alpha_loss_lin = clt_parameters.imp.terr_alpha_loss_lin; // alpha linear growing loss for when out of [0,1] range and below minimal vegetation alpha
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;
......@@ -1499,6 +1523,8 @@ public class VegetationModel {
double alpha_push_center = clt_parameters.imp.terr_alpha_weight_center; // 1.5; // weight of center alpha pixel relative to each of the 4 ortho ones
boolean alpha_en_holes = clt_parameters.imp.terr_en_holes; // true; // false; // true;
double alpha_mm_hole = clt_parameters.imp.terr_alpha_mm_hole; // 0.1; // NaN to disable. Local "almost minimum" (lower than this fraction between min and max neighbor) is not subject to alpha_lpf
double alpha_diff_hole = clt_parameters.imp.terr_alpha_diff_hole; // 0.01; Minimal alpha difference between min and max neighbor to be considered a hole
double terr_lpf = clt_parameters.imp.terr_terr_lpf; // 0.1; // 0.15; /// 0.2; /// 0.1; // pull terrain to average of 4 neighbors (very small)
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 elevation_lpf = clt_parameters.imp.terr_elev_lpf;
......@@ -1573,13 +1599,13 @@ public class VegetationModel {
boolean recalc_average = clt_parameters.imp.terr_recalc_average ; //false; // apply transparency to average mismatch
boolean debug_save_improved = clt_parameters.imp.terr_debug_improved;
boolean debug_save_worsened = clt_parameters.imp.terr_debug_worsened;
boolean restore_mode = false;
// boolean restore_mode = false;
boolean save_par_files = true; // false;
String segments_dir = getSegmentsDir(segments_sub);
boolean read_pars = false; // true; /// false; /// true; // false; // true;
// debug feature to read to continue - needs to be cleaned up/replaced
String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-al100.0-alo0.0-alp10.0-alin-tl0.2-vl0.01-tp0.01-vp0.01-bp5.0-um1.0_0.8.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-al100.0-alo0.0-alp10.0-alin-tl0.2-vl0.01-tp0.01-vp0.01-bp5.0-um1.0_0.8.tiff";
boolean last_run = false;
......@@ -1659,7 +1685,7 @@ public class VegetationModel {
// maybe it is better to set NaN before UM and then use UM with fillNaN
/*
if (um_en) { // not used anymore
double [][] um_data = new double [terrain_scenes_render.length+2][];
System.arraycopy(terrain_scenes_render, 0, um_data, 0, terrain_scenes_render.length);
......@@ -1671,7 +1697,7 @@ public class VegetationModel {
um_sigma, // final double um_sigma,
um_weight); // final double um_weight)
}
*/
double dir_sigma = 16;
/*
vegetation_warp_md = new double [vegetation_warp.length][][];
......@@ -2030,12 +2056,31 @@ public class VegetationModel {
if (run_combine) {
/*
VegetationSegment [] segments = vegetationLMA.readAllSegments(
segments_dir, // String dir_path)
segments_suffix); // String suffix);
vegetationLMA.combineSegments(
*/
boolean crop_combo = true;
VegetationSegment [] segments = vegetationLMA.readAllSegments(
segments_dir, // String dir_path)
segments_suffix, // String suffix);
transparency_opaque, // double transparency_opaque,
transparency_pedestal, // double transparency_pedestal,
transparency_frac, // double transparency_frac,
transparency_dist, // double transparency_dist,
transparency_pow, // double transparency_pow,
transparency_gb, // double transparency_gb,
debugLevel, // int debugLevel,
debug_save_improved, // boolean debug_save_improved, // Save debug image after successful LMA step.");
debug_save_worsened); // boolean debug_save_worsened) { // Save debug image after unsuccessful LMA step.");
VegetationSegment.combineSegments(
vegetationLMA, // VegetationLMA vegetationLMA,
segments,
crop_combo, // boolean crop_combo,
border_width, // int width);
um_sigma, // final double um_sigma,
um_weight, //final double um_weight,
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
......@@ -2059,7 +2104,8 @@ public class VegetationModel {
System.out.println ("===== No WOIs to process left, exiting");
break;
}
String par_path = restore_mode? "RESTORE": (read_pars ? parameters_path : null);
// String par_path = restore_mode? "RESTORE": (read_pars ? parameters_path : null);
// String par_path = read_pars ? parameters_path : null;
if (tile_woi) {
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+").");
......@@ -2073,7 +2119,6 @@ public class VegetationModel {
max_warp, // final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this
max_offset, // final int max_offset, // maximal "elevation" to consider
elevation_radius, // final double elevation_radius, // Radius of elevation/vegetation influence.
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
terrain_correction,// final double terrain_correction,
fit_terr, // final boolean adjust_terr,
......@@ -2095,6 +2140,7 @@ public class VegetationModel {
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
alpha_diff_hole,//final double alpha_diff_hole, // 0.01; // Minimal alpha difference between min and max neighbor to be considered a hole
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)
elevation_lpf, // final double elevation_lpf,
......@@ -2110,9 +2156,9 @@ public class VegetationModel {
scenes_pull0, // final double scenes_pull0,
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,
// 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);
debug_save_improved, // final boolean debug_save_improved, // Save debug image after successful LMA step.");
debug_save_worsened);// final boolean debug_save_worsened) // Save debug image after unsuccessful LMA step.");
......@@ -2137,7 +2183,7 @@ public class VegetationModel {
}
int num_iter = num_iters[step_restore]; //
if (par_restore) { // always use last number of iterations - not anymore
par_path = parameters_dir;
String par_path = parameters_dir;
if (!par_path.endsWith(Prefs.getFileSeparator())) {
par_path+=Prefs.getFileSeparator();
}
......@@ -2167,6 +2213,7 @@ public class VegetationModel {
//num_iters.length
}
// old
/*
if ("RESTORE".equals(par_path)) {
System.out.println("Reading fitted parameters from file");
if (save_par_files) {
......@@ -2179,7 +2226,7 @@ public class VegetationModel {
continue;
}
}
*/
if ((show_final_result) && (debugLevel > -2)) { // 0)) {
String reconstructed_title = reference_scene+"-reconstructed-pre-step"+step_restore; //
vegetationLMA.showYfX(
......
package com.elphel.imagej.vegetation;
import java.awt.Rectangle;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.tileprocessor.ImageDtt;
import com.elphel.imagej.tileprocessor.QuadCLT;
public class VegetationSegment {
public Rectangle woi_veg;
public Rectangle woi;
public double [] scene_offsets;
public double [][] tva;
public double [][] tva; // woi_veg
public double terrain_offset;
public double [] confidence; // woi
public String path;
public VegetationSegment(
String path,
......@@ -15,12 +22,423 @@ public class VegetationSegment {
Rectangle woi,
double terrain_offset,
double [] scene_offsets, // has NaNs
double [][] tva) {
double [][] tva,
double [] confidence) {
this.path = path;
this.woi = woi;
this.woi_veg = woi_veg;
this.scene_offsets = scene_offsets;
this.tva = tva;
this.terrain_offset = terrain_offset;
this.confidence = confidence;
}
public static Rectangle getBounds( // [0] - woi, [1] - woi_weg
VegetationSegment [] segments,
boolean use_veg) {
Rectangle bounds = null;
for (VegetationSegment segment:segments) {
Rectangle selected_woi = use_veg ?segment.woi_veg : segment.woi;
if (bounds == null) {
bounds = new Rectangle(selected_woi);
} else {
bounds.add(selected_woi);
}
}
return bounds;
}
public static void combineSegments(
VegetationLMA vegetationLMA,
VegetationSegment [] segments,
boolean crop_combo,
int width,
final double um_sigma,
final double um_weight,
final boolean render_open, // render open areas (no vegetation offset)
final boolean render_no_alpha, // render where no opacity is available
final double alpha_min, // below - completely transparent vegetation
final double alpha_max, // above - completely opaque
final double weight_opaque, // render through completely opaque vegetation
final double boost_parallax, // increase weights of scenes with high parallax relative to the reference one
final double max_parallax,
final int num_exaggerate) { // show amplified difference from filtering
//FIXME: Handle woi separately!
final Rectangle combo_woi = crop_combo? VegetationSegment.getBounds(segments, false):vegetationLMA.getFull();
final Rectangle combo_woi_veg = crop_combo? VegetationSegment.getBounds(segments, true): vegetationLMA.getFull();
final Rectangle out_woi = new Rectangle(combo_woi);
out_woi.add(combo_woi_veg);
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
double ksigma = 1.0;
double min_sw = 1e-4;
int out_length = out_woi.width*out_woi.height;
int accum_indx = segments.length;
String [] top_titles = {"terrain","vegetation","alpha","elevation","confidence"};
double [][][] preview_data = new double [top_titles.length][accum_indx+1][out_length];
String [] titles = new String[accum_indx+1];
for (int ns = 0; ns < segments.length; ns++) {
Rectangle woi = segments[ns].woi; // for confidence and limits for terrain
Rectangle woi_veg = segments[ns].woi_veg;
titles[ns] = woi.toString();
int woi_length = woi.width * woi.height;
int woi_veg_length = woi_veg.width * woi_veg.height;
double [][] woi_tva = segments[ns].tva;
double [] confidence = segments[ns].confidence;
for (int t = 0; t < top_titles.length; t++) {
Arrays.fill(preview_data[t][ns], Double.NaN); // java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
switch (t) {
case 0: // terrain cut out from woi_tva
for (int windx = 0; windx < woi_length; windx++) {
int wx = windx % woi.width;
int wy = windx / woi.width;
int wxsrc = wx + woi.x-woi_veg.x; // >= 0
int wysrc = wy + woi.y-woi_veg.y; // >= 0
int wsrc = wxsrc + wysrc * woi_veg.width; // index in woi_tva[t][windx];
int x = wx + woi.x - out_woi.x;
int y = wy + woi.y - out_woi.y;
int indx = x + y * out_woi.width;
preview_data[t][ns][indx] = woi_tva[t][wsrc];
}
break;
case 1: // vegetation
case 2: // alpha
case 3: // vegetation
for (int windx = 0; windx < woi_veg_length; windx++) {
int x = windx % woi_veg.width + woi_veg.x - out_woi.x;
int y = windx / woi_veg.width + woi_veg.y - out_woi.y;
int indx = x + y * out_woi.width;
preview_data[t][ns][indx] = woi_tva[t][windx];
}
break;
case 4: // confidence
for (int windx = 0; windx < woi_length; windx++) {
int x = windx % woi.width + woi_veg.x - out_woi.x;
int y = windx / woi.width + woi_veg.y - out_woi.y;
int indx = x + y * out_woi.width;
preview_data[t][ns][indx] = confidence[windx];
}
break;
}
}
}
titles[accum_indx] = "accum";
double [][] sum_w = new double [preview_data.length][out_length];
double [][] sum_wd = new double [preview_data.length][out_length];
for (int ns = 0; ns < segments.length; ns++) {
Rectangle woi = segments[ns].woi;
int woi_length = woi.width*woi.height;
// double [][] woi_tva = segments[ns].tva;
double [] wnd = overlapCosineWindow (woi, width);
for (int windx = 0; windx < woi_length; windx++) {
int x = windx % woi.width + woi.x - out_woi.x;
int y = windx / woi.width + woi.y - out_woi.y;
int indx = x + y * out_woi.width;
for (int t = 0; t < preview_data.length; t++) {
double d = preview_data[t][ns][indx];
if (!Double.isNaN(d)) {
double w = wnd[windx];
sum_w [t][indx] += w;
sum_wd[t][indx] += w * d ;
}
}
}
}
for (int t = 0; t < preview_data.length; t++) {
for (int i = 0; i < out_length; i++) {
if (sum_w[t][i] == 0) {
preview_data[t][accum_indx][i] = Double.NaN;
} else {
preview_data[t][accum_indx][i] = sum_wd[t][i]/sum_w[t][i];
}
}
}
VegetationModel vegetationModel = vegetationLMA.getModel();
String ref_scene = vegetationModel.reference_scene;
ShowDoubleFloatArrays.showArraysHyperstack(
preview_data, // double[][][] pixels,
out_woi.width, // int width,
ref_scene+"-preview_segments", // 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
top_titles, // String [] frame_titles, // frame titles or null
true); // boolean show)
double [] terrain_reference = crop(
vegetationModel.terrain_scenes_render[vegetationModel.reference_index],
vegetationLMA.getFull().width,
out_woi);
double [] terrain_accumulated = crop(
vegetationModel.terrain_average_render,
vegetationLMA.getFull().width,
out_woi);
double [] terrain_um = terrain_accumulated.clone();
for (int i = 0; i < terrain_um.length; i++) {
if (Double.isNaN(terrain_um[i])) {
terrain_um[i] = 0;
}
}
VegetationModel.unsharpMask(
terrain_um, // final double [] data,
out_woi.width, // final int width,
um_sigma, // final double um_sigma,
um_weight); // final double um_weight)
String [] result_titles = {"ref_render", "terrain_accum",String.format("terrain_accum_UM%5.2f-%4.2f",um_sigma,um_weight),"terrain"};
double [][] result_img = {terrain_reference,terrain_accumulated,terrain_um,preview_data[0][accum_indx]};
// ref_scene+"-result-terrain"
ShowDoubleFloatArrays.showArrays(
result_img,
out_woi.width,
out_woi.height,
true,
ref_scene+"-result_terrain",
result_titles);
// Combine offsets per scene
/*
double [][] combined_offsets = new double [num_scenes][full_length];
String [] titles_scenes = new String [num_scenes];
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [] sw = new double [full_length];
for (int nscene = ai.getAndIncrement(); nscene < num_scenes; nscene = ai.getAndIncrement()) {
titles_scenes[nscene] = "scene "+nscene;
double [] swd = combined_offsets[nscene];
Arrays.fill(sw, 0);
for (int ns = 0; ns < segments.length; ns++) {
Rectangle woi_veg = segments[ns].woi;
int woi_length = woi_veg.width*woi_veg.height;
double scene_offset = segments[ns].scene_offsets[nscene];
if (!Double.isNaN(scene_offset)) {
double [] wnd = overlapCosineWindow (woi, width);
for (int windx = 0; windx < woi_length; windx++) {
int x = windx % woi_veg.width + woi_veg.x;
int y = windx / woi_veg.width + woi_veg.y;
int indx = x + y * full.width;
for (int t = 0; t < preview_data.length; t++) {
double w = wnd[windx];
sw [indx] += w;
swd[indx] += w * scene_offset ;
}
}
}
}
(new DoubleGaussianBlur()).blurDouble(
sw, //
full.width,
full.height,
ksigma*width, // double sigmaX,
ksigma*width, // double sigmaY,
0.01); // double accuracy)
(new DoubleGaussianBlur()).blurDouble(
swd, //
full.width,
full.height,
ksigma*width, // double sigmaX,
ksigma*width, // double sigmaY,
0.01); // double accuracy)
for (int i = 0; i < full_length; i++) {
if (sw[i] < min_sw) {
swd[i] = Double.NaN;
} else {
swd[i] /= sw[i];
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
double [][] tva = {preview_data[0][accum_indx],preview_data[1][accum_indx],preview_data[2][accum_indx]};
vegetationModel.setTVA(tva);
// new String[] {"full average", "filtered average"});
// String ref_scene = vegetationModel.reference_scene;
String render_title = "render-ro_"+render_open+"-rna_"+render_no_alpha+"-amn"+alpha_min+"-amx"+alpha_max+"-wo"+weight_opaque+"-bp"+boost_parallax+".tiff";
double [] render = renderWithAlpha(
preview_data[2][accum_indx], // final double [] alpha,
combined_offsets, // final double [][] scene_offsets, // subtract if not null
render_open, // final boolean render_open, // render open areas (no vegetation offset)
render_no_alpha, // final boolean render_no_alpha, // render where no opacity is available
alpha_min, // final double alpha_min, // below - completely transparent vegetation
alpha_max, // final double alpha_max, // above - completely opaque
weight_opaque, // final double weight_opaque, // render through completely opaque vegetation
boost_parallax, // final double boost_parallax) { // increase weights of scenes with high parallax relative to the reference one
max_parallax); // final double max_parallax)
// num_exaggerate
double [][] result_renders = new double [1+num_exaggerate][];
String [] result_titles = new String [result_renders.length];
result_titles[0] = "full average";
result_titles[1] = "filtered average";
result_renders[0] = terrain_average;
result_renders[1] = render;
for (int n = 2; n <= num_exaggerate; n++) {
result_titles[n]="exaggerate x "+n;
result_renders[n] = new double [full_length];
for (int i = 0; i < full_length; i++) {
result_renders[n][i] = terrain_average[i] + n * (render[i] - terrain_average[i]);
}
}
ShowDoubleFloatArrays.showArrays(
combined_offsets,
full.width,
full.height,
true,
ref_scene+"-scene_offsets",
titles_scenes);
ShowDoubleFloatArrays.showArrays(
result_renders,
full.width,
full.height,
true,
ref_scene+"-"+render_title,
result_titles);
String [] synt_titles = {"render","synthetic", "synt_terrain", "synt vegetation","masked render", "render"};
final double [][][] synt_data = new double [synt_titles.length][num_scenes][];
final double terrain_max = alpha_min;
final double vegetation_min = 0.5; // alpha_max;
String synt_name = "synthetic-terr"+terrain_max+"-veg"+vegetation_min;
synt_data[0] = terrain_rendered;
synt_data[5] = terrain_rendered;
double [][][] synt_tv= renderSynthetic(
preview_data[2][accum_indx], // final double [] alpha,
combined_offsets, // final double [][] scene_offsets, // subtract if not null
terrain_max, // final double terrain_max, // below - terrain is visible
vegetation_min, // final double vegetation_min, // above - vegetation is visible
boost_parallax, // final double boost_parallax, // increase weights of scenes with high parallax relative to the reference one
max_parallax); //final double max_parallax) {
synt_data[2] = synt_tv[0];
synt_data[3] = synt_tv[1];
// for (int nscene = 0; nscene < num_scenes; nscene++) { // use threads
// synt_data[1][nscene] = synt_tv[0][nscene].clone();
// synt_data[4][nscene] = terrain_rendered[nscene].clone();
// double [] veg_scene = synt_tv[1][nscene];
// for (int i = 0; i < veg_scene.length; i++) {
// if (!Double.isNaN(veg_scene[i])) {
// synt_data[1][nscene][i] = veg_scene[i];
// synt_data[4][nscene][i] = Double.NaN;
// }
// }
// }
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nscene = ai.getAndIncrement(); nscene < num_scenes; nscene = ai.getAndIncrement()) {
synt_data[1][nscene] = synt_tv[0][nscene].clone();
synt_data[4][nscene] = terrain_rendered[nscene].clone();
double [] veg_scene = synt_tv[1][nscene];
for (int i = 0; i < veg_scene.length; i++) {
if (!Double.isNaN(veg_scene[i])) {
synt_data[1][nscene][i] = veg_scene[i];
synt_data[4][nscene][i] = Double.NaN;
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
ShowDoubleFloatArrays.showArraysHyperstack(
synt_data, // double[][][] pixels,
full.width, // int width,
ref_scene+"-"+synt_name, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles_scenes, // String [] titles, // all slices*frames titles or just slice titles or null
synt_titles, // String [] frame_titles, // frame titles or null
true); // boolean show)
*/
return;
}
public static double [] overlapCosineWindow(
Rectangle woi,
int width){
if (width > woi.width/2) {
width = woi.width/2;
}
if (width > woi.height/2) {
width = woi.height/2;
}
double [] window = new double [woi.width*woi.height];
double [] wnd_x = new double [woi.width];
double [] wnd_y = new double [woi.height];
Arrays.fill(wnd_x, 1.0);
Arrays.fill(wnd_y, 1.0);
for (int i = 0; i < width; i++) {
double w = 0.5* (1 - Math.cos(Math.PI * (i + 0.5) / width));
wnd_x[i] = w;
wnd_x[woi.width - i - 1] = w;
wnd_y[i] = wnd_x[i];
wnd_y[woi.height - i - 1] = w;
}
int indx = 0;
for (int y = 0; y < woi.height; y++) {
for (int x = 0; x < woi.width; x++) {
window[indx++] = wnd_x[x] * wnd_y[y];
}
}
return window;
}
public static double [] crop(
double [] data,
int width,
Rectangle woi) {
int height = data.length/width;
if ((woi.x==0) && (woi.y==0) && (woi.width==width) && (woi.height==height)) {
return data.clone();
}
double [] cropped = new double [woi.width*woi.height];
Arrays.fill (cropped, Double.NaN);
for (int row = 0; row < woi.height; row ++) {
int src_row = row + woi.y;
if ((src_row >0) && (src_row < height)) {
int col0 = 0;
int col1 = woi.width;
int src_col0 = col0+woi.x;
int src_col1 = src_col0+ woi.width;
if (src_col0 < 0) {
col0 -= src_col0;
src_col0 = 0;
}
if (src_col1 > width) {
col1 -= src_col1 - width;
src_col1 = width;
}
int row_len = col1 - col0;
if (row_len > 0) {
System.arraycopy(
data,
src_row * width + src_col0,
cropped,
row*woi.width + col0,
row_len);
}
}
}
return cropped;
}
}
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