Commit baed6b68 authored by Andrey Filippov's avatar Andrey Filippov

Improving code related to the synthetic images, adding comments.

parent ada7257a
......@@ -5827,15 +5827,6 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
SYNC_COMMAND, // // SyncCommand SYNC_COMMAND,
CLT_PARAMETERS, // CLTParameters clt_parameters,
DEBUG_LEVEL); // final int debugLevel
/*
} else if (label.equals("Test LDLT Cholesky")) {
ImagePlus imp_sel = WindowManager.getCurrentImage();
if (imp_sel == null) {
IJ.showMessage("Error", "No images selected");
return;
}
CholeskyLDLTMulti.testCholesky(imp_sel); // ImagePlus imp.);
*/
} else if (label.equals("Test LLT Cholesky")) {
ImagePlus imp_sel = WindowManager.getCurrentImage();
if (imp_sel == null) {
......
......@@ -989,9 +989,11 @@ min_str_neib_fpn 0.35
public String synth_directory = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/restore_foliage/01/";
public String synth_scene = "1697877490_630338";
public String synth_model = "-preview_segments-0-0-640-512-ACCUM.tiff";
// public String synth_source = "_warps.tiff";
public String synth_segments = ".vegetation-segments"; // serialized: number of models, array of models
public String synth_render = "_synth-render.tiff";
public boolean synth_crop_real = true; // crop synthetic by real
public String synth_scene_offs = "-0-0-640-512-SCENE_OFFSETS.tiff";
public boolean synth_add_offs = true; // crop synthetic by real
// public String ter_rendered_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/1697877491_613999-terrain_vegetation_render.tiff";
......@@ -2491,9 +2493,11 @@ min_str_neib_fpn 0.35
gd.addStringField ("Synthesis directory", synth_directory, 120, "Directory with the terrain/foliage model generation files.");
gd.addStringField ("Scene name", synth_scene, 40, "Name (timestamp) of the model.");
gd.addStringField ("Model suffix", synth_model, 120, "File name suffix for the model.");
// gd.addStringField ("Source suffix", synth_source, 120, "File name suffix for the camera images, warps and scales.");
gd.addStringField ("Vegetation segments", synth_segments, 120, "File name suffix for partial terrain/vegetation segments.");
gd.addStringField ("Rendered suffix", synth_render, 120, "Result file name suffix for the rendered synthetic images.");
gd.addCheckbox ("Crop by real", synth_crop_real, "Crop synthetic by real.");
gd.addStringField ("Scene offsets", synth_scene_offs,120, "Filenam suffix with scene offsets.");
gd.addCheckbox ("Add scene offsets", synth_add_offs, "Add scene offsets (vignetting corrcetion).");
}
public void dialogAnswers(GenericJTabbedDialog gd) {
......@@ -3349,9 +3353,11 @@ min_str_neib_fpn 0.35
synth_directory = gd.getNextString(); // String
synth_scene = gd.getNextString(); // String
synth_model = gd.getNextString(); // String
// synth_source = gd.getNextString(); // String
synth_segments = gd.getNextString(); // String
synth_render = gd.getNextString(); // String
synth_crop_real = gd.getNextBoolean();// boolean
synth_scene_offs = gd.getNextString(); // String
synth_add_offs = gd.getNextBoolean();// boolean
if (this.weight_zero_neibs > 1.0) this.weight_zero_neibs = 1.0;
}
......@@ -4191,9 +4197,11 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"synth_directory", synth_directory+""); // String
properties.setProperty(prefix+"synth_scene", synth_scene+""); // String
properties.setProperty(prefix+"synth_model", synth_model+""); // String
// properties.setProperty(prefix+"synth_source", synth_source+""); // String
properties.setProperty(prefix+"synth_segments", synth_segments+""); // String
properties.setProperty(prefix+"synth_render", synth_render+""); // String
properties.setProperty(prefix+"synth_crop_real", synth_crop_real+""); // boolean
properties.setProperty(prefix+"synth_scene_offs", synth_scene_offs+""); // String
properties.setProperty(prefix+"synth_add_offs", synth_add_offs+""); // boolean
}
public void getProperties(String prefix,Properties properties){
......@@ -5048,9 +5056,11 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"synth_directory")!= null) synth_directory=(String) properties.getProperty(prefix+"synth_directory");
if (properties.getProperty(prefix+"synth_scene")!= null) synth_scene=(String) properties.getProperty(prefix+"synth_scene");
if (properties.getProperty(prefix+"synth_model")!= null) synth_model=(String) properties.getProperty(prefix+"synth_model");
// if (properties.getProperty(prefix+"synth_source")!= null) synth_source=(String) properties.getProperty(prefix+"synth_source");
if (properties.getProperty(prefix+"synth_segments")!= null) synth_segments=(String) properties.getProperty(prefix+"synth_segments");
if (properties.getProperty(prefix+"synth_render")!= null) synth_render=(String) properties.getProperty(prefix+"synth_render");
if (properties.getProperty(prefix+"synth_crop_real")!= null) synth_crop_real=Boolean.parseBoolean(properties.getProperty(prefix+"synth_crop_real"));
if (properties.getProperty(prefix+"synth_scene_offs")!= null) synth_scene_offs=(String) properties.getProperty(prefix+"synth_scene_offs");
if (properties.getProperty(prefix+"synth_add_offs")!= null) synth_add_offs=Boolean.parseBoolean(properties.getProperty(prefix+"synth_add_offs"));
}
@Override
......@@ -5861,9 +5871,11 @@ min_str_neib_fpn 0.35
imp.synth_directory = this.synth_directory;
imp.synth_scene = this.synth_scene;
imp.synth_model = this.synth_model;
// imp.synth_source = this.synth_source;
imp.synth_segments = this.synth_segments;
imp.synth_render = this.synth_render;
imp.synth_crop_real = this.synth_crop_real;
imp.synth_scene_offs = this.synth_scene_offs;
imp.synth_add_offs = this.synth_add_offs;
return imp;
}
public static long getLongColor(Color color) {
......
......@@ -369,436 +369,7 @@ public class QuadCLTCPU {
* @param full_path null or full path to parent directory
* @return center_CLT instance or null
*/
@Deprecated
public static QuadCLT restoreCenterClt_old(
CLTParameters clt_parameters,
QuadCLT ref_clt,
String full_path // if non-null, use it instead of ref_clt
) {
QuadCLT center_parent = null;
double [][] parent_dsi = null;
if (full_path != null) {
if (full_path.endsWith(Prefs.getFileSeparator())) {
full_path = full_path.substring(0, full_path.length()-1);
}
int ver_sep = full_path.lastIndexOf(Prefs.getFileSeparator());
// String ver_str = full_path.substring(ver_sep+1);
int name_sep = full_path.lastIndexOf(Prefs.getFileSeparator(),ver_sep-1);
String parent_name = full_path.substring(name_sep+1,ver_sep);
// ref_dir_path = full_path; // .substring(0,name_sep+1)+
File cdir_parent = new File(full_path);
if (!cdir_parent.exists() || !cdir_parent.isDirectory()) {
System.out.println("restoreCenterClt(): directory does not exist: "+full_path);
return null;
}
center_parent = new QuadCLT(ref_clt, parent_name);
center_parent.setImagePath(cdir_parent.getPath());
center_parent.setCenterParent();
int [] wh_parent = new int[2];
float [][] fclt_w_parent;
fclt_w_parent= center_parent.readFloatArrayFromModelDirectory(
CENTER_CLT_SUFFIX, // String suffix,
0, // int num_slices, // (0 - all)
wh_parent); // int [] wh)
if (fclt_w_parent == null) {
System.out.println("restoreCenterClt(): No parent FCLT data in "+center_parent.getImagePath());
return null;
}
if (fclt_w_parent.length != 1) {
System.out.println("restoreCenterClt(): expected a single-slice data, got "+fclt_w_parent.length+" slices.");
return null;
}
int fclt_tile_length = center_parent.getCltTileLength();
float [] center_clt_weights = new float [fclt_w_parent[0].length/(fclt_tile_length + 1)];
float [] center_clt = new float [fclt_w_parent[0].length/(fclt_tile_length + 1) * fclt_tile_length];
System.arraycopy(fclt_w_parent[0], 0, center_clt, 0, center_clt.length);
System.arraycopy(fclt_w_parent[0], center_clt.length, center_clt_weights, 0, center_clt_weights.length);
center_parent.setCenterClt(
center_clt, // float [] clt,
center_clt_weights); // int clt_width);
parent_dsi = center_parent.restoreComboDSI(true);
if (parent_dsi == null) {
System.out.println("restoreCenterClt(): No parent DSI data in "+center_parent.getImagePath());
return null;
}
}
String center_name = QuadCLT.getCenterDirName(ref_clt.getImageName());
String ref_dir_path = ref_clt.readX3dDirectory(center_name); // gets /home/elphel/lwir16-proc/eagle_mountain/configs!
File cdir = new File(ref_dir_path);
QuadCLT center_CLT = null;
// Try to read this (created/tuned) center_CLT
try_read_center: {
if (ref_dir_path == null) {
System.out.println("restoreCenterClt(): directory does not exist: "+ref_dir_path);
break try_read_center;
}
if (!cdir.exists() || !cdir.isDirectory()) {
System.out.println("restoreCenterClt(): directory does not exist or is not a directory: "+ref_dir_path);
break try_read_center;
}
center_CLT = new QuadCLT(ref_clt, center_name);
center_CLT.setImagePath(cdir.getPath());
int [] wh = new int[2];
float [][] fclt_w;
fclt_w= center_CLT.readFloatArrayFromModelDirectory(
CENTER_CLT_SUFFIX, // String suffix,
0, // int num_slices, // (0 - all)
wh); // int [] wh)
if (fclt_w == null) {
System.out.println("restoreCenterClt(): No FCLT data for the center_CLT in "+center_CLT.getImagePath());
center_CLT = null; // will create a new one if parent exists
break try_read_center;
}
if (fclt_w.length != 1) {
System.out.println("restoreCenterClt(): expected a single-slice data, got "+fclt_w.length+" slices.");
break try_read_center;
}
int fclt_tile_length = center_CLT.getCltTileLength();
float [] center_clt_weights = new float [fclt_w[0].length/(fclt_tile_length + 1)];
float [] center_clt = new float [fclt_w[0].length/(fclt_tile_length + 1) * fclt_tile_length];
System.arraycopy(fclt_w[0], 0, center_clt, 0, center_clt.length);
System.arraycopy(fclt_w[0], center_clt.length, center_clt_weights, 0, center_clt_weights.length);
center_CLT.setCenterClt(
center_clt, // float [] clt,
center_clt_weights); // int clt_width);
if (center_CLT.restoreComboDSI(true) == null) {
System.out.println("restoreCenterClt(): No DSI data in "+center_CLT.getImagePath());
center_CLT = null; // will create a new one if parent exists
break try_read_center;
}
}
if ((center_parent == null) && (center_CLT == null)) {
System.out.println("restoreCenterClt(): no parent CLT and no saved CLT, exiting with null");
return null;
}
if (center_CLT == null) {
// create new center_CLT with data from the parent_CLT
center_CLT = new QuadCLT(ref_clt, center_name);
center_CLT.setImagePath(cdir.getPath());
cdir.mkdirs();
float [] center_weights = center_parent.getCenterCltWeights().clone();
Arrays.fill(center_weights, 0.0f); // 1.0f); // make non-zeros, will be overwritten later
center_CLT.setCenterClt(
center_parent.getCenterClt(), // float [] clt,
center_weights); // null); // null weights
center_CLT.setDSIFromCombo(parent_dsi); // set center DSI from parent
String rslt_suffix = "-INTER-INTRA";
if (!clt_parameters.correlate_lma){
System.out.println("createCenterClt() BUG??? clt_parameters.correlate_lma="+clt_parameters.correlate_lma);
clt_parameters.correlate_lma = true;
}
rslt_suffix += (clt_parameters.correlate_lma?"-LMA":"-NOLMA");
center_CLT.saveDoubleArrayInModelDirectory( // error
rslt_suffix, // String suffix,
OpticalFlow.COMBO_DSN_TITLES, // combo_dsn_titles_full, // null, // String [] labels, // or null
parent_dsi, // double [][] data,
center_CLT.getTilesX(), // int width,
center_CLT.getTilesY()); // int height)
center_CLT.saveCenterClt();
/*
double [][] dsi = center_parent.getDSI().clone();
for (int i = 0; i < dsi.length; i++) { // deep clone
if (dsi[i] != null) {
dsi[i] = dsi[i].clone();
}
}
center_CLT.setDSI(dsi);
*/
}
center_CLT.setCenterParent(center_parent);
return center_CLT;
}
@Deprecated
public static QuadCLT restoreCenterClt_old2(
CLTParameters clt_parameters,
QuadCLT ref_clt , // latest
String full_path, // if non-null, use it instead of ref_clt
int debugLevel) {
double tolerance = clt_parameters.imp.cuas_clt_threshold;
double decay = clt_parameters.imp.cuas_decay_average;
if (full_path.endsWith(Prefs.getFileSeparator())) {
full_path = full_path.substring(0, full_path.length()-1);
}
// QuadCLT center_parent = null;
double [][] parent_dsi = null;
int tilesX = ref_clt.getTilesX();
int num_colors = ref_clt.getNumColors();
double dts = ref_clt.getTimeStamp();
CuasData parentCuasData = null;
CuasData cuasData = null;
if (full_path != null) {
parentCuasData = CuasData.getCuasData(
full_path, // String full_path, // ends with /vxx
num_colors, // int num_colors, // only used if restored from tiff, ignored for .cuas
tilesX, // int width, // only used if restored from tiff, ignored for .cuas
dts, // double dts, // time stamp as double, only used if restored from tiff, ignored for .cuas
debugLevel); // int debugLevel)
if (parentCuasData == null) {
System.out.println("restoreCenterClt(): parentCuasData returned null for "+full_path);
return null;
}
// old code to restore combo_dsi
int ver_sep = full_path.lastIndexOf(Prefs.getFileSeparator());
int name_sep = full_path.lastIndexOf(Prefs.getFileSeparator(),ver_sep-1);
String parent_name = full_path.substring(name_sep+1,ver_sep);
File cdir_parent = new File(full_path);
if (!cdir_parent.exists() || !cdir_parent.isDirectory()) {
System.out.println("restoreCenterClt(): directory does not exist: "+full_path);
return null;
}
String dsi_path = full_path+Prefs.getFileSeparator()+parent_name+DSI_SUFFIXES[INDEX_INTER_LMA]+".tiff";
double [][] combo_dsi = new double [OpticalFlow.COMBO_DSN_TITLES.length][];
int num_slices = restoreDSI( // new method 06/03/2025, switched argument order
combo_dsi, // double [][] dsi,
dsi_path, // String file_path,
true); // boolean silent)
if (num_slices <= 0) {
System.out.println("restoreCenterClt(): No parent DSI data in "+dsi_path);
return null;
}
}
String center_name = QuadCLT.getCenterDirName(ref_clt.getImageName());
String center_dir_path = ref_clt.readX3dDirectory(center_name); // gets /home/elphel/lwir16-proc/eagle_mountain/configs!
File cdir = new File(center_dir_path);
QuadCLT center_CLT = null;
// Try to read this (created/tuned) center_CLT
try_read_center: {
if (center_dir_path == null) {
System.out.println("restoreCenterClt(): directory does not exist: "+center_dir_path);
break try_read_center;
}
if (!cdir.exists() || !cdir.isDirectory()) {
System.out.println("restoreCenterClt(): directory does not exist or is not a directory: "+center_dir_path);
break try_read_center;
}
cuasData = CuasData.getCuasData(
center_dir_path, // String full_path, // ends with /vxx
num_colors, // int num_colors, // only used if restored from tiff, ignored for .cuas
tilesX, // int width, // only used if restored from tiff, ignored for .cuas
dts, // double dts, // time stamp as double, only used if restored from tiff, ignored for .cuas
debugLevel); // int debugLevel)
if (cuasData == null) {
System.out.println("restoreCenterClt(): parentCuasData returned null for "+center_dir_path);
return null;
}
center_CLT = new QuadCLT(ref_clt, center_name);
center_CLT.setImagePath(cdir.getPath());
// set center data
if (center_CLT.restoreComboDSI(true) == null) {
System.out.println("restoreCenterClt(): No DSI data in "+center_CLT.getImagePath());
center_CLT = null; // will create a new one if parent exists
break try_read_center;
}
dts = ref_clt.getTimeStamp();
if (center_CLT.restoreComboDSI(true) == null) {
System.out.println("restoreCenterClt(): No DSI data in "+center_CLT.getImagePath());
center_CLT = null; // will create a new one if parent exists
break try_read_center;
}
}
if (center_CLT == null) {
cuasData = parentCuasData; // use parent's
// create new center_CLT with data from the parent_CLT
center_CLT = new QuadCLT(ref_clt, center_name);
center_CLT.setImagePath(cdir.getPath());
cdir.mkdirs();
center_CLT.setDSIFromCombo(parent_dsi); // set center DSI from parent
String rslt_suffix = "-INTER-INTRA";
if (!clt_parameters.correlate_lma){
System.out.println("createCenterClt() BUG??? clt_parameters.correlate_lma="+clt_parameters.correlate_lma);
clt_parameters.correlate_lma = true;
}
rslt_suffix += (clt_parameters.correlate_lma?"-LMA":"-NOLMA");
center_CLT.saveDoubleArrayInModelDirectory( // error
rslt_suffix, // String suffix,
OpticalFlow.COMBO_DSN_TITLES, // combo_dsn_titles_full, // null, // String [] labels, // or null
parent_dsi, // double [][] data,
center_CLT.getTilesX(), // int width,
center_CLT.getTilesY()); // int height)
}
float [] fclt = cuasData.collapse( // itself or parent
tolerance, // final double tolerance, // NaN works as infinity
decay, // final double decay,
dts)[0]; // final double ts_now)
center_CLT.setCenterClt(fclt); // float [] clt)
String center_cuas_path = center_CLT.getImagePath()+Prefs.getFileSeparator() + center_CLT.getImageName()+CuasData.getCuasSuffix();
if (full_path != null) {
center_CLT.setCenterParentDir(full_path);
}
try {
cuasData.writeCuasData (center_cuas_path);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return center_CLT;
}
/**
* Read (try to read) this first, maybe parent is not needed (yet)
* @param clt_parameters
* @param ref_clt
* @param full_path
* @param single_first true: read single first, cumulative second, false - read cumulative first
* @param debugLevel
* @return
*/
public static QuadCLT restoreCenterClt_old3(
CLTParameters clt_parameters,
QuadCLT ref_clt , // latest
String full_path, // if non-null, use it instead of ref_clt
boolean single_first, // true: read single first, cumulative second
int debugLevel) {
// 1) read single from model directory (only .cuas) if single_first only model dir?
// 2) read cumulative from specified dir. If does not exist - try single from specified dir. If does not exist read old format. Read DSI from specified dir
// If both local and parent exist - combine
// If rad old-style from parent - save it there as cumulative
//What about DSI?
double tolerance = clt_parameters.imp.cuas_clt_threshold;
double decay = clt_parameters.imp.cuas_decay_average;
if (full_path.endsWith(Prefs.getFileSeparator())) {
full_path = full_path.substring(0, full_path.length()-1);
}
// QuadCLT center_parent = null;
double [][] parent_dsi = null;
int tilesX = ref_clt.getTilesX();
int num_colors = ref_clt.getNumColors();
double dts = ref_clt.getTimeStamp();
// CuasData parentCuasData = null;
CuasData cuasData = null;
String center_name = QuadCLT.getCenterDirName(ref_clt.getImageName());
// allow creation, otherwise returns config
/// String center_dir_path = ref_clt.readX3dDirectory(center_name); // gets /home/elphel/lwir16-proc/eagle_mountain/configs!
String center_dir_path = ref_clt.setX3dDirectory(center_name); // gets /home/elphel/lwir16-proc/eagle_mountain/configs!
File cdir = new File(center_dir_path);
QuadCLT center_CLT = null;
// Try to read this (created/tuned) center_CLT
try_read_center: {
if (center_dir_path == null) {
System.out.println("restoreCenterClt(): directory does not exist: "+center_dir_path);
break try_read_center;
}
if (!cdir.exists() || !cdir.isDirectory()) {
System.out.println("restoreCenterClt(): directory does not exist or is not a directory: "+center_dir_path);
break try_read_center;
}
cuasData = CuasData.getCuasData(
center_dir_path, // String full_path, // ends with /vxx
num_colors, // int num_colors, // only used if restored from tiff, ignored for .cuas
tilesX, // int width, // only used if restored from tiff, ignored for .cuas
dts, // double dts, // time stamp as double, only used if restored from tiff, ignored for .cuas
debugLevel); // int debugLevel)
if (cuasData == null) {
System.out.println("restoreCenterClt(): CuasData returned null for "+center_dir_path);
break try_read_center;
}
center_CLT = new QuadCLT(ref_clt, center_name);
center_CLT.setImagePath(cdir.getPath());
// set center data
if (center_CLT.restoreComboDSI(true) == null) {
System.out.println("restoreCenterClt(): No DSI data in "+center_CLT.getImagePath());
center_CLT = null; // will create a new one if parent exists
break try_read_center;
}
dts = center_CLT.getTimeStamp();
}
if (center_CLT == null) {
if (full_path == null) {
System.out.println("restoreCenterClt(): parentCuasData is not provided, bailing out.");
return null;
}
cuasData = CuasData.getCuasData( // parent
full_path, // String full_path, // ends with /vxx
num_colors, // int num_colors, // only used if restored from tiff, ignored for .cuas
tilesX, // int width, // only used if restored from tiff, ignored for .cuas
dts, // double dts, // time stamp as double, only used if restored from tiff, ignored for .cuas
debugLevel); // int debugLevel)
if (cuasData == null) {
System.out.println("restoreCenterClt(): parentCuasData returned null for "+full_path);
return null;
}
// old code to restore combo_dsi
int ver_sep = full_path.lastIndexOf(Prefs.getFileSeparator());
int name_sep = full_path.lastIndexOf(Prefs.getFileSeparator(),ver_sep-1);
String parent_name = full_path.substring(name_sep+1,ver_sep);
File cdir_parent = new File(full_path);
if (!cdir_parent.exists() || !cdir_parent.isDirectory()) {
System.out.println("restoreCenterClt(): directory does not exist: "+full_path);
return null;
}
String dsi_path = full_path+Prefs.getFileSeparator()+parent_name+DSI_SUFFIXES[INDEX_INTER_LMA]+".tiff";
parent_dsi = new double [OpticalFlow.COMBO_DSN_TITLES.length][];
int num_slices = restoreDSI( // new method 06/03/2025, switched argument order
parent_dsi, // double [][] dsi,
dsi_path, // String file_path,
true); // boolean silent)
if (num_slices <= 0) {
System.out.println("restoreCenterClt(): No parent DSI data in "+dsi_path);
return null;
}
// Create new center_CLT
center_CLT = new QuadCLT(ref_clt, center_name);
center_CLT.setImagePath(cdir.getPath()); // *********************
cdir.mkdirs();
center_CLT.setDSIFromCombo(parent_dsi); // set center DSI from parent
String rslt_suffix = "-INTER-INTRA";
if (!clt_parameters.correlate_lma){
System.out.println("createCenterClt() BUG??? clt_parameters.correlate_lma="+clt_parameters.correlate_lma);
clt_parameters.correlate_lma = true;
}
rslt_suffix += (clt_parameters.correlate_lma?"-LMA":"-NOLMA");
center_CLT.saveDoubleArrayInModelDirectory( // error
rslt_suffix, // String suffix,
OpticalFlow.COMBO_DSN_TITLES, // combo_dsn_titles_full, // null, // String [] labels, // or null
parent_dsi, // double [][] data,
center_CLT.getTilesX(), // int width,
center_CLT.getTilesY()); // int height)
center_CLT.setDSIFromCombo(parent_dsi);
}
float [] fclt = cuasData.collapse( // itself or parent
tolerance, // final double tolerance, // NaN works as infinity
decay, // final double decay,
dts)[0]; // final double ts_now)
center_CLT.setCenterClt(fclt); // float [] clt)
String center_cuas_path = center_CLT.getImagePath()+Prefs.getFileSeparator() + center_CLT.getImageName()+CuasData.getCuasSuffix();
try {
cuasData.writeCuasData (center_cuas_path);
if (debugLevel >-3) {
System.out.println("restoreCenterClt(): saved CuasData to "+center_cuas_path+" .");
}
} catch (IOException e) {
System.out.println("restoreCenterClt(): FAILED to save CuasData to "+center_cuas_path+" .");
// TODO Auto-generated catch block
e.printStackTrace();
}
if (full_path != null) {
center_CLT.setCenterParentDir(full_path); // is not in cuasData, only in center_CLT instance
}
return center_CLT;
}
/**
......
......@@ -6456,8 +6456,15 @@ public class VegetationLMA {
for (int t = 0; t < SAVE_TYPES.length; t++) {
int n = SAVE_TYPES[t];
if (n ==TVAO_SCENE_OFFSET) {
tvao_data[n] = new double [num_scenes];
if ( data[t] != null) {
System.arraycopy(data[t], 0, tvao_data[n],0, num_scenes);
}
} else {
tvao_data[n] = data[t];
}
}
for (int n = 0; n < tvao_data.length; n++) {
if (tvao_data[n] == null) {
tvao_data[n] = new double [width*height];
......@@ -6735,7 +6742,7 @@ public class VegetationLMA {
terrain_offset, // terrain_offset,
tvao[TVAO_SCENE_OFFSET], // double [] scene_offsets,
// terrain, vegetation, alpha, elevation, terrain_elevation
new double [][] {tvao[0],tvao[1],tvao[2],tvao[3],tvao[5]}, // double [][] tva) {} {}
new double [][] {tvao[0],tvao[1],tvao[2],tvao[3],tvao[5]}, // double [][] tva) {} {} // skipping common terrain elevation
confidence, // double [] confidence
has_vegetation); //boolean [] overlaid)
if (debugLevel>-2) {
......
......@@ -2,6 +2,7 @@ package com.elphel.imagej.vegetation;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
......@@ -2068,7 +2069,46 @@ public class VegetationModel {
if (run_combine) {
VegetationSegment [] segments = vegetationLMA.readAllSegments(
String synth_directory = clt_parameters.imp.synth_directory; // "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/restore_foliage/01/";
if (!synth_directory.endsWith(Prefs.getFileSeparator())) {
synth_directory+=Prefs.getFileSeparator();
}
String synth_segments = clt_parameters.imp.synth_segments; // ".vegetation-segments"; // serialized: number of models, array of models
String synth_scene = clt_parameters.imp.synth_scene;
String segments_path = synth_directory + synth_scene + synth_segments;
// try to read segments from the serialized file (to force recalculation - just remove it)
VegetationSegment [] segments = null;
try {
segments = VegetationSegment.readVegetationSegments (
segments_path);
System.out.println("processVegetationLMA(): read serialized segment data from "+(segments.length)+" segments to "+segments_path);
System.out.println("To rebuild the segments - just remove "+segments_path+" and re-run the program");
} catch (ClassNotFoundException | IOException e1) {
System.out.println("processVegetationLMA(): failed to read segments data from "+segments_path+", will rebuild it.");
} // String path)
//fixing wrong scene_offsets
boolean fixed_scene_offsets= false;
int num_scenes = getSceneNames().length;
for (VegetationSegment segment:segments) {
if (segment.scene_offsets.length > num_scenes) {
double [] s_o = new double [num_scenes];
System.arraycopy(segment.scene_offsets, 0, s_o, 0, num_scenes);
segment.scene_offsets = s_o;
fixed_scene_offsets = true;
}
}
if (fixed_scene_offsets) {
try {
VegetationSegment.writeVegetationSegments(
segments_path, // String path,
segments);
System.out.println("processVegetationLMA(): Saved fixed scene_offsets serialized data for "+(segments.length)+" segments to "+segments_path);
} catch (IOException e) {
System.out.println("processVegetationLMA(): failed to save fixed scene_offsets segments data to "+segments_path);
} // VegetationSegment [] segments) throws IOException {
}
if (segments == null) {
segments = vegetationLMA.readAllSegments(
segments_dir, // String dir_path)
segments_suffix, // String suffix);
transparency_opaque, // double transparency_opaque,
......@@ -2081,11 +2121,25 @@ public class VegetationModel {
debug_path, // String debug_path,
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.");
// String segments_path = model_directory+reference_scene+"-foliage_model.foliage-model";
try {
VegetationSegment.writeVegetationSegments(
segments_path, // String path,
segments);
System.out.println("processVegetationLMA(): Saved serialized data for "+(segments.length)+" segments to "+segments_path);
} catch (IOException e) {
System.out.println("processVegetationLMA(): failed to save segments data to "+segments_path);
} // VegetationSegment [] segments) throws IOException {
}
if (keep_partial) { // may require too much memory
VegetationSegment.combineSegments(
vegetationLMA, // VegetationLMA vegetationLMA,
segments,
crop_combo, // boolean crop_combo,
keep_partial, // boolean keep_partial,
true, // boolean keep_partial,
border_width, // int width);
um_sigma, // final double um_sigma,
um_weight, //final double um_weight,
......@@ -2097,6 +2151,35 @@ public class VegetationModel {
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
} else {
VegetationSegment.combineSegments(
vegetationLMA, // VegetationLMA vegetationLMA,
segments,
crop_combo, // boolean crop_combo,
// keep_partial, // boolean keep_partial,
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
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
}
ImagePlus imp_scene_offsets = VegetationSegment.combineSegmentsSceneOffsets(
vegetationLMA, // VegetationLMA vegetationLMA,
segments, // VegetationSegment [] segments,
crop_combo, // boolean crop_combo,
border_width, // int width);
num_scenes); // final int num_scenes
if (imp_scene_offsets != null) {
imp_scene_offsets.show();
}
return;
}
Rectangle woi = woi_last_done;
......
package com.elphel.imagej.vegetation;
import java.awt.Rectangle;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
......@@ -12,7 +19,8 @@ import com.elphel.imagej.tileprocessor.QuadCLT;
import ij.ImagePlus;
import ij.gui.GenericDialog;
public class VegetationSegment {
public class VegetationSegment implements Serializable {
private static final long serialVersionUID = 1L;
public Rectangle woi_max;
public Rectangle woi;
public double [] scene_offsets;
......@@ -21,6 +29,8 @@ public class VegetationSegment {
public double [] confidence; // woi
public boolean [] overlaid;
public String path;
public VegetationSegment(
String path,
Rectangle woi_max,
......@@ -41,6 +51,7 @@ public class VegetationSegment {
correctTerrainOffset();
}
public void correctTerrainOffset() {
if (!Double.isNaN(terrain_offset) && (overlaid != null)) {
int woi_length = woi.width * woi.height;
......@@ -55,6 +66,19 @@ public class VegetationSegment {
}
}
public double [] getSceneOffsets() {
return scene_offsets;
}
public Rectangle getWoi() {
return woi;
}
public Rectangle getWoiMax() {
return woi_max;
}
public static Rectangle getBounds( // [0] - woi, [1] - woi_weg
VegetationSegment [] segments,
boolean use_veg) {
......@@ -69,7 +93,8 @@ public class VegetationSegment {
}
return bounds;
}
public static void combineSegments(
public static void combineSegments( // KeepPartial
VegetationLMA vegetationLMA,
VegetationSegment [] segments,
boolean crop_combo,
......@@ -97,7 +122,7 @@ public class VegetationSegment {
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","terrain_elevation","confidence"};
String [] top_titles = {"terrain","vegetation","alpha","elevation","terrain_elevation","confidence","terrain_offset"};
double [][][] preview_data = new double [top_titles.length][accum_indx+1][out_length]; // Java heap space
String [] titles = new String[accum_indx+1];
for (int ns = 0; ns < segments.length; ns++) {
......@@ -108,6 +133,7 @@ public class VegetationSegment {
int woi_veg_length = woi_veg.width * woi_veg.height;
double [][] woi_tva = segments[ns].tva;
double [] confidence = segments[ns].confidence;
double terrain_offset = segments[ns].terrain_offset;
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) {
......@@ -150,6 +176,14 @@ public class VegetationSegment {
preview_data[t][ns][indx] = confidence[windx];
}
break;
case 6: // terrain_offset
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] = terrain_offset;
}
break;
}
}
}
......@@ -249,12 +283,282 @@ public class VegetationSegment {
true,
res_title,
result_titles);
return;
}
public static void combineSegments(
VegetationLMA vegetationLMA,
VegetationSegment [] segments,
boolean crop_combo,
// boolean keep_partial,
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","terrain_elevation","confidence","terrain_offset"};
// double [][][] preview_data = new double [top_titles.length][accum_indx+1][out_length]; // Java heap space
String [] titles = new String[accum_indx+1];
double [][] sum_w = new double [top_titles.length][out_length];
double [][] sum_wd = new double [top_titles.length][out_length];
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_max;
titles[ns] = woi.toString();
int woi_length = woi.width * woi.height;
// creating larger window, still use only the woi for overlapping, discard outside
int woi_veg_length = woi_veg.width * woi_veg.height;
double [] wnd = overlapCosineWindow (woi, width);
double [] wnd_veg = new double [woi_veg_length];
for (int windx = 0; windx < woi_length; windx++) {
int wx = windx % woi.width;
int wy = windx / woi.width;
int wvx = wx + woi.x - woi_veg.x;
int wvy = wy + woi.y - woi_veg.y;
wnd_veg[wvx + wvy * woi_veg.width] = wnd[windx];
}
double [][] woi_tva = segments[ns].tva;
double [] confidence = segments[ns].confidence;
double terrain_offset = segments[ns].terrain_offset;
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]; // java.lang.ArrayIndexOutOfBoundsException: Index -43 out of bounds for length 550
double d = woi_tva[t][wsrc];
if (!Double.isNaN(d)) {
double w = wnd[windx];
sum_w [t][indx] += w;
sum_wd[t][indx] += w * d ;
}
}
break;
case 1: // vegetation
case 2: // alpha
case 3: // elevation
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];
double d = woi_tva[t][windx];
if (!Double.isNaN(d)) {
double w = wnd_veg[windx]; // Index 400 out of bounds for length 400
sum_w [t][indx] += w;
sum_wd[t][indx] += w * d ;
}
}
break;
case 4: // terrain elevation
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]; // skipping terrain elevation average
double d = woi_tva[t][windx];
if (!Double.isNaN(d)) {
double w = wnd_veg[windx];
sum_w [t][indx] += w;
sum_wd[t][indx] += w * d ;
}
}
break;
case 5: // 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];
double d = confidence[windx];
if (!Double.isNaN(d)) {
double w = wnd[windx];
sum_w [t][indx] += w;
sum_wd[t][indx] += w * d ;
}
}
break;
case 6: // terrain_offset
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] = terrain_offset;
double d = terrain_offset;
if (!Double.isNaN(d)) {
double w = wnd[windx];
sum_w [t][indx] += w;
sum_wd[t][indx] += w * d ;
}
}
break;
}
}
}
for (int t = 0; t < sum_wd.length; t++) {
for (int i = 0; i < out_length; i++) {
if (sum_w[t][i] == 0) {
sum_wd[t][i] = Double.NaN;
} else {
sum_wd[t][i] /= sum_w[t][i];
}
}
}
VegetationModel vegetationModel = vegetationLMA.getModel();
String ref_scene = vegetationModel.reference_scene;
String pre_title = ref_scene+"-preview_segments-"+out_woi.x+"-"+out_woi.y+"-"+out_woi.width+"-"+out_woi.height;
ShowDoubleFloatArrays.showArrays(
sum_wd,
out_woi.width,
out_woi.height,
true,
pre_title+"-ACCUM",
top_titles);
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, sum_wd[0]};
boolean normalize = true;
int norm_index = 1;
if (normalize) {
result_img = normalize (
result_img, // final double [][] data,
norm_index); // final int norm_index){
}
String res_title = ref_scene+"-result_terrain-"+out_woi.x+"-"+out_woi.y+"-"+out_woi.width+"-"+out_woi.height;
if (normalize) {
res_title+= "-normalized"+norm_index;
}
ShowDoubleFloatArrays.showArrays(
result_img,
out_woi.width,
out_woi.height,
true,
res_title,
result_titles);
return;
}
public static ImagePlus combineSegmentsSceneOffsets(
VegetationLMA vegetationLMA,
VegetationSegment [] segments,
boolean crop_combo,
final int width,
final int num_scenes
) { // 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);
int out_length = out_woi.width*out_woi.height;
double [][] sum_scene_w = new double [num_scenes][out_length];
double [][] sum_scene_wd = new double [num_scenes][out_length];
for (int ns = 0; ns < segments.length; ns++) {
Rectangle woi = segments[ns].woi; // for confidence and limits for terrain
int woi_length = woi.width * woi.height;
// creating larger window, still use only the woi for overlapping, discard outside
double [] wnd = overlapCosineWindow (woi, width);
double [] scene_offsets = segments[ns].scene_offsets;
int min_scenes = Math.min(num_scenes, scene_offsets.length);
for (int windx = 0; windx < woi_length; windx++) {
int wx = windx % woi.width;
int wy = windx / woi.width;
int x = wx + woi.x - out_woi.x;
int y = wy + woi.y - out_woi.y;
int indx = x + y * out_woi.width;
for (int nscene = 0; nscene < min_scenes; nscene++) {
double d = scene_offsets[nscene];
if (!Double.isNaN(d)) {
double w = wnd[windx];
sum_scene_w [nscene][indx] += w;
sum_scene_wd[nscene][indx] += w * d ;
}
}
}
}
for (int nscene = 0; nscene < num_scenes; nscene++) {
for (int i = 0; i < sum_scene_w[nscene].length; i++) {
if (sum_scene_w [nscene][i] == 0) {
sum_scene_wd [nscene][i] = Double.NaN;
} else {
sum_scene_wd [nscene][i] /= sum_scene_w [nscene][i];
}
}
}
VegetationModel vegetationModel = vegetationLMA.getModel();
String [] scene_names= vegetationLMA.getModel().getSceneNames();
String ref_scene = vegetationModel.reference_scene;
String pre_title = ref_scene+"-"+out_woi.x+"-"+out_woi.y+"-"+out_woi.width+"-"+out_woi.height;
ImagePlus imp = ShowDoubleFloatArrays.makeArrays(
sum_scene_wd,
out_woi.width,
out_woi.height,
pre_title+"-SCENE_OFFSETS", // +"-objects_"+scene_num,
scene_names); // test_titles,
return imp;
}
public static double [] overlapCosineWindow(
Rectangle woi,
int width){
......@@ -449,4 +753,40 @@ public class VegetationSegment {
return data;
}
@SuppressWarnings("static-method")
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
}
@SuppressWarnings("static-method")
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
}
public static void writeVegetationSegments(
String path,
VegetationSegment [] segments) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream(path);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(segments.length); // current_version);
for (VegetationSegment segment:segments) {
objectOutputStream.writeObject(segment);
}
objectOutputStream.flush();
objectOutputStream.close();
}
public static VegetationSegment [] readVegetationSegments (
String path) throws IOException, ClassNotFoundException {
FileInputStream fileInputStream = new FileInputStream(path);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
int num_segments = (int) objectInputStream.readObject(); // reads OrthoMapsCollection
VegetationSegment [] segments = new VegetationSegment [num_segments];
for (int i = 0; i < num_segments; i++) {
segments[i] = (VegetationSegment) objectInputStream.readObject();
}
objectInputStream.close();
return segments;
}
}
......@@ -22,9 +22,9 @@ public class VegetationSynthesis {
// elevation-dependent parameters, calculated once if elevations are not adjusted or each time if they are
private double [] elev_radius; // for the future - make variable-size influence of the vegetation to mitigate far influenced pixels
private double elev_radius_extra = 1.2; // scale both radii when setupElevationLMA(), setupTerrainElevationLMA(), and setupTerrainElevationPixLMA()
private int [][][] elev_woi4; // [scene][woi_veg][~4] indices (in woi) of 4 (or more/less) neighbors of projections (negatives)
private double [][][] elev_weights4; // [scene][woi_veg][~4] weights of influence for 4 neighbors
private double [][] elev_sum_weights; // [scene][woi] sum weights from up to 4 elevation pixels (even more with overlap)
private int [][][] elev_woi4; // [scene][pixel][~4] indices (in woi) of 4 (or more/less) neighbors of projections (negatives)
private double [][][] elev_weights4; // [scene][pixel][~4] weights of influence for 4 neighbors
private double [][] elev_sum_weights; // [scene][pixel] sum weights from up to 4 elevation pixels (even more with overlap)
private final int num_scenes;
private final int num_pixels;
private boolean [] valid_scenes;
......@@ -44,17 +44,26 @@ public class VegetationSynthesis {
String synth_directory = clt_parameters.imp.synth_directory; // "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/restore_foliage/01/";
String synth_scene = clt_parameters.imp.synth_scene; // "1697877490_630338";
String synth_model = clt_parameters.imp.synth_model; // "-preview_segments-0-0-640-512-ACCUM.tiff";
String synth_render_suffix = clt_parameters.imp.synth_render; // "_synth-render.tiff";
String synth_segments = clt_parameters.imp.synth_segments; // ".vegetation-segments"; // serialized: number of models, array of models
String synth_render_suffix =clt_parameters.imp.synth_render; // "_synth-render.tiff";
boolean synth_crop_real = clt_parameters.imp.synth_crop_real;
String synth_scene_offs = clt_parameters.imp.synth_scene_offs; // "-0-0-640-512-SCENE_OFFSETS.tiff";
boolean synth_add_offs = clt_parameters.imp.synth_add_offs; //
boolean update = false;
GenericJTabbedDialog gd = new GenericJTabbedDialog("Set synthesis parameters",900,300);
GenericJTabbedDialog gd = new GenericJTabbedDialog("Set synthesis parameters",900,375);
gd.addStringField ("3D Model directory", model_directory, 120, "Directory with 3D model to extract X,Y scales and captured images.");
gd.addStringField ("3D Model state file", model_state_file, 120,"3D model state file with images, elevation and scales as absolute values and directions.");
gd.addStringField ("Synthesis directory", synth_directory, 120, "Directory with the terrain/foliage model generation files.");
gd.addStringField ("Scene name", synth_scene, 40, "Name (timestamp) of the model.");
gd.addStringField ("Model suffix", synth_model, 120, "File name suffix for the model.");
gd.addStringField ("Vegetation segments", synth_segments, 120, "File name suffix for partial terrain/vegetation segments.");
gd.addStringField ("Rendered suffix", synth_render_suffix, 120, "Result file name suffix for the rendered synthetic images.");
gd.addCheckbox ("Crop by real", synth_crop_real, "Crop synthetic by real.");
gd.addStringField ("Scene offsets", synth_scene_offs,120, "Filenam suffix with scene offsets.");
gd.addCheckbox ("Add scene offsets", synth_add_offs, "Add scene offsets (vignetting corrcetion).");
gd.addCheckbox ("Update settings", update, "Update settings in the global parameters (wil require saving).");
gd.showDialog();
if (gd.wasCanceled()) return false;
......@@ -63,11 +72,11 @@ public class VegetationSynthesis {
synth_directory = gd.getNextString(); // String
synth_scene = gd.getNextString(); // String
synth_model = gd.getNextString(); // String
synth_segments = gd.getNextString(); // String
synth_render_suffix = gd.getNextString(); // String
synth_crop_real = gd.getNextBoolean();
synth_scene_offs = gd.getNextString(); // String
synth_add_offs = gd.getNextBoolean();// boolean
update = gd.getNextBoolean();// boolean
if (update) {
clt_parameters.imp.terr_model_path = model_directory;
......@@ -75,8 +84,11 @@ public class VegetationSynthesis {
clt_parameters.imp.synth_directory = synth_directory;
clt_parameters.imp.synth_scene = synth_scene;
clt_parameters.imp.synth_model = synth_model;
clt_parameters.imp.synth_segments = synth_segments;
clt_parameters.imp.synth_render = synth_render_suffix;
clt_parameters.imp.synth_crop_real = synth_crop_real;
clt_parameters.imp.synth_scene_offs = synth_scene_offs;
clt_parameters.imp.synth_add_offs = synth_add_offs;
}
if (!synth_directory.endsWith(Prefs.getFileSeparator())) {
synth_directory+=Prefs.getFileSeparator();
......@@ -135,6 +147,25 @@ public class VegetationSynthesis {
rendered_model, // final double [][] synth, // will be modified
captured_images); // final double [][] captured) { // extracted NaN-s
}
double [][] scene_offs = null;
if (synth_add_offs && (synth_scene_offs != null) && (synth_scene_offs.trim().length()>0)) {
String path_scene_offs = synth_directory+synth_scene+synth_scene_offs;
ImagePlus imp_scene_offs = new ImagePlus(path_scene_offs);
if (imp_scene_offs.getWidth() == 0) {
System.out.println("testSynthetic(): Failed reading scene offs from: " + path_scene_offs);
} else {
int scene_offs_slices = imp_scene_offs.getStackSize();
System.out.println("testSynthetic(): read scene offsets from: " + path_scene_offs +", got "+scene_offs_slices+" slices, will add them to the rendered images");
scene_offs = QuadCLT.readDoubleArray(
imp_scene_offs, // ImagePlus imp,
0, // int num_slices, // (0 - all)
wh); // int [] wh); // int [] wh)
addSceneOffsets( // modify captured images to correct vignetting
captured_images, // final double [][] synth, // will be modified
scene_offs, // final double [][] scene_offsets, // extracted NaN-s
-1); // final double scale)
}
}
String rendered_title = synth_directory + synth_scene + (synth_crop_real?"-masked":"") +synth_render_suffix;
ImagePlus imp = ShowDoubleFloatArrays.makeArrays(
......@@ -159,9 +190,26 @@ public class VegetationSynthesis {
diffYminusfX[nscene][npix] = captured_images[nscene][npix] - rendered_model[nscene][npix];
}
}
double [][][] compareYfX = {captured_images, rendered_model, diffYminusfX};
String [] top_titles = {"captured", "synthesized", "captured-synthesized"};
String compare_title = synth_directory + synth_scene + (synth_crop_real?"-masked":"")+ "-compare"+ synth_render_suffix;
double [][][] scaleXandY = new double[2][num_scenes][num_pixels];
for (int i = 0; i < scaleXandY.length; i++) {
for (int nscene = 0; nscene < scaleXandY[0].length; nscene++) {
Arrays.fill(scaleXandY[i][nscene], Double.NaN);
}
}
for (int nscene = 0; nscene < scaleXandY[0].length; nscene++) {
for (int npix = 0; npix < num_pixels; npix++) {
if (scales_xy[nscene] != null) {
scaleXandY[0][nscene][npix] = scales_xy[nscene][npix][0];
scaleXandY[1][nscene][npix] = scales_xy[nscene][npix][1];
}
}
}
double [][][] compareYfX = {captured_images, rendered_model, diffYminusfX,scaleXandY[0],scaleXandY[1]};
String [] top_titles = {"captured", "synthesized", "captured-synthesized","scale_elevation_X","scale_elevation_Y"};
if (scene_offs != null) {
top_titles[0] += "_vignetting-corrected";
}
String compare_title = synth_directory + synth_scene + (synth_crop_real?"-masked":"")+ ((scene_offs != null)?"-vignetting-corrected":"")+ "-compare"+ synth_render_suffix;
ImagePlus imp_diff= ShowDoubleFloatArrays.showArraysHyperstack(
compareYfX, // double[][][] pixels,
width, // int width,
......@@ -202,6 +250,26 @@ public class VegetationSynthesis {
return;
}
public static void addSceneOffsets(
final double [][] synth, // will be modified
final double [][] scene_offsets,
final double scale) {
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nScene = ai.getAndIncrement(); nScene < synth.length; nScene = ai.getAndIncrement()) {
for (int npix = 0; npix < synth[nScene].length; npix++) {
synth[nScene][npix] += scale*scene_offsets[nScene][npix];
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return;
}
public VegetationSynthesis(
......@@ -237,15 +305,23 @@ public class VegetationSynthesis {
this.terr_elev_radius = terr_elev_radius;
return;
}
/**
* Calculate per-scene, per-pixel index (x+ y* width) synthetic images from the model in tvae[][] array. This method is made from
* VegitationLMA.getFxDerivs() by removing the code for derivatives and regularization parameters (improving fitted model convergence
* by adding requirements on the model in addition to the L2 norm of the difference between captured and simularted images)
* @param debugLevel debug level
* @return per-scene, per pixel 2D array of the simulated images values (temperatures)
*/
public double [][] renderModel (
final int debugLevel) {
final double [][] render = new double [num_scenes][num_pixels];
for (int nscene = 0; nscene < num_scenes; nscene++) {
Arrays.fill(render[nscene], Double.NaN);
}
// prepare elevation-related arrays that map vegetation temperatures and opacity to the rendered image pixels
setupElevationLMA(
debugLevel); // final int debugLevel);
// prepare terrain elevation-related arrays that map terrain temperatures to the rendered image pixels.
setupTerrainElevationPixLMA(
terr_elev_radius, // final double radius,
debugLevel); // final int debugLevel);
......@@ -255,6 +331,7 @@ public class VegetationSynthesis {
final int dbg_windex = -234; // -1;
final int dbg_wtindex = -340; // -1;
final int dbg_findx = -121775;
// Project vegetation and elevated terrain to the output images pixels
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
......@@ -262,6 +339,8 @@ public class VegetationSynthesis {
double [] alpha_woi = new double [num_pixels];
double [] veget_woi = new double [num_pixels];
double [] terrain_woi = new double [num_pixels]; // needs to be divided by terrain_woi_weights
// outer multi-threading iteration by scenes - scene rendering is independent between scenes, so they can be calculated
// in parallel.
for (int nScene = ai.getAndIncrement(); nScene < num_scenes; nScene = ai.getAndIncrement()) if (valid_scenes[nScene]){
Arrays.fill(alpha_woi,0);
Arrays.fill(veget_woi,0);
......@@ -272,6 +351,7 @@ public class VegetationSynthesis {
double [] terrain_scene = tvae[VegetationLMA.TVAO_TERRAIN];
// process vegetation, here individually by pixel, if it is not NaN
for (int wvindex = 0; wvindex < num_pixels; wvindex++) if (!Double.isNaN(vegetation_scene[wvindex])) {
// Here and below comments that mention woi, woi_veg remained from the original geFxDerivs
int x = wvindex % full.width; // relative to woi_veg
int y = wvindex / full.width; // relative to woi_veg
int npix = x + y * full.width;
......@@ -295,7 +375,7 @@ public class VegetationSynthesis {
} // for (int wvindex = 0; wvindex < woi_veg_length; wvindex++) if (valid_vegetation[wvindex]) {
if (terr_elpix_woi4 != null) { // per-pixel terrain elevation. Make mutually-exclusive with terr_elev_woi4
if (terr_elpix_woi4 != null) { // per-pixel terrain elevation.
for (int wtindex = 0; wtindex < num_pixels; wtindex++) if ((terr_elpix_woi4[nScene] != null) && (terr_elpix_woi4[nScene][wtindex] != null)) {
int x = wtindex % full.width; // relative to woi_terr
int y = wtindex / full.width; // relative to woi_terr
......@@ -376,13 +456,28 @@ public class VegetationSynthesis {
}
/**
* Based on VegetationLMA.setupElevationLMA() method. Removed largest part related to derivatives by parameters for Jacobian array calculation
* The VegetationLMA.setupElevationLMA() is called from getFxDerivs only once in the beginning and when elevation (of vegetation) was fitted. '
* Fitting with the elevation frozen (significant part of adjustment steps) this method was not skipped to increase the overall performance.
*
* Per-pixel elev_radius[] array (currently same value for all pixel) - radius of influence of the foliage elements (additionally scaled by
* elev_radius_extra). This is parameter is used to compensate for variable density of the projections in the areas of large elevation gradients.
*
* @param debugLevel debug level
*/
private void setupElevationLMA( // return pivot?
final int debugLevel) {
final double [] vegetation = tvae[VegetationLMA.TVAO_VEGETATION]; //
elev_woi4 = new int [num_scenes][][];
// next array per scene, per pixel has variable-length array of pixel indices (x + y*width). The values are indices of the render
// pixels indices that are influenced by the specific vegetation pixel (secon index)
elev_woi4 = new int [num_scenes][][]; // [scene][pixel][~4] pixel indices of 4 (or more/less) neighbors of projections (negatives)
// next array specifies influence amount of the current vegetation pixel on the pixels indexed by elev_woi4 above.
elev_weights4 = new double [num_scenes][][];
// Indexed by the render indices where the vegetation pixels are projected. These values are needed to normalize sum of the vegetation
// temperatures and opacities of the vegetation pixels that influence this render ones
elev_sum_weights = new double [num_scenes][];
// The above 3 arrays are the result of this method, they are used in renderModel() method.
//elev_radius[num_pixels];
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
......@@ -450,6 +545,7 @@ public class VegetationSynthesis {
};
}
ImageDtt.startAndJoin(threads);
if (debugLevel > 6) {
String title = "setupElevationLMA.tiff";
String [] titles = new String [num_scenes];
......@@ -478,11 +574,20 @@ public class VegetationSynthesis {
return;
}
/**
* Based on VegetationLMA.setupTerrainElevationPixLMA() method. Removed largest part related to derivatives by parameters for Jacobian
* array calculation. Most comments for the setupElevationLMA() above are applicable here. As the variable terrain elevation is much smaller
* (by an order of magnitude) that elevation of the vegetation
* @param radius radius of influence of the elevated terrain (now fixed to terr_elev_radius = 1.5)
* @param debugLevel debug level
*/
private void setupTerrainElevationPixLMA(
final double radius,
final int debugLevel) {
final double [] terrain = tvae[VegetationLMA.TVAO_TERRAIN]; //
final double [] terrain_elevation = tvae[VegetationLMA.TVAO_TERR_ELEV_PIX]; //
// The following 3 arrays are similar to the 3 corresponding arrays in setupElevationLMA() method
terr_elpix_woi4 = new int [num_scenes][][];
terr_elpix_weights4 = new double [num_scenes][][];
terr_elpix_sum_weights = new double [num_scenes][];
......
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