Commit af6220a8 authored by Andrey Filippov's avatar Andrey Filippov

creating terrain 3d (removing vegetation)

parent 4aec6d1f
...@@ -3122,7 +3122,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ ...@@ -3122,7 +3122,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
double avg_all = getMaskedAverage ( double avg_all = getMaskedAverage (
elev, // final double [] data, elev, // final double [] data,
null); // final boolean [] mask) null, // final boolean [] mask)
null); // final double [] stdp);
double abs_high= avg_all + initial_above; double abs_high= avg_all + initial_above;
double abs_low= avg_all - initial_below; double abs_low= avg_all - initial_below;
boolean [] mask = removeAbsoluteLowHigh ( boolean [] mask = removeAbsoluteLowHigh (
...@@ -3236,15 +3237,18 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ ...@@ -3236,15 +3237,18 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
* Calculate average of a double array, ignore masked out (!mask[i] and NaNs in the data) * Calculate average of a double array, ignore masked out (!mask[i] and NaNs in the data)
* @param data double data array * @param data double data array
* @param mask optional (may be null) boolean mask - ignore data items that have corresponding mask element false * @param mask optional (may be null) boolean mask - ignore data items that have corresponding mask element false
* @param stdp null or double[1] standard deviation
* @return average value of the non-NaN and not disabled by mask elements of data[] * @return average value of the non-NaN and not disabled by mask elements of data[]
*/ */
private static double getMaskedAverage ( public static double getMaskedAverage (
final double [] data, final double [] data,
final boolean [] mask) { final boolean [] mask,
final double [] stdp) {
final Thread[] threads = ImageDtt.newThreadArray(); final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
final AtomicInteger ati = new AtomicInteger(0); final AtomicInteger ati = new AtomicInteger(0);
final double [] avg_arr = new double [threads.length]; final double [] avg_arr = new double [threads.length];
final double [] std_arr = new double [threads.length];
final double [] npix_arr = new double [threads.length]; final double [] npix_arr = new double [threads.length];
for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() { threads[ithread] = new Thread() {
...@@ -3252,18 +3256,25 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ ...@@ -3252,18 +3256,25 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
int thread_num = ati.getAndIncrement(); int thread_num = ati.getAndIncrement();
for (int iPix = ai.getAndIncrement(); iPix < data.length; iPix = ai.getAndIncrement()) if (!Double.isNaN(data[iPix]) && ((mask == null) || (mask[iPix]))){ for (int iPix = ai.getAndIncrement(); iPix < data.length; iPix = ai.getAndIncrement()) if (!Double.isNaN(data[iPix]) && ((mask == null) || (mask[iPix]))){
avg_arr[thread_num] += data[iPix]; avg_arr[thread_num] += data[iPix];
std_arr[thread_num] += data[iPix]*data[iPix];
npix_arr[thread_num] += 1.0; npix_arr[thread_num] += 1.0;
} }
} }
}; };
} }
ImageDtt.startAndJoin(threads); ImageDtt.startAndJoin(threads);
double avg=0, num=0; double avg=0, num=0,sum2=0;
for (int i = 0; i < avg_arr.length; i++) { for (int i = 0; i < avg_arr.length; i++) {
avg+=avg_arr[i]; avg+=avg_arr[i];
num+=npix_arr[i]; num+=npix_arr[i];
sum2+=std_arr[i];
} }
return avg/num; avg /= num;
sum2 /= num;
if (stdp != null) {
stdp[0] = Math.sqrt(sum2- avg*avg);
}
return avg;
} }
/** /**
...@@ -3310,7 +3321,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ ...@@ -3310,7 +3321,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
* @param threshold_low remove lower elements () and NaNs in the data * @param threshold_low remove lower elements () and NaNs in the data
* @return updated mask (same instance if not null) that disables (makes false) filtered out data [] elements * @return updated mask (same instance if not null) that disables (makes false) filtered out data [] elements
*/ */
private static boolean [] removeAbsoluteLowHigh ( public static boolean [] removeAbsoluteLowHigh (
final double [] data, final double [] data,
final boolean [] mask, final boolean [] mask,
final double threshold_high, final double threshold_high,
...@@ -3386,7 +3397,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ ...@@ -3386,7 +3397,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
* @param num_bins number of the histogram bins * @param num_bins number of the histogram bins
* @return boolean array of the remaining data elements. Input mask_in array (if not null) is modified too. * @return boolean array of the remaining data elements. Input mask_in array (if not null) is modified too.
*/ */
private static boolean [] removeRelativeLowHigh ( public static boolean [] removeRelativeLowHigh (
final double [] data, final double [] data,
final boolean [] mask_in, final boolean [] mask_in,
final double abs_high, final double abs_high,
......
...@@ -320,8 +320,13 @@ public class IntersceneMatchParameters { ...@@ -320,8 +320,13 @@ public class IntersceneMatchParameters {
public double range_max = 5000.0; public double range_max = 5000.0;
// Export 3D model // Export 3D model
public boolean export3d = false; // true; public boolean export3d = false; // true;
public boolean export3dterrain = false; // true;
// Generate CT scan
public boolean export_CT = false; // true;
public double ct_min = 3.7; //
public double ct_max = 4.5; //
public double ct_step = 0.02; // pix
public int ct_expand = 2; // pix // expand section area by 1 pixel in 8 directions
// Debug and visualization // Debug and visualization
public boolean scene_is_ref_test= false; // correlate ref-2-ref for testing public boolean scene_is_ref_test= false; // correlate ref-2-ref for testing
...@@ -1149,6 +1154,15 @@ min_str_neib_fpn 0.35 ...@@ -1149,6 +1154,15 @@ min_str_neib_fpn 0.35
gd.addMessage ("3D model generation"); gd.addMessage ("3D model generation");
gd.addCheckbox ("Generate 3D model", this.export3d, gd.addCheckbox ("Generate 3D model", this.export3d,
"Generate textures and model."); "Generate textures and model.");
gd.addCheckbox ("Generate 3D model of terrain", this.export3dterrain,
"Generate textures and model, remove vegetation.");
gd.addMessage ("CT scan generation");
gd.addCheckbox ("Generate ST scan", this.export_CT, "Generate \"CT scan\" of the vegetation.");
gd.addNumericField("Minimal CT scan disparity", this.ct_min, 5,7,"pix","Start disparity (lowest altitude).");
gd.addNumericField("Maximal CT scan disparity", this.ct_max, 5,7,"pix","End disparity (highest altitude).");
gd.addNumericField("CT scan step", this.ct_step, 5,7,"pix","Scan step.");
gd.addNumericField("CT scan expand section", this.ct_expand, 0,3,"tiles","expand section area, 2 - a tile in 8 directions.");
gd.addMessage ("Debug and visialization parameters"); gd.addMessage ("Debug and visialization parameters");
gd.addCheckbox ("Replace scene with reference scene", this.scene_is_ref_test, gd.addCheckbox ("Replace scene with reference scene", this.scene_is_ref_test,
...@@ -2075,6 +2089,13 @@ min_str_neib_fpn 0.35 ...@@ -2075,6 +2089,13 @@ min_str_neib_fpn 0.35
this.range_max = gd.getNextNumber(); this.range_max = gd.getNextNumber();
this.export3d = gd.getNextBoolean(); this.export3d = gd.getNextBoolean();
this.export3dterrain = gd.getNextBoolean();
this.export_CT = gd.getNextBoolean();
this.ct_min = gd.getNextNumber();
this.ct_max = gd.getNextNumber();
this.ct_step = gd.getNextNumber();
this.ct_expand = (int) gd.getNextNumber();
this.scene_is_ref_test = gd.getNextBoolean(); this.scene_is_ref_test = gd.getNextBoolean();
this.render_ref = gd.getNextBoolean(); this.render_ref = gd.getNextBoolean();
...@@ -2684,6 +2705,13 @@ min_str_neib_fpn 0.35 ...@@ -2684,6 +2705,13 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"range_min_strength", this.range_min_strength+""); // double properties.setProperty(prefix+"range_min_strength", this.range_min_strength+""); // double
properties.setProperty(prefix+"range_max", this.range_max+""); // double properties.setProperty(prefix+"range_max", this.range_max+""); // double
properties.setProperty(prefix+"export3d", this.export3d+""); // boolean properties.setProperty(prefix+"export3d", this.export3d+""); // boolean
properties.setProperty(prefix+"export3dterrain", this.export3dterrain+""); // boolean
properties.setProperty(prefix+"export_CT", this.export_CT+""); // boolean
properties.setProperty(prefix+"ct_min", this.ct_min+""); // double
properties.setProperty(prefix+"ct_max", this.ct_max+""); // double
properties.setProperty(prefix+"ct_step", this.ct_step+""); // double
properties.setProperty(prefix+"ct_expand", this.ct_expand+""); // int
properties.setProperty(prefix+"scene_is_ref_test", this.scene_is_ref_test+""); // boolean properties.setProperty(prefix+"scene_is_ref_test", this.scene_is_ref_test+""); // boolean
properties.setProperty(prefix+"render_ref", this.render_ref+""); // boolean properties.setProperty(prefix+"render_ref", this.render_ref+""); // boolean
...@@ -3256,7 +3284,13 @@ min_str_neib_fpn 0.35 ...@@ -3256,7 +3284,13 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"range_max")!=null) this.range_max=Double.parseDouble(properties.getProperty(prefix+"range_max")); if (properties.getProperty(prefix+"range_max")!=null) this.range_max=Double.parseDouble(properties.getProperty(prefix+"range_max"));
if (properties.getProperty(prefix+"export3d")!=null) this.export3d=Boolean.parseBoolean(properties.getProperty(prefix+"export3d")); if (properties.getProperty(prefix+"export3d")!=null) this.export3d=Boolean.parseBoolean(properties.getProperty(prefix+"export3d"));
if (properties.getProperty(prefix+"export3dterrain")!=null) this.export3dterrain=Boolean.parseBoolean(properties.getProperty(prefix+"export3dterrain"));
if (properties.getProperty(prefix+"export_CT")!=null) this.export_CT=Boolean.parseBoolean(properties.getProperty(prefix+"export_CT"));
if (properties.getProperty(prefix+"ct_min")!=null) this.ct_min=Double.parseDouble(properties.getProperty(prefix+"ct_min"));
if (properties.getProperty(prefix+"ct_max")!=null) this.ct_max=Double.parseDouble(properties.getProperty(prefix+"ct_max"));
if (properties.getProperty(prefix+"ct_step")!=null) this.ct_step=Double.parseDouble(properties.getProperty(prefix+"ct_step"));
if (properties.getProperty(prefix+"ct_expand")!=null) this.ct_expand=Integer.parseInt(properties.getProperty(prefix+"ct_expand"));
if (properties.getProperty(prefix+"scene_is_ref_test")!=null) this.scene_is_ref_test=Boolean.parseBoolean(properties.getProperty(prefix+"scene_is_ref_test")); if (properties.getProperty(prefix+"scene_is_ref_test")!=null) this.scene_is_ref_test=Boolean.parseBoolean(properties.getProperty(prefix+"scene_is_ref_test"));
if (properties.getProperty(prefix+"render_ref")!=null) this.render_ref=Boolean.parseBoolean(properties.getProperty(prefix+"render_ref")); if (properties.getProperty(prefix+"render_ref")!=null) this.render_ref=Boolean.parseBoolean(properties.getProperty(prefix+"render_ref"));
...@@ -3834,8 +3868,13 @@ min_str_neib_fpn 0.35 ...@@ -3834,8 +3868,13 @@ min_str_neib_fpn 0.35
imp.range_min_strength = this.range_min_strength; imp.range_min_strength = this.range_min_strength;
imp.range_max = this.range_max; imp.range_max = this.range_max;
imp.export3d = this.export3d; imp.export3d = this.export3d;
imp.export3dterrain = this.export3dterrain;
imp.export_CT = this.export_CT;
imp.ct_min = this.ct_min;
imp.ct_max = this.ct_max;
imp.ct_step = this.ct_step;
imp.ct_expand = this.ct_expand;
imp.scene_is_ref_test = this.scene_is_ref_test; imp.scene_is_ref_test = this.scene_is_ref_test;
imp.render_ref = this.render_ref; imp.render_ref = this.render_ref;
......
...@@ -4673,6 +4673,13 @@ public class OpticalFlow { ...@@ -4673,6 +4673,13 @@ public class OpticalFlow {
boolean generate_mapped = clt_parameters.imp.generate_mapped && boolean generate_mapped = clt_parameters.imp.generate_mapped &&
(gen_seq_mono_color[0] || gen_seq_mono_color[1]); // generate sequences - Tiff and/or video (gen_seq_mono_color[0] || gen_seq_mono_color[1]); // generate sequences - Tiff and/or video
boolean export3d = clt_parameters.imp.export3d; // true; boolean export3d = clt_parameters.imp.export3d; // true;
boolean export3dterrain = clt_parameters.imp.export3dterrain; // true;
boolean export_CT = clt_parameters.imp.export_CT; // false;
double ct_min = clt_parameters.imp.ct_min ;
double ct_max = clt_parameters.imp.ct_max ;
double ct_step = clt_parameters.imp.ct_step ;
int ct_expand = clt_parameters.imp.ct_expand ;
boolean [] annotate_mono_color = {clt_parameters.imp.annotate_mono,clt_parameters.imp.annotate_color}; boolean [] annotate_mono_color = {clt_parameters.imp.annotate_mono,clt_parameters.imp.annotate_color};
boolean annotate_transparent_mono = clt_parameters.imp.annotate_transparent_mono; boolean annotate_transparent_mono = clt_parameters.imp.annotate_transparent_mono;
...@@ -6176,9 +6183,60 @@ public class OpticalFlow { ...@@ -6176,9 +6183,60 @@ public class OpticalFlow {
} }
} }
if (export_CT) {
double [][][] ct_scans = new double [(int) Math.ceil((ct_max-ct_min)/ct_step) + 1][][];
boolean ok_ct = TexturedModel.output3d( // quadCLTs have same image name, and everything else
clt_parameters, // CLTParameters clt_parameters,
colorProcParameters, // ColorProcParameters colorProcParameters,
rgbParameters, // EyesisCorrectionParameters.RGBParameters rgbParameters,
quadCLTs[ref_index], // quadCLTs.length-1], // quadCLT_main, // final QuadCLT parameter_scene, // to use for rendering parameters in multi-series sequences
// if null - use reference scene
quadCLTs, // QuadCLT [] scenes,
ref_index, // final int ref_index,
combo_dsn_final, //double [][] combo_dsn_final, // null OK, will read file
ct_scans, // final double [][] ct_scans,
ct_min, // final double ct_min,
ct_step, // final double ct_step,
ct_expand, // final int ct_expand,
false, // final boolean terrain_mode,
null, // final double [][] hdr_render_size, // { hdr_whs[3],hdr_x0y0[2]}; save/use rendering parameters
false, // final boolean hdr_render_slave,// use rendering parameters (to match other mode)
updateStatus, // final boolean updateStatus,
debugLevel); // + 1); // final int debugLevel)
System.out.println ("CT scan-> "+ok_ct);
String [] titles = new String[ct_scans.length];
for (int i = 0; i < titles.length; i++) {
titles[i] = String.format("disparity=%.3f pix",ct_min+ct_step*i);
}
String suffix = String.format("-CT_SCAN_%.3f_%.3f_%.3f_%d",ct_min,ct_max,ct_step,ct_expand);
final int transform_size= quadCLTs[ref_index].getTileProcessor().getTileSize();
final int tilesX = quadCLTs[ref_index].getTileProcessor().getTilesX();
final int tilesY = quadCLTs[ref_index].getTileProcessor().getTilesY();
int nslices = 0;
for (int n = 0; n < ct_scans.length; n++) {
nslices = Math.max(nslices, ct_scans[n].length);
}
for (int nslice = 0; nslice < nslices; nslice++) {
double [][] ct_scan_slice = new double [ct_scans.length][];
for (int n = 0; n < ct_scan_slice.length; n++) {
// int i = Math.min(nslice, ct_scans[n].length);
if (nslice < ct_scans[n].length) {
ct_scan_slice[n] = ct_scans[n][nslice];
}
}
quadCLTs[ref_index].saveDoubleArrayInModelDirectory(
suffix+"-SLICE"+nslice, // String suffix,
titles, // String [] labels, // or null
ct_scan_slice, // double [][] data,
tilesX * transform_size, // int width, // int tilesX,
tilesY * transform_size); // int height, // int tilesY,
}
}
// debugging 3D model // debugging 3D model
int [] whs = new int[3]; int [] whs = new int[3];
double [] x0y0 = new double[2]; double [] x0y0 = new double[2];
double [][] hdr_render_size = new double[2][];
if (export3d) { //combo_dsn_final had strength 1.0e-4 where it should not? Reset it? if (export3d) { //combo_dsn_final had strength 1.0e-4 where it should not? Reset it?
boolean ok_3d = TexturedModel.output3d( // quadCLTs have same image name, and everything else boolean ok_3d = TexturedModel.output3d( // quadCLTs have same image name, and everything else
clt_parameters, // CLTParameters clt_parameters, clt_parameters, // CLTParameters clt_parameters,
...@@ -6189,9 +6247,38 @@ public class OpticalFlow { ...@@ -6189,9 +6247,38 @@ public class OpticalFlow {
quadCLTs, // QuadCLT [] scenes, quadCLTs, // QuadCLT [] scenes,
ref_index, // final int ref_index, ref_index, // final int ref_index,
combo_dsn_final, //double [][] combo_dsn_final, // null OK, will read file combo_dsn_final, //double [][] combo_dsn_final, // null OK, will read file
null, // final double [][] ct_scans,
0, // final double ct_min,
0, // final double ct_step,
0, // final int ct_expand,
false, // final boolean terrain_mode,
hdr_render_size, // final double [][] hdr_render_size, // { hdr_whs[3],hdr_x0y0[2]}; save/use rendering parameters
false, // final boolean hdr_render_slave,// use rendering parameters (to match other mode)
updateStatus, // final boolean updateStatus,
debugLevel); // + 1); // final int debugLevel)
System.out.println ("TexturedModel.output3d() -> "+ok_3d+" (full, with vegetation)");
}
if (export3dterrain) { //combo_dsn_final had strength 1.0e-4 where it should not? Reset it?
boolean hdr_render_slave= true;
boolean ok_3d = TexturedModel.output3d( // quadCLTs have same image name, and everything else
clt_parameters, // CLTParameters clt_parameters,
colorProcParameters, // ColorProcParameters colorProcParameters,
rgbParameters, // EyesisCorrectionParameters.RGBParameters rgbParameters,
quadCLTs[ref_index], // quadCLTs.length-1], // quadCLT_main, // final QuadCLT parameter_scene, // to use for rendering parameters in multi-series sequences
// if null - use reference scene
quadCLTs, // QuadCLT [] scenes,
ref_index, // final int ref_index,
combo_dsn_final, //double [][] combo_dsn_final, // null OK, will read file
null, // final double [][] ct_scans,
0, // final double ct_min,
0, // final double ct_step,
0, // final int ct_expand,
true, // final boolean terrain_mode,
hdr_render_size, // final double [][] hdr_render_size, // { hdr_whs[3],hdr_x0y0[2]}; save/use rendering parameters
hdr_render_slave, // final boolean hdr_render_slave,// use rendering parameters (to match other mode)
updateStatus, // final boolean updateStatus, updateStatus, // final boolean updateStatus,
debugLevel); // + 1); // final int debugLevel) debugLevel); // + 1); // final int debugLevel)
System.out.println ("TexturedModel.output3d() -> "+ok_3d); System.out.println ("TexturedModel.output3d() -> "+ok_3d+" (terrain only, no vegetation)");
} }
......
...@@ -75,6 +75,7 @@ import com.elphel.imagej.ims.Did_ins_2; ...@@ -75,6 +75,7 @@ import com.elphel.imagej.ims.Did_ins_2;
import com.elphel.imagej.ims.Did_pimu; import com.elphel.imagej.ims.Did_pimu;
import com.elphel.imagej.ims.EventLogger; import com.elphel.imagej.ims.EventLogger;
import com.elphel.imagej.ims.Imx5; import com.elphel.imagej.ims.Imx5;
import com.elphel.imagej.orthomosaic.OrthoMap;
import com.elphel.imagej.readers.ElphelTiffWriter; import com.elphel.imagej.readers.ElphelTiffWriter;
import com.elphel.imagej.readers.ImagejJp4Tiff; import com.elphel.imagej.readers.ImagejJp4Tiff;
import com.elphel.imagej.x3d.export.TriMesh; import com.elphel.imagej.x3d.export.TriMesh;
...@@ -1706,6 +1707,85 @@ public class QuadCLTCPU { ...@@ -1706,6 +1707,85 @@ public class QuadCLTCPU {
tilesY); // int height) tilesY); // int height)
} }
public double [] getFlatGround(
double [] disparity,
double rmse_above, // from average
double rmse_below, // from average, // positive value
int num_refine,
double frac_above,
double frac_below,
String debug_title) {
final double [] plane_disparity = new double [disparity.length];
final int num_bins = 1024;
final int tilesX = tp.getTilesX();
final int tilesY = tp.getTilesY();
final double [] center_xy= {0.5*tilesX, 0.5*tilesY};
final double [] stdp = new double[1];
double avg_all = OrthoMap.getMaskedAverage (
disparity, // final double [] data,
null, // final boolean [] mask)
stdp); // final double [] stdp);
double initial_above = rmse_above*stdp[0];
double initial_below = rmse_below*stdp[0];
double abs_high= avg_all + initial_below;
double abs_low= avg_all - rmse_below*stdp[0];
boolean [] mask = OrthoMap.removeAbsoluteLowHigh (
disparity, // final double [] data,
null, // final boolean [] mask,
abs_high, // final double threshold_high,
abs_low); // final double threshold_low),
double [] plane_tiles = {0,0,avg_all,center_xy[0], center_xy[1]}; // 5 elements here
for (int ntry = 0; ntry < num_refine; ntry++) {
if (ntry > 0) {
// remove relatives, start from new mask
mask = OrthoMap.removeRelativeLowHigh (
disparity, // final double [] data,
null, // final boolean [] mask_in,
initial_above, // final double abs_high,
-initial_below, // final double abs_low,
frac_above, // final double rhigh,
frac_below, // final double rlow,
plane_tiles, // final double [] ground_plane, // tiltx,tilty, offs, x0(pix), y0(pix) or null
tilesX, // final int width, // only used with ground_plane != null;
num_bins); // final int num_bins)
}
plane_tiles= OrthoMap.getPlane(
disparity, // final double [] data,
mask , // final boolean [] mask,
null, // final double [] weight,
tilesX, // final int width,
center_xy); // final double [] xy0)
}
for (int nTile = 0; nTile < disparity.length; nTile++) {
int tileX = nTile % tilesX;
int tileY = nTile / tilesX;
double x = tileX - plane_tiles[3];
double y = tileY - plane_tiles[4];
plane_disparity[nTile] = plane_tiles[2]+ x *plane_tiles[0] +y * plane_tiles[1];
}
if (debug_title != null) {
String [] dbg_titles = {"disparity", "plane", "diff"};
double [][] dbg_img = new double [dbg_titles.length][disparity.length];
dbg_img[0] = disparity;
dbg_img[1] = plane_disparity;
for (int i = 0; i < disparity.length; i++) {
dbg_img[2][i] = disparity[i] - plane_disparity[i];
}
ShowDoubleFloatArrays.showArrays(
dbg_img,
tilesX,
tilesY,
true,
debug_title,
dbg_titles);
}
return plane_disparity;
}
public double [] getSmoothGround( public double [] getSmoothGround(
CLTParameters clt_parameters, CLTParameters clt_parameters,
......
...@@ -43,6 +43,7 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays; ...@@ -43,6 +43,7 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.correction.EyesisCorrections; import com.elphel.imagej.correction.EyesisCorrections;
import com.elphel.imagej.gpu.TpTask; import com.elphel.imagej.gpu.TpTask;
import com.elphel.imagej.ims.Imx5; import com.elphel.imagej.ims.Imx5;
import com.elphel.imagej.orthomosaic.OrthoMap;
import com.elphel.imagej.x3d.export.GlTfExport; import com.elphel.imagej.x3d.export.GlTfExport;
import com.elphel.imagej.x3d.export.Render3D; import com.elphel.imagej.x3d.export.Render3D;
import com.elphel.imagej.x3d.export.TriMesh; import com.elphel.imagej.x3d.export.TriMesh;
...@@ -2430,6 +2431,116 @@ public class TexturedModel { ...@@ -2430,6 +2431,116 @@ public class TexturedModel {
titles); titles);
} }
public static double [] getTerrainDisparity(
final double [] disparity, // maybe already filtered from smooth (combined, allow strong deviations)
final double [] flat,
final double threshold_above,
final int expand,
final int width){
final int height = disparity.length/width;
double [] terrain_disparity = disparity.clone();
boolean [] above_terrain = new boolean [disparity.length];
for (int i = 0; i <disparity.length; i++) {
above_terrain[i] = (disparity[i]-flat[i]) > threshold_above;
}
TileNeibs tn = new TileNeibs (width,height);
tn.growSelection(
expand, // int grow, // grow tile selection by 1 over non-background tiles 1: 4 directions, 2 - 8 directions, 3 - 8 by 1, 4 by 1 more
above_terrain, //final boolean [] tiles,
null); // final boolean [] prohibit)
for (int i = 0; i <above_terrain.length; i++) if (above_terrain[i]){
terrain_disparity[i] = Double.NaN;
}
OrthoMap.fillNaNs(
terrain_disparity, // double [] data,
tn, // TileNeibs tn,
3); // int min_neibs)
return terrain_disparity;
}
public static void mixDisparityWithSmooth(
double [][] ds_fg_bg, // modified inside
double [][] ss_fg_bg, // modified inside
double [] smooth_ground,
double [] sfm_gain,
double gsmth_sfm_gain,
int gsmth_sfm_rad,
double lim_disparity, // 100
double gsmth_str_bump,
double gsmth_str_dip,
double small_strength,
int width,
String dbg_title) {
double [][] ds_fg_bg_bkp = (dbg_title != null) ? (new double [][] {ds_fg_bg[0].clone(), ds_fg_bg[1].clone()}): null;
double [][] ss_fg_bg_bkp = (dbg_title != null) ? (new double [][] {ss_fg_bg[0].clone(), ss_fg_bg[1].clone()}): null;
TileNeibs tn = new TileNeibs(width, smooth_ground.length/width);
for (int ntile = 0; ntile < smooth_ground.length; ntile++) {
double disp = (ss_fg_bg[1][ntile] > ss_fg_bg[0][ntile]) ? ds_fg_bg[1][ntile] : ds_fg_bg[1][ntile]; // strongest
if (disp > lim_disparity) {
disp = lim_disparity;
}
double str = Math.max(ss_fg_bg[1][ntile], ss_fg_bg[0][ntile]);
boolean strong = false;
if (disp > smooth_ground[ntile]) {
strong = str >= gsmth_str_bump;
} else {
strong = str >= gsmth_str_dip;
}
if (strong) {
check_neibs:
{
for (int dy = -gsmth_sfm_rad; dy <= gsmth_sfm_rad; dy++) {
for (int dx = -gsmth_sfm_rad; dx <= gsmth_sfm_rad; dx++) {
int ntile1 = tn.getNeibIndex(ntile, dx, dy);
if ((ntile1 < 0) || (sfm_gain[ntile1] < gsmth_sfm_gain)) {
strong = false;
break check_neibs;
}
}
}
if (disp > smooth_ground[ntile]) {
ds_fg_bg[0][ntile] = disp;
ss_fg_bg[0][ntile] = str;
ds_fg_bg[1][ntile] = smooth_ground[ntile];
ss_fg_bg[1][ntile] = small_strength;
} else {
ds_fg_bg[0][ntile] = Double.NaN;
ss_fg_bg[0][ntile] = 0.0;
smooth_ground[ntile] = disp;
ds_fg_bg[1][ntile] = smooth_ground[ntile];
ss_fg_bg[1][ntile] = str;
}
}
}
if (!strong) { // either was weak or broke check_neibs
ds_fg_bg[0][ntile] = Double.NaN;
ds_fg_bg[1][ntile] = smooth_ground[ntile];
ss_fg_bg[0][ntile] = 0.0;
ss_fg_bg[1][ntile] = str;
}
}
if (dbg_title != null) {
String [] dbg_titles = {"FG0","BG0","FG", "BG", "SG0", "SG1", "SG", "BG"};
double [][] dbg_img = {
ds_fg_bg_bkp[0], ds_fg_bg_bkp[1], ds_fg_bg[0], ds_fg_bg[1],
ss_fg_bg_bkp[0], ss_fg_bg_bkp[1], ss_fg_bg[0], ss_fg_bg[1],
};
ShowDoubleFloatArrays.showArrays(
dbg_img,
width,
dbg_img[0].length/width,
true,
dbg_title,
dbg_titles);
}
return;
}
/** /**
...@@ -2453,9 +2564,20 @@ public class TexturedModel { ...@@ -2453,9 +2564,20 @@ public class TexturedModel {
QuadCLT [] scenes, QuadCLT [] scenes,
final int ref_index, final int ref_index,
double [][] combo_dsn_final, // null OK, will read file double [][] combo_dsn_final, // null OK, will read file
final double [][][] ct_scans,
final double ct_min,
final double ct_step,
final int ct_expand_in,
final boolean terrain_mode,
final double [][] hdr_render_size, // { hdr_whs[3],hdr_x0y0[2]}; save/use rendering parameters
final boolean hdr_render_slave,// use rendering parameters (to match other mode)
final boolean updateStatus, final boolean updateStatus,
final int debugLevel) final int debugLevel)
{ {
final boolean save_ct_disp = true;
final boolean expand_bg = (ct_expand_in <0);
final int ct_expand = Math.abs(ct_expand_in);
final boolean map_en = clt_parameters.gmap_en; final boolean map_en = clt_parameters.gmap_en;
final boolean render_hdr = clt_parameters.gmap_render_hdr || map_en;// true; //false; // true; // generate textures w/o normalization to generate undistorted final boolean render_hdr = clt_parameters.gmap_render_hdr || map_en;// true; //false; // true; // generate textures w/o normalization to generate undistorted
final boolean use_parallel_proj = clt_parameters.gmap_parallel_proj; // Use parallel projection (map)\ final boolean use_parallel_proj = clt_parameters.gmap_parallel_proj; // Use parallel projection (map)\
...@@ -2556,6 +2678,7 @@ public class TexturedModel { ...@@ -2556,6 +2678,7 @@ public class TexturedModel {
ArrayList<TriMesh> tri_meshes = null; ArrayList<TriMesh> tri_meshes = null;
long startStepTime=System.nanoTime(); long startStepTime=System.nanoTime();
final int tilesX = tp.getTilesX(); final int tilesX = tp.getTilesX();
final int tilesY = tp.getTilesY();
final int transform_size = tp.getTileSize(); final int transform_size = tp.getTileSize();
final int width = tilesX * transform_size; final int width = tilesX * transform_size;
...@@ -2570,8 +2693,8 @@ public class TexturedModel { ...@@ -2570,8 +2693,8 @@ public class TexturedModel {
combo_dsn_final =scenes[ref_index].restoreComboDSI(true); // also sets quadCLTs[ref_index].dsi and blue sky combo_dsn_final =scenes[ref_index].restoreComboDSI(true); // also sets quadCLTs[ref_index].dsi and blue sky
} }
double[][] ds_fg_bg = null; double[][] ds_fg_bg_common = null;
double[][] ss_fg_bg = null; double[][] ss_fg_bg_common = null;
double small_strength = 0.0001; double small_strength = 0.0001;
/// normal conditioning /// normal conditioning
...@@ -2607,6 +2730,7 @@ public class TexturedModel { ...@@ -2607,6 +2730,7 @@ public class TexturedModel {
combo_dsn_final[OpticalFlow.COMBO_DSN_INDX_LMA_BG].clone(), combo_dsn_final[OpticalFlow.COMBO_DSN_INDX_LMA_BG].clone(),
combo_dsn_final[OpticalFlow.COMBO_DSN_INDX_STRENGTH_BG].clone() combo_dsn_final[OpticalFlow.COMBO_DSN_INDX_STRENGTH_BG].clone()
}; };
for (int i = 0; i < dls_bg[0].length; i++) if (Double.isNaN(dls_bg[0][i])){ for (int i = 0; i < dls_bg[0].length; i++) if (Double.isNaN(dls_bg[0][i])){
dls_bg[0][i] = dls_fg[0][i]; dls_bg[0][i] = dls_fg[0][i];
dls_bg[1][i] = dls_fg[1][i]; dls_bg[1][i] = dls_fg[1][i];
...@@ -2643,52 +2767,246 @@ public class TexturedModel { ...@@ -2643,52 +2767,246 @@ public class TexturedModel {
} }
} }
ds_fg_bg = new double[][] {ds_fg[0], ds_bg[0].clone()};
ss_fg_bg = new double[][] {ds_fg[1], ds_bg[1]};
boolean mixed_flat = false;
double lim_disparity_noct=100;
int num_scans = (ct_scans==null)? 1 : ct_scans.length;
TileCluster [] tileClusters = null;
double[][][] faded_textures = null;
double [][][][] lin_text0 = null;
double [][] ct_disparity = ((ct_scans!=null) && save_ct_disp)? new double [num_scans][]:null;
if (show_bs_debug) { if (show_bs_debug) {
String [] dbg_titles = {"FG","BG","BS"}; String [] dbg_titles = {"FG","BG","FS", "BS"};
double [][] dbg_img = {ds_fg_bg[0], ds_fg_bg[1],combo_dsn_final[OpticalFlow.COMBO_DSN_INDX_BLUE_SKY].clone()}; double [][] dbg_img = {ds_fg[0], ds_bg[0],ds_fg[1], ds_bg[1]}; // here BG==FG
for (int i = 0; i < dbg_img[0].length; i++) {
dbg_img[2][i] = sky_tiles[i]? 20:0; // *= 20;
}
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
dbg_img, dbg_img,
tilesX, tilesX,
dbg_img[0].length/tilesX, dbg_img[0].length/tilesX,
true, true,
ref_scene.getImageName()+"-disparity_layers", ref_scene.getImageName()+"-fg-bg-disparity_strength",
dbg_titles); dbg_titles);
} }
ds_fg_bg_common = new double[][] {ds_fg[0].clone(), ds_bg[0].clone()};
ss_fg_bg_common = new double[][] {ds_fg[1].clone(), ds_bg[1].clone()};
/*
if (ct_scans==null) {
for (int i = 0; i < ds_fg_bg[0].length; i++) {
if (ds_fg_bg[0][i] > lim_disparity) {
ds_fg_bg[0][i] = lim_disparity;
}
if (ds_fg_bg[1][i] > lim_disparity) {
ds_fg_bg[1][i] = lim_disparity;
}
}
}
*/
// Create data for consolidated textures (multiple texture segments combined in same "passes" // Create data for consolidated textures (multiple texture segments combined in same "passes"
// now it will be able to modify ds_fg_bg and sky_tiles to improve around blue sky // now it will be able to modify ds_fg_bg and sky_tiles to improve around blue sky
if (require_lma) { // make non-LMA very weak; if (require_lma) { // make non-LMA very weak;
for (int i = 0; i < ss_fg_bg.length; i++) { for (int i = 0; i < ss_fg_bg_common.length; i++) {
ss_fg_bg[i]= ss_fg_bg[i].clone(); ss_fg_bg_common[i]= ss_fg_bg_common[i].clone();
} }
for (int i = 0; i < ss_fg_bg[0].length; i++) { for (int i = 0; i < ss_fg_bg_common[0].length; i++) {
if (Double.isNaN(dls_fg[1][i])){ if (Double.isNaN(dls_fg[1][i])){ // no LMA
ss_fg_bg[0][i] = Math.min(ss_fg_bg[0][i],small_strength); // do not increase if it was already 0 ss_fg_bg_common[0][i] = Math.min(ss_fg_bg_common[0][i],small_strength); // do not increase if it was already 0
} }
if (Double.isNaN(dls_bg[1][i])){ if (Double.isNaN(dls_bg[1][i])){
ss_fg_bg[1][i] = Math.min(ss_fg_bg[1][i],small_strength); // do not increase if it was already 0 ss_fg_bg_common[1][i] = Math.min(ss_fg_bg_common[1][i],small_strength); // do not increase if it was already 0
} }
} }
if (show_bs_debug) {
String [] dbg_titles = {"FG","BG","FG_LMA", "BG_LMA", "FS", "BS"};
double [][] dbg_img = {ds_fg_bg_common[0], ds_fg_bg_common[1], dls_fg[1], dls_bg[1], ss_fg_bg_common[0], ss_fg_bg_common[1]}; // here BG==FG
ShowDoubleFloatArrays.showArrays(
dbg_img,
tilesX,
dbg_img[0].length/tilesX,
true,
ref_scene.getImageName()+"-fg-bg-disparity_strength-LMA",
dbg_titles);
} }
// ------- }
boolean mixed_flat = false; double [] smooth_ground = null;
double rmse_above = 1.0; // from average
double rmse_below = 1.0; // from average, // positive value
int num_refine = 5;
double frac_above = 0.4;
double frac_below = 0.3;
double [] flat_ground = null;
final double threshold_above = 0.05;
final int expand_above = 4; // 2;
if (gsmth_enable && (!has_sfm || gsmth_sfm_gnd)) { if (gsmth_enable && (!has_sfm || gsmth_sfm_gnd)) {
double [] smooth_ground = scenes[ref_index].getSmoothGround( smooth_ground = scenes[ref_index].getSmoothGround(
clt_parameters, clt_parameters,
has_sfm, // boolean sfm_mode, has_sfm, // boolean sfm_mode,
debugLevel); debugLevel);
String title_flat = (show_bs_debug)? (ref_scene.getImageName()+"-dbg_flat"):null ;
flat_ground = scenes[ref_index].getFlatGround(
smooth_ground, // double [] disparity,
rmse_above, //double rmse_above, // from average
rmse_below, // double rmse_below, // from average, // positive value
num_refine, // int num_refine,
frac_above, // double frac_above,
frac_below, // double frac_below,
title_flat); // String debug_title)
if (smooth_ground != null) {
if (has_sfm && gsmth_sfm_deviate) {
mixed_flat = true;
String dbg_title = show_bs_debug?(ref_scene.getImageName()+"-fg-bg-disparity_strength-LMA-GND-FLAT"):null;
mixDisparityWithSmooth(
ds_fg_bg_common, //double [][] ds_fg_bg, // modified inside
ss_fg_bg_common, //double [][] ss_fg_bg, // modified inside
smooth_ground, // double [] smooth_ground,
sfm_gain, // double [] sfm_gain,
gsmth_sfm_gain, // double gsmth_sfm_gain,
gsmth_sfm_rad, // int gsmth_sfm_rad,
100, // double lim_disparity, // 100
gsmth_str_bump, // double gsmth_str_bump,
gsmth_str_dip, // double gsmth_str_dip,
small_strength, // double small_strength,
tilesX, // int width)
dbg_title); // String dbg_title);
} else { // smooth surface only: nothing in FG, surface - in BG
for (int i = 0; i < smooth_ground.length; i++) {
ds_fg_bg_common[1][i] = smooth_ground[i];
ss_fg_bg_common[1][i] = Math.max(ss_fg_bg_common[1][i],ss_fg_bg_common[0][i]);
ss_fg_bg_common[1][i] = Math.max(ss_fg_bg_common[1][i],small_strength);
ds_fg_bg_common[0][i] = Double.NaN;
ss_fg_bg_common[0][i] = 0.0;
}
}
}
double [] single_disparity = ds_fg_bg_common[0].clone();
for (int i = 0; i < single_disparity.length; i++) if (ss_fg_bg_common[1][i] > ss_fg_bg_common[0][i]) {
single_disparity[i] = ds_fg_bg_common[1][i];
}
double [] terrain_disparity = getTerrainDisparity(
single_disparity, // final double [] disparity, // maybe already filtered from smooth (combined, allow strong deviations)
flat_ground, // final double [] flat,
threshold_above, // final double threshold_above,
expand_above, // final int expand,
tilesX); // final int width) ;
if (show_bs_debug) {
String [] dbg_titles = {"FG","BG","FG_LMA", "BG_LMA", "GND", "FLAT", "SINGLE", "TERRAIN", "FS", "BS"};
double [][] dbg_img = {
ds_fg_bg_common[0], ds_fg_bg_common[1], dls_fg[1], dls_bg[1],
smooth_ground, flat_ground, single_disparity, terrain_disparity,
ss_fg_bg_common[0], ss_fg_bg_common[1]}; // here BG==FG
ShowDoubleFloatArrays.showArrays(
dbg_img,
tilesX,
dbg_img[0].length/tilesX,
true,
ref_scene.getImageName()+"-fg-bg-disparity_strength-LMA-GND-FLAT",
dbg_titles);
}
scenes[ref_index].setSmoothGround( // was in the end
clt_parameters, // CLTParameters clt_parameters,
smooth_ground, // double [] smooth_ground,
debugLevel); // int debugLevel)
if (terrain_mode) {
// ds_fg_bg_common[0] = terrain_disparity.clone();
// ds_fg_bg_common[1] = terrain_disparity.clone();
for (int i = 0; i < smooth_ground.length; i++) { // ~smooth terrain surface only: nothing in FG, surface - in BG
ds_fg_bg_common[1][i] = terrain_disparity[i];
ss_fg_bg_common[1][i] = Math.max(ss_fg_bg_common[1][i],ss_fg_bg_common[0][i]);
ss_fg_bg_common[1][i] = Math.max(ss_fg_bg_common[1][i],small_strength);
ds_fg_bg_common[0][i] = Double.NaN;
ss_fg_bg_common[0][i] = 0.0;
}
}
}
for (int nscan = 0; nscan < num_scans; nscan++) {
double [][] ds_fg_bg = new double[][] {ds_fg_bg_common[0].clone(), ds_fg_bg_common[1].clone()};
double [][] ss_fg_bg = new double[][] {ss_fg_bg_common[0].clone(), ss_fg_bg_common[1].clone()};
double lim_disparity = lim_disparity_noct;
boolean ct_mode = false;
if (ct_scans != null) {
if (nscan < (num_scans- 1)) { // last pass in ct mode - as if no CT, no limit
ct_mode = true;
lim_disparity = ct_min+ct_step*nscan;
}
String sstat = String.format("processing CT scan %d, disparity=%.3f",nscan,lim_disparity);
if (updateStatus) IJ.showStatus(sstat);
System.out.println(sstat);
}
boolean [][] ct_section_fgbg = new boolean[2][ ds_fg_bg[0].length]; // only FG!
for (int i = 0; i < ds_fg_bg[0].length; i++) {
if (ds_fg_bg[0][i] > lim_disparity) {
ds_fg_bg[0][i] = lim_disparity;
ct_section_fgbg[0][i] = true;
}
if (ds_fg_bg[1][i] > lim_disparity) {
ds_fg_bg[1][i] = lim_disparity;
ct_section_fgbg[1][i] = true;
}
}
double [][] fg_bg_preexpand = null;
if (ct_mode && (ct_expand > 0)) {
if (show_bs_debug) {
fg_bg_preexpand = new double[][] {ds_fg_bg[0].clone(),ds_fg_bg[0].clone()};
}
TileNeibs tn = new TileNeibs(tilesX,tilesY);
int nexp = expand_bg? 2:1; // no need to expand bg
for (int n = 0; n < nexp; n++) {
tn.growSelection(
ct_expand, // int grow, // grow tile selection by 1 over non-background tiles 1: 4 directions, 2 - 8 directions, 3 - 8 by 1, 4 by 1 more
ct_section_fgbg[n], //final boolean [] tiles,
null); // final boolean [] prohibit)
for (int i = 0; i < ct_section_fgbg[n].length; i++) if (ct_section_fgbg[n][i]) {
ds_fg_bg[n][i] = lim_disparity;
}
}
if (show_bs_debug) {
String [] dbg_titles = {"FG","BG","FG_preexp", "BG_preexp", "FG_full", "BG_full", "GND", "FS", "BS"};
double [][] dbg_img = {
ds_fg_bg[0], ds_fg_bg[1],
fg_bg_preexpand[0],fg_bg_preexpand[1],
ds_fg_bg_common[0], ds_fg_bg_common[1],
smooth_ground,
ss_fg_bg_common[0], ss_fg_bg_common[1]}; // here BG==FG
ShowDoubleFloatArrays.showArrays(
dbg_img,
tilesX,
dbg_img[0].length/tilesX,
true,
ref_scene.getImageName()+"-fg-bg-expansion",
dbg_titles);
}
}
/*
if ((smooth_ground != null) && !ct_mode) { // no sense to use with CT? or compare with the common only?
if (has_sfm && gsmth_sfm_deviate) { if (has_sfm && gsmth_sfm_deviate) {
mixed_flat = true; mixed_flat = true;
// Change! // Change!
// Use FG for FG, and ground plane as BG? // Use FG for FG, and ground plane as BG?
TileNeibs tn = new TileNeibs(tilesX, smooth_ground.length/tilesX); TileNeibs tn = new TileNeibs(tilesX, smooth_ground.length/tilesX);
for (int ntile = 0; ntile < smooth_ground.length; ntile++) { for (int ntile = 0; ntile < smooth_ground.length; ntile++) {
double disp = (ss_fg_bg[1][ntile] > ss_fg_bg[0][ntile]) ? ds_fg_bg[1][ntile] : ds_fg_bg[1][ntile]; double disp = (ss_fg_bg[1][ntile] > ss_fg_bg[0][ntile]) ? ds_fg_bg[1][ntile] : ds_fg_bg[1][ntile]; // strongest
if (disp > lim_disparity) {
disp = lim_disparity;
}
double str = Math.max(ss_fg_bg[1][ntile], ss_fg_bg[0][ntile]); double str = Math.max(ss_fg_bg[1][ntile], ss_fg_bg[0][ntile]);
boolean strong = false; boolean strong = false;
if (disp > smooth_ground[ntile]) { if (disp > smooth_ground[ntile]) {
...@@ -2723,13 +3041,21 @@ public class TexturedModel { ...@@ -2723,13 +3041,21 @@ public class TexturedModel {
} }
} }
if (!strong) { // either was weak or broke check_neibs if (!strong) { // either was weak or broke check_neibs
// if (ct_mode) {
// ds_fg_bg[0][ntile] = lim_disparity;
// ss_fg_bg[0][ntile] = str;
// ds_fg_bg[1][ntile] = smooth_ground[ntile];
// ss_fg_bg[1][ntile] = small_strength;
// } else {
ds_fg_bg[0][ntile] = Double.NaN; ds_fg_bg[0][ntile] = Double.NaN;
ds_fg_bg[1][ntile] = smooth_ground[ntile]; ds_fg_bg[1][ntile] = smooth_ground[ntile];
ss_fg_bg[0][ntile] = 0.0; ss_fg_bg[0][ntile] = 0.0;
ss_fg_bg[1][ntile] = str; ss_fg_bg[1][ntile] = str;
// }
} }
} }
} else { // smooth surface only: nothing in FG, surface - in BG } else { // smooth surface only: nothing in FG, surface - in BG
if (!ct_mode) { // no sense to use smooth_ground in CT scan mode
for (int i = 0; i < smooth_ground.length; i++) { for (int i = 0; i < smooth_ground.length; i++) {
ds_fg_bg[1][i] = smooth_ground[i]; ds_fg_bg[1][i] = smooth_ground[i];
ss_fg_bg[1][i] = Math.max(ss_fg_bg[1][i],ss_fg_bg[0][i]); ss_fg_bg[1][i] = Math.max(ss_fg_bg[1][i],ss_fg_bg[0][i]);
...@@ -2737,25 +3063,36 @@ public class TexturedModel { ...@@ -2737,25 +3063,36 @@ public class TexturedModel {
ds_fg_bg[0][i] = Double.NaN; ds_fg_bg[0][i] = Double.NaN;
ss_fg_bg[0][i] = 0.0; ss_fg_bg[0][i] = 0.0;
} }
/*
for (int i = 0; i < smooth_ground.length; i++) {
ds_fg_bg[1][i] = Double.NaN;
ds_fg_bg[0][i] = smooth_ground[i];
ss_fg_bg[1][i] = 0.0;
ss_fg_bg[0][i] = Math.max(ss_fg_bg[0][i], small_strength); //???
} }
*/
} }
// Save matching DSI data to *-INTER-INTRA-LMA.tiff
scenes[ref_index].setSmoothGround( if (show_bs_debug && (debugLevel>1)) {
clt_parameters, // CLTParameters clt_parameters, String [] dbg_titles = {"FGC","BGC","FG", "BG", "GND", "FS", "BS"};
smooth_ground, // double [] smooth_ground, double [][] dbg_img = {ds_fg_bg_common[0], ds_fg_bg_common[1], ds_fg_bg[0], ds_fg_bg[1], smooth_ground, ss_fg_bg_common[0], ss_fg_bg_common[1]}; // here BG==FG
debugLevel); // int debugLevel) ShowDoubleFloatArrays.showArrays(
if (debugLevel > -3) { dbg_img,
System.out.println("output3d(): Using smooth ground for 3D/maps generation."); tilesX,
dbg_img[0].length/tilesX,
true,
ref_scene.getImageName()+"-fgc-bgc-fg-bg-disparity_strength-LMA-GND",
dbg_titles);
} }
} }
*/
if (show_bs_debug) {
String [] dbg_titles = {"FGC","BGC","FG", "BG", "GND", "FS", "BS"};
double [][] dbg_img = {ds_fg_bg_common[0], ds_fg_bg_common[1], ds_fg_bg[0], ds_fg_bg[1], smooth_ground, ss_fg_bg_common[0], ss_fg_bg_common[1]}; // here BG==FG
ShowDoubleFloatArrays.showArrays(
dbg_img,
tilesX,
dbg_img[0].length/tilesX,
true,
ref_scene.getImageName()+"-fgc-bgc-fg-bg-disparity_strength-LMA-GND-final",
dbg_titles);
}
final ArrayList <TileCluster> cluster_list = new ArrayList<TileCluster>(); final ArrayList <TileCluster> cluster_list = new ArrayList<TileCluster>();
double [][] disparity_layers =buildSkyCluster( double [][] disparity_layers =buildSkyCluster(
...@@ -2775,17 +3112,18 @@ public class TexturedModel { ...@@ -2775,17 +3112,18 @@ public class TexturedModel {
tilesX, // final int tilesX, tilesX, // final int tilesX,
debugLevel); // final int debugLevel) debugLevel); // final int debugLevel)
if (show_bs_debug) { if (show_bs_debug && (debugLevel>1)) {
String [] dbg_titles = {"FG","BG", "SFG", "SBG","BS"}; String [] dbg_titles = {"FG","FG0","BG","BG0", "SFG", "SBG","BS"};
double [][] dbg_img = new double [dbg_titles.length][]; double [] dbg_blue = new double [sky_tiles.length];
dbg_img[0] = disparity_layers[0];
dbg_img[1] = disparity_layers[1];
dbg_img[2] = ss_fg_bg[0];
dbg_img[3] = ss_fg_bg[1];
dbg_img[4] = new double [sky_tiles.length];
for (int i = 0; i < sky_tiles.length; i++) { for (int i = 0; i < sky_tiles.length; i++) {
dbg_img[4][i] = sky_tiles[i]? 20: 0; dbg_blue[i] = sky_tiles[i]? 20: 0;
} }
double [][] dbg_img = new double [dbg_titles.length][];
dbg_img = new double [][] {
disparity_layers[0], ds_fg_bg[0], disparity_layers[1],ds_fg_bg[1],
ss_fg_bg[0], ss_fg_bg[1],
dbg_blue};
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
dbg_img, dbg_img,
tilesX, tilesX,
...@@ -2795,12 +3133,16 @@ public class TexturedModel { ...@@ -2795,12 +3133,16 @@ public class TexturedModel {
dbg_titles); dbg_titles);
} }
if (ct_disparity != null) {
ct_disparity[nscan] = disparity_layers[0].clone();
}
// double [][] ct_disparity = ((ct_scans!=null) && show_bs_debug)? new double [num_scans][]:null;
TileCluster [] tileClusters =
clusterizeFgBg( // wrong result type, not decided tileClusters = clusterizeFgBg( // wrong result type, not decided
cluster_list, // final ArrayList <TileCluster> cluster_list, cluster_list, // final ArrayList <TileCluster> cluster_list,
tilesX, // final int tilesX, tilesX, // final int tilesX,
disparity_layers, // ds_fg_bg, // final double [][] disparities, // may have more layers disparity_layers, // ds_fg_bg, // final double [][] disparities, // may have more layers
...@@ -2836,9 +3178,9 @@ public class TexturedModel { ...@@ -2836,9 +3178,9 @@ public class TexturedModel {
scenes_sel[i] = true; scenes_sel[i] = true;
} }
double [][][][] lin_text0 = render_hdr ? new double [1][][][] : null; lin_text0 = render_hdr ? new double [1][][][] : null;
double[][][] faded_textures = getInterCombinedTextures( // return ImagePlus[] matching tileClusters[], with alpha faded_textures = getInterCombinedTextures( // return ImagePlus[] matching tileClusters[], with alpha
clt_parameters, // final CLTParameters clt_parameters, clt_parameters, // final CLTParameters clt_parameters,
colorProcParameters, // ColorProcParameters colorProcParameters, colorProcParameters, // ColorProcParameters colorProcParameters,
parameter_scene, // final QuadCLT parameter_scene, // to use for rendering parameters in multi-series sequences parameter_scene, // final QuadCLT parameter_scene, // to use for rendering parameters in multi-series sequences
...@@ -2851,7 +3193,45 @@ public class TexturedModel { ...@@ -2851,7 +3193,45 @@ public class TexturedModel {
max_disparity_lim, // final double max_disparity_lim, // 100.0; // do not allow stray disparities above this max_disparity_lim, // final double max_disparity_lim, // 100.0; // do not allow stray disparities above this
min_trim_disparity, // final double min_trim_disparity, // 2.0; // do not try to trim texture outlines with lower disparities min_trim_disparity, // final double min_trim_disparity, // 2.0; // do not try to trim texture outlines with lower disparities
lin_text0, // final double [][][][] lin_textures, // null or [1][][][] to return non-normalized textures lin_text0, // final double [][][][] lin_textures, // null or [1][][][] to return non-normalized textures
(ct_scans != null), // ct_mode, // final boolean ct_mode,
terrain_mode, // final boolean terrain_mode, Just for file name
debugLevel); // final int debug_level) debugLevel); // final int debug_level)
if (ct_scans != null) {
// ct_scans[nscan] = new double [][] {faded_textures[0][0].clone(),faded_textures[1][0].clone()}; // both slices, channel 0
ct_scans[nscan] = new double [faded_textures.length][];
for (int i = 0; i < ct_scans[nscan].length; i++) {
ct_scans[nscan][i] = faded_textures[i][0].clone(); // channel 0 from each slice
}
if (updateStatus) IJ.showProgress((nscan+1.0)/num_scans);
}
}
if (ct_scans != null) {
if (ct_disparity != null) {
String [] titles = new String[ct_disparity.length];
for (int nscan = 0; nscan < titles.length-1; nscan++) {
titles[nscan] = String.format("D=%.3f", ct_min+ct_step*nscan);
}
titles[titles.length-1]="full";
/*
ShowDoubleFloatArrays.showArrays(
ct_disparity,
tilesX,
ct_disparity[0].length/tilesX,
true,
ref_scene.getImageName()+"-CT_scan_disparities",
titles);
*/
double ct_max = ct_min+ct_step* (ct_scans.length-1);
String suffix = String.format("-CT_SCAN_%.3f_%.3f_%.3f",ct_min,ct_max,ct_step);
scenes[ref_index].saveDoubleArrayInModelDirectory(
suffix, // String suffix,
titles, // String [] labels, // or null
ct_disparity, // double [][] data,
tilesX, // int width, // int tilesX,
tilesY); // int height, // int tilesY,
}
return true;
}
double [][][] lin_textures = (lin_text0 != null) ? lin_text0[0] : null; double [][][] lin_textures = (lin_text0 != null) ? lin_text0[0] : null;
if (no_alpha && (lin_textures!= null)){ if (no_alpha && (lin_textures!= null)){
for (int nslice = 0; nslice < lin_textures.length; nslice++) { for (int nslice = 0; nslice < lin_textures.length; nslice++) {
...@@ -2938,7 +3318,7 @@ public class TexturedModel { ...@@ -2938,7 +3318,7 @@ public class TexturedModel {
// do nothing, just keep // do nothing, just keep
} }
} }
if ((clt_parameters.output_x3d || clt_parameters.output_glTF) && (x3d_dir != null)) { if ((clt_parameters.output_x3d || clt_parameters.output_glTF || render_hdr) && (x3d_dir != null)) {
tri_meshes = new ArrayList<TriMesh>(); tri_meshes = new ArrayList<TriMesh>();
} }
...@@ -3163,9 +3543,37 @@ public class TexturedModel { ...@@ -3163,9 +3543,37 @@ public class TexturedModel {
} }
} }
if ((hdr_whs[0]<0) || (hdr_whs[1]<0)) { if ((hdr_whs[0]<0) || (hdr_whs[1]<0)) {
System.out.println("**** BUG: hdr_whs[0]="+hdr_whs[0]+", hdr_whs[1]="+hdr_whs[1]); System.out.println("**** BUG: hdr_whs[0]="+hdr_whs[0]+", hdr_whs[1]="+hdr_whs[1]);
} else { } else {
if (hdr_render_slave && (hdr_render_size!=null) && (hdr_render_size[0]!=null) && (hdr_render_size[0]!=null)) {
for (int i = 0; i < hdr_whs.length; i++) {
hdr_whs[i] = (int) Math.round(hdr_render_size[0][i]);
}
for (int i = 0; i < hdr_x0y0.length; i++) {
hdr_x0y0[i] =hdr_render_size[1][i];
}
scaled_pixel_size = pix_size * hdr_whs[2];
System.out.println("Using pre-defined rendering parameters:");
if (debugLevel > -2) {
System.out.println("Updated parameters for rendering:BOTTOM left corner=["+hdr_x0y0[0]+"m, "+hdr_x0y0[1]+"m]");
System.out.println(" : width="+hdr_whs[0]+"pix, height="+hdr_whs[1]+"pix, scale level="+hdr_whs[2]);
System.out.println(" : pixel size: ="+(1000*scaled_pixel_size)+"mm");
}
}
if (hdr_render_size!=null) { // set/update rendering size
hdr_render_size[0] = new double [hdr_whs.length];
for (int i = 0; i < hdr_whs.length; i++) {
hdr_render_size[0][i] = hdr_whs[i];
}
hdr_render_size[1] = hdr_x0y0.clone();
}
Render3D render3D = new Render3D ( Render3D render3D = new Render3D (
//x3d_dir, // String x3d_dir, //x3d_dir, // String x3d_dir,
//ref_scene.correctionsParameters.getModelName(ref_scene.getImageName()), // String model_name, //ref_scene.correctionsParameters.getModelName(ref_scene.getImageName()), // String model_name,
...@@ -3197,7 +3605,7 @@ public class TexturedModel { ...@@ -3197,7 +3605,7 @@ public class TexturedModel {
debugLevel); //int debugLevel) debugLevel); //int debugLevel)
} }
// String model_name = ref_scene.correctionsParameters.getModelName(ref_scene.getImageName()); // String model_name = ref_scene.correctionsParameters.getModelName(ref_scene.getImageName());
String suffix ="-RECT"; String suffix =(terrain_mode?"-TERR":"")+"-RECT";
suffix +="-PIX"+pix_size * hdr_whs[2]; suffix +="-PIX"+pix_size * hdr_whs[2];
suffix += bicubic ? "-BC":"-BL"; suffix += bicubic ? "-BC":"-BL";
if (gsmth_enable) { if (gsmth_enable) {
...@@ -7430,6 +7838,8 @@ public class TexturedModel { ...@@ -7430,6 +7838,8 @@ public class TexturedModel {
final double max_disparity_lim, final double max_disparity_lim,
final double min_trim_disparity, final double min_trim_disparity,
final double [][][][] lin_textures, // null or [1][][][] to return non-normalized textures final double [][][][] lin_textures, // null or [1][][][] to return non-normalized textures
final boolean ct_mode,
final boolean terrain_mode,
final int debugLevel) final int debugLevel)
{ {
// TODO: ***** scenes with high motion blur also have high ERS to be corrected ! ***** // TODO: ***** scenes with high motion blur also have high ERS to be corrected ! *****
...@@ -7739,7 +8149,7 @@ public class TexturedModel { ...@@ -7739,7 +8149,7 @@ public class TexturedModel {
min_trim_disparity, // final double min_trim_disparity, // do not try to trim texture outlines with lower disparities min_trim_disparity, // final double min_trim_disparity, // do not try to trim texture outlines with lower disparities
tp_tasks_ref, // final TpTask[][][] tp_tasks_ref, // reference tasks for each slice to get offsets tp_tasks_ref, // final TpTask[][][] tp_tasks_ref, // reference tasks for each slice to get offsets
ref_scene.getImageName()); // null); // ref_scene.getImageName()); // final String dbg_prefix); ref_scene.getImageName()); // null); // ref_scene.getImageName()); // final String dbg_prefix);
if (save_interm_textures) { if (save_interm_textures && !ct_mode) {
double [][] dbg_textures = new double [faded_textures.length * faded_textures[0].length][faded_textures[0][0].length]; double [][] dbg_textures = new double [faded_textures.length * faded_textures[0].length][faded_textures[0][0].length];
String [] dbg_titles = new String[dbg_textures.length]; String [] dbg_titles = new String[dbg_textures.length];
String [] dbg_subtitles = new String [faded_textures[0].length]; String [] dbg_subtitles = new String [faded_textures[0].length];
...@@ -7751,7 +8161,7 @@ public class TexturedModel { ...@@ -7751,7 +8161,7 @@ public class TexturedModel {
dbg_titles[i] = dbg_subtitles[i % dbg_subtitles.length] + "-" + (i / dbg_subtitles.length); dbg_titles[i] = dbg_subtitles[i % dbg_subtitles.length] + "-" + (i / dbg_subtitles.length);
} }
String suffix = "-combined_textures-prenorm-pre_UM"; String suffix = (terrain_mode?"-TERR":"")+"-combined_textures-prenorm-pre_UM";
ref_scene.saveDoubleArrayInModelDirectory( ref_scene.saveDoubleArrayInModelDirectory(
suffix, // String suffix, suffix, // String suffix,
null, // String [] labels, // or null null, // String [] labels, // or null
...@@ -7783,6 +8193,9 @@ public class TexturedModel { ...@@ -7783,6 +8193,9 @@ public class TexturedModel {
0.03, // final double max_rchange, // = 0.01 - does not need to be accurate 0.03, // final double max_rchange, // = 0.01 - does not need to be accurate
THREADS_MAX); // final int threadsMax) // maximal number of threads to launch THREADS_MAX); // final int threadsMax) // maximal number of threads to launch
} }
if (ct_mode) {
return faded_textures; // use faded_textures[0][0];
}
if (save_interm_textures) { if (save_interm_textures) {
double [][] dbg_textures = new double [faded_textures.length * faded_textures[0].length][faded_textures[0][0].length]; double [][] dbg_textures = new double [faded_textures.length * faded_textures[0].length][faded_textures[0][0].length];
...@@ -7797,7 +8210,7 @@ public class TexturedModel { ...@@ -7797,7 +8210,7 @@ public class TexturedModel {
dbg_titles[i] = dbg_subtitles[i % dbg_subtitles.length] + "-" + (i / dbg_subtitles.length); dbg_titles[i] = dbg_subtitles[i % dbg_subtitles.length] + "-" + (i / dbg_subtitles.length);
} }
String suffix = "-combined_textures-filled-NaNs"; String suffix = (terrain_mode?"-TERR":"")+"-combined_textures-filled-NaNs";
if (!batch_run && (debugLevel > -1)) { if (!batch_run && (debugLevel > -1)) {
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
dbg_textures, dbg_textures,
...@@ -7829,6 +8242,7 @@ public class TexturedModel { ...@@ -7829,6 +8242,7 @@ public class TexturedModel {
} }
} }
} }
// Optionally apply UM (before auto/manual range) // Optionally apply UM (before auto/manual range)
final boolean um_ignore_alpha = true; final boolean um_ignore_alpha = true;
final boolean hist_ignore_alpha = true; final boolean hist_ignore_alpha = true;
...@@ -7853,7 +8267,7 @@ public class TexturedModel { ...@@ -7853,7 +8267,7 @@ public class TexturedModel {
dbg_titles[i] = dbg_subtitles[i % dbg_subtitles.length] + "-" + (i / dbg_subtitles.length); dbg_titles[i] = dbg_subtitles[i % dbg_subtitles.length] + "-" + (i / dbg_subtitles.length);
} }
String suffix = "-combined_textures-prenorm"; String suffix = (terrain_mode?"-TERR":"")+"-combined_textures-prenorm";
if (save_interm_textures) { if (save_interm_textures) {
if (!batch_run && (debugLevel > -1)) { if (!batch_run && (debugLevel > -1)) {
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
...@@ -7872,7 +8286,7 @@ public class TexturedModel { ...@@ -7872,7 +8286,7 @@ public class TexturedModel {
tilesX * transform_size, // int width, // int tilesX, tilesX * transform_size, // int width, // int tilesX,
tilesY * transform_size); // int height, // int tilesY, tilesY * transform_size); // int height, // int tilesY,
if (dbg_weights != null) { if (dbg_weights != null) {
suffix = "-texture_weights-prenorm"; suffix = (terrain_mode?"-TERR":"")+"-texture_weights-prenorm";
if (!batch_run && (debugLevel > -1)) { if (!batch_run && (debugLevel > -1)) {
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
dbg_weights, dbg_weights,
...@@ -7892,7 +8306,7 @@ public class TexturedModel { ...@@ -7892,7 +8306,7 @@ public class TexturedModel {
} }
// here is the best full-range texture. For UAS just use slice 0 // here is the best full-range texture. For UAS just use slice 0
if (save_um_texture0) { if (save_um_texture0) {
suffix = "-texture"; suffix = (terrain_mode?"-TERR":"")+"-texture";
if (tex_um) { if (tex_um) {
suffix+= "-UM"+tex_um_sigma+"_"+tex_um_weight; suffix+= "-UM"+tex_um_sigma+"_"+tex_um_weight;
} }
...@@ -7996,7 +8410,7 @@ public class TexturedModel { ...@@ -7996,7 +8410,7 @@ public class TexturedModel {
minmax, // double [] minmax, // null for auto minmax, // double [] minmax, // null for auto
null, // QuadCLT scene, null, // QuadCLT scene,
tex_palette, // int tex_palette, tex_palette, // int tex_palette,
"", // +tex_palette, // String suffix, (terrain_mode?"-TERR":"")+"", // +tex_palette, // String suffix,
debugLevel); // int debugLevel) debugLevel); // int debugLevel)
tex_palette = 1; // regular color tex_palette = 1; // regular color
ref_scene.writeLwirPreview( ref_scene.writeLwirPreview(
...@@ -8005,7 +8419,7 @@ public class TexturedModel { ...@@ -8005,7 +8419,7 @@ public class TexturedModel {
minmax, // double [] minmax, // null for auto minmax, // double [] minmax, // null for auto
null, // QuadCLT scene, null, // QuadCLT scene,
tex_palette, // int tex_palette, tex_palette, // int tex_palette,
"-black_hot", // +tex_palette, // String suffix, (terrain_mode?"-TERR":"")+"-black_hot", // +tex_palette, // String suffix,
debugLevel); // int debugLevel) debugLevel); // int debugLevel)
tex_palette = 2; // regular color tex_palette = 2; // regular color
ref_scene.writeLwirPreview( ref_scene.writeLwirPreview(
...@@ -8014,12 +8428,12 @@ public class TexturedModel { ...@@ -8014,12 +8428,12 @@ public class TexturedModel {
minmax, // double [] minmax, // null for auto minmax, // double [] minmax, // null for auto
null, // QuadCLT scene, null, // QuadCLT scene,
tex_palette, // int tex_palette, tex_palette, // int tex_palette,
"-color", // +tex_palette, // String suffix, (terrain_mode?"-TERR":"")+"-color", // +tex_palette, // String suffix,
debugLevel); // int debugLevel) debugLevel); // int debugLevel)
} }
if (save_interm_textures) { if (save_interm_textures) {
String suffix = "-combined_textures"; String suffix = (terrain_mode?"-TERR":"")+"-combined_textures";
if (!batch_run && (debugLevel > -1)) { if (!batch_run && (debugLevel > -1)) {
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
dbg_textures, dbg_textures,
......
...@@ -78,12 +78,19 @@ public class Render3D { ...@@ -78,12 +78,19 @@ public class Render3D {
ground_normal = ground_origin.subtract( ground_normal = ground_origin.subtract(
ground_x.scalarMultiply(ground_origin.dotProduct(ground_x))).subtract( ground_x.scalarMultiply(ground_origin.dotProduct(ground_x))).subtract(
ground_y.scalarMultiply(ground_origin.dotProduct(ground_y))); ground_y.scalarMultiply(ground_origin.dotProduct(ground_y)));
ground_normal_unit = ground_normal.normalize(); // unitary vector normal and away from the ground plane Vector3D gnu;
try {
gnu = ground_normal.normalize(); // unitary vector normal and away from the ground plane
} catch (Exception e) {
System.out.println("Zero above ground");
gnu = ground_x.crossProduct(ground_y).normalize(); // sets to (0, 0, 1)
}
ground_normal_unit = gnu; // only used for center projection where ground_origin != 0;
above_ground = ground_normal.getNorm(); above_ground = ground_normal.getNorm();
xy_offs = new double[] {ground_x.dotProduct(ground_origin), ground_y.dotProduct(ground_origin)}; xy_offs = new double[] {ground_x.dotProduct(ground_origin), ground_y.dotProduct(ground_origin)};
} }
public double [] projectToPlaneLinear(Vector3D v3) { // get ground plane pixel coordinate from camera x,y,z public double [] projectToPlaneLinear(Vector3D v3) { // get ground plane pixel coordinate from camera x,y,z - not used
double z = ground_normal_unit.dotProduct(v3); double z = ground_normal_unit.dotProduct(v3);
Vector3D in_plane = v3.scalarMultiply(above_ground/z); Vector3D in_plane = v3.scalarMultiply(above_ground/z);
double [] xy = new double[3]; double [] xy = new double[3];
...@@ -93,7 +100,7 @@ public class Render3D { ...@@ -93,7 +100,7 @@ public class Render3D {
return xy; return xy;
} }
public double [] projectToPlanePixels(Vector3D v3) { // get ground plane pixel coordinate from camera x,y,z public double [] projectToPlanePixels(Vector3D v3) { // get ground plane pixel coordinate from camera x,y,z used in center proj
double z = ground_normal_unit.dotProduct(v3); double z = ground_normal_unit.dotProduct(v3);
Vector3D in_plane = v3.scalarMultiply(above_ground/z); Vector3D in_plane = v3.scalarMultiply(above_ground/z);
double [] xy = new double[3]; double [] xy = new double[3];
......
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