Commit cb61d659 authored by Andrey Filippov's avatar Andrey Filippov

Putting all together, adding generation of thumbnails, KML, etc.

parent 9c02927a
......@@ -226,16 +226,19 @@ public class BiQuadParameters {
public boolean ml_generate = false; // Generate ML data automatically when running ground truth
public boolean ml_poles = true; // Generate ML data from the DSI that includes extracted poles
public boolean ml_copyJP4 = true; // Copy source jp4 files when running "Ground truth" command
public int ml_hwidth = 2; // Half-width of the ML tiles to export (0-> 1x1, 1->3x3, 2 -> 5x5)
public double ml_disparity_sweep = 2.0; // Disparity sweep around ground truth, each side
public int ml_sweep_steps = 5; // Number of disparity sweep steps
public int ml_hwidth = 4; // Half-width of the ML tiles to export (0-> 1x1, 1->3x3, 2 -> 5x5)
public double ml_disparity_sweep = 1.0; // Disparity sweep around ground truth, each side
public int ml_sweep_steps = 21; // Number of disparity sweep steps
public boolean ml_keep_aux = true; // include auxiliary camera data in the ML output
public boolean ml_keep_inter = true; // include inter-camera correlation data in the ML output
public boolean ml_keep_aux = false; // true; // include auxiliary camera data in the ML output
public boolean ml_keep_inter = false; // true; // include inter-camera correlation data in the ML output
public boolean ml_keep_hor_vert = true; // include combined horizontal and vertical pairs data in the ML output
public boolean ml_keep_tbrl = true; // include individual top, bottom, right, left pairs
public boolean ml_keep_debug= true; // include debug layer(s) data in the ML output
public boolean ml_keep_tbrl = false; // true; // include individual top, bottom, right, left pairs
public boolean ml_keep_debug= false; // true; // include debug layer(s) data in the ML output
public boolean ml_8bit= true; // output in 8-bit format (default - 32-bit TIFF
public double ml_limit_extrim = 0.00001; // ignore lowest and highest values when converting to 8 bpp
public boolean ml_show_ml = true; // show each generated MLoutput file
......@@ -311,7 +314,7 @@ public class BiQuadParameters {
gd.addNumericField("Minimal RMS improvement after short cycle to exit", this.rig_adjust_short_threshold, 3,6,"",
"Short cycle iteration finish after relative RMS improvement is less than this of maximal number of steps is exceeded");
gd.addCheckbox ("Adjust orientation (azimuth, tilt, roll) of the auxiliary camera", this.rig_adjust_orientation,"3 angles, most basic adjustment");
gd.addCheckbox ("Adjust orientation relative zoom of the auxiliary camera", this.rig_adjust_zoom,"Not likely to change, may be frozen");
gd.addCheckbox ("Adjust relative zoom of the auxiliary camera", this.rig_adjust_zoom,"Not likely to change, may be frozen");
gd.addCheckbox ("Adjust position of the aux camera in the main camera pricipal plane", this.rig_adjust_angle,"0 - exactly to the right, positive - higher than main");
gd.addCheckbox ("Adjust aux camera distance from the main", this.rig_adjust_distance,"Normally not practical, rely on direct measurement");
gd.addCheckbox ("Adjust aux camera distance from the main principal plane", this.rig_adjust_forward,"Not implemented, assumed zero");
......@@ -600,6 +603,13 @@ public class BiQuadParameters {
gd.addTab("ML","Parameters related to the ML files generation for the dual-quad camera rig");
gd.addCheckbox ("Generate ML data automatically", this.ml_generate,
"Generate ML data automatically when running ground truth (may run separately from a command button)");
gd.addCheckbox ("Generate ML data from the DSI that includes extracted poles", this.ml_poles,
"If unchecked - use DSI w/o poles data");
gd.addCheckbox ("Copy JP4 source images when generating ML data", this.ml_copyJP4,
"Possible to run by a command button");
gd.addNumericField("Half-width of the ML tiles to export (0-> 1x1, 1->3x3, 2 -> 5x5)", this.ml_hwidth, 0,3,"",
"Amount of data to export to the ML system");
gd.addNumericField("Disparity sweep around ground truth, each side", this.ml_disparity_sweep, 3,6,"",
......@@ -802,6 +812,10 @@ public class BiQuadParameters {
this.rf_min_disp= gd.getNextNumber();
this.rf_remove_unselected= gd.getNextBoolean();
this.ml_generate= gd.getNextBoolean();
this.ml_poles= gd.getNextBoolean();
this.ml_copyJP4= gd.getNextBoolean();
this.ml_hwidth= (int) gd.getNextNumber();
this.ml_disparity_sweep= gd.getNextNumber();
this.ml_sweep_steps= (int) gd.getNextNumber();
......@@ -995,6 +1009,9 @@ public class BiQuadParameters {
properties.setProperty(prefix+"rf_min_disp", this.rf_min_disp+"");
properties.setProperty(prefix+"rf_remove_unselected", this.rf_remove_unselected+"");
properties.setProperty(prefix+"ml_generate", this.ml_generate+"");
properties.setProperty(prefix+"ml_poles", this.ml_poles+"");
properties.setProperty(prefix+"ml_copyJP4", this.ml_copyJP4+"");
properties.setProperty(prefix+"ml_hwidth", this.ml_hwidth+"");
properties.setProperty(prefix+"ml_disparity_sweep", this.ml_disparity_sweep+"");
properties.setProperty(prefix+"ml_sweep_steps", this.ml_sweep_steps+"");
......@@ -1185,6 +1202,9 @@ public class BiQuadParameters {
if (properties.getProperty(prefix+"rf_min_disp")!=null) this.rf_min_disp=Double.parseDouble(properties.getProperty(prefix+"rf_min_disp"));
if (properties.getProperty(prefix+"rf_remove_unselected")!=null) this.rf_remove_unselected=Boolean.parseBoolean(properties.getProperty(prefix+"rf_remove_unselected"));
if (properties.getProperty(prefix+"ml_generate")!=null) this.ml_generate=Boolean.parseBoolean(properties.getProperty(prefix+"ml_generate"));
if (properties.getProperty(prefix+"ml_poles")!=null) this.ml_poles=Boolean.parseBoolean(properties.getProperty(prefix+"ml_poles"));
if (properties.getProperty(prefix+"ml_copyJP4")!=null) this.ml_copyJP4=Boolean.parseBoolean(properties.getProperty(prefix+"ml_copyJP4"));
if (properties.getProperty(prefix+"ml_hwidth")!=null) this.ml_hwidth=Integer.parseInt(properties.getProperty(prefix+"ml_hwidth"));
if (properties.getProperty(prefix+"ml_disparity_sweep")!=null) this.ml_disparity_sweep=Double.parseDouble(properties.getProperty(prefix+"ml_disparity_sweep"));
if (properties.getProperty(prefix+"ml_sweep_steps")!=null) this.ml_sweep_steps=Integer.parseInt(properties.getProperty(prefix+"ml_sweep_steps"));
......@@ -1376,6 +1396,9 @@ public class BiQuadParameters {
bqp.rf_min_disp= this.rf_min_disp;
bqp.rf_remove_unselected= this.rf_remove_unselected;
bqp.ml_generate= this.ml_generate;
bqp.ml_poles= this.ml_poles;
bqp.ml_copyJP4= this.ml_copyJP4;
bqp.ml_hwidth= this.ml_hwidth;
bqp.ml_disparity_sweep= this.ml_disparity_sweep;
bqp.ml_sweep_steps= this.ml_sweep_steps;
......
......@@ -871,10 +871,10 @@ public class BiScan {
System.out.println("suggestNewScan(): nTile="+nTile+" w="+w);
System.out.println("suggestNewScan(): nTile="+nTile+" w="+w);
}
if (nTile == 66945) {
System.out.println("suggestNewScan(): nTile="+nTile+" w="+w);
System.out.println("suggestNewScan(): nTile="+nTile+" w="+w);
}
// if (nTile == 66945) {
// System.out.println("suggestNewScan(): nTile="+nTile+" w="+w);
// System.out.println("suggestNewScan(): nTile="+nTile+" w="+w);
// }
}
}
......
......@@ -132,9 +132,20 @@ public class EyesisCorrectionParameters {
public String x3dModelVersion="v01";
public String jp4SubDir="jp4";
public String x3dDirectory="";
public String mlDirectory="";
public String mlDirectory="ml";
public int thumb_width = 200;
public int thumb_height = 100;
public double thumb_h_center = 0.5;
public double thumb_v_center = 0.5;
public double thumb_size = 0.75;
public int default_rating = 5;
public CorrectionParameters getAux() {
return aux_camera;
......@@ -228,6 +239,7 @@ public class EyesisCorrectionParameters {
cp.use_x3d_subdirs= this.use_x3d_subdirs;
cp.x3dSubdirPrefix= this.x3dSubdirPrefix;
cp.x3dModelVersion= this.x3dModelVersion;
cp.jp4SubDir= this.jp4SubDir;
cp.clt_batch_apply_man= this.clt_batch_apply_man;
cp.clt_batch_extrinsic= this.clt_batch_extrinsic;
cp.clt_batch_poly= this.clt_batch_poly;
......@@ -364,6 +376,7 @@ public class EyesisCorrectionParameters {
properties.setProperty(prefix+"x3dSubdirPrefix", this.x3dSubdirPrefix+"");
properties.setProperty(prefix+"x3dSubdirSuffix", this.x3dSubdirSuffix+"");
properties.setProperty(prefix+"x3dModelVersion", this.x3dModelVersion);
properties.setProperty(prefix+"jp4SubDir", this.jp4SubDir);
properties.setProperty(prefix+"mlDirectory", this.mlDirectory);
......@@ -376,6 +389,15 @@ public class EyesisCorrectionParameters {
properties.setProperty(prefix+"clt_batch_assign", this.clt_batch_assign+"");
properties.setProperty(prefix+"clt_batch_gen3d", this.clt_batch_gen3d+"");
properties.setProperty(prefix+"clt_batch_dbg1", this.clt_batch_dbg1+"");
properties.setProperty(prefix+"thumb_width", this.thumb_width+"");
properties.setProperty(prefix+"thumb_height", this.thumb_height+"");
properties.setProperty(prefix+"thumb_h_center", this.thumb_h_center+"");
properties.setProperty(prefix+"thumb_v_center", this.thumb_v_center+"");
properties.setProperty(prefix+"thumb_size", this.thumb_size+"");
properties.setProperty(prefix+"default_rating", this.default_rating+"");
if (aux_camera != null) { // always
updateAuxFromMain();
String aux_prefix = prefix + AUX_PREFIX;
......@@ -491,6 +513,7 @@ public class EyesisCorrectionParameters {
if (properties.getProperty(prefix+"x3dSubdirSuffix")!= null) this.x3dSubdirSuffix=properties.getProperty(prefix+"x3dSubdirSuffix");
if (properties.getProperty(prefix+"x3dModelVersion")!= null) this.x3dModelVersion=properties.getProperty(prefix+"x3dModelVersion");
if (properties.getProperty(prefix+"jp4SubDir")!= null) this.jp4SubDir=properties.getProperty(prefix+"jp4SubDir");
if (properties.getProperty(prefix+"mlDirectory")!= null) this.mlDirectory=properties.getProperty(prefix+"mlDirectory");
......@@ -504,6 +527,14 @@ public class EyesisCorrectionParameters {
if (properties.getProperty(prefix+"clt_batch_gen3d")!= null) this.clt_batch_gen3d=Boolean.parseBoolean(properties.getProperty(prefix+"clt_batch_gen3d"));
if (properties.getProperty(prefix+"clt_batch_dbg1")!= null) this.clt_batch_dbg1=Boolean.parseBoolean(properties.getProperty(prefix+"clt_batch_dbg1"));
if (properties.getProperty(prefix+"thumb_width")!=null) this.thumb_width=Integer.parseInt(properties.getProperty(prefix+"thumb_width"));
if (properties.getProperty(prefix+"thumb_height")!=null) this.thumb_height=Integer.parseInt(properties.getProperty(prefix+"thumb_height"));
if (properties.getProperty(prefix+"thumb_h_center")!=null) this.thumb_h_center= Double.parseDouble(properties.getProperty(prefix+"thumb_h_center"));
if (properties.getProperty(prefix+"thumb_v_center")!=null) this.thumb_v_center= Double.parseDouble(properties.getProperty(prefix+"thumb_v_center"));
if (properties.getProperty(prefix+"thumb_size") !=null) this.thumb_size= Double.parseDouble(properties.getProperty(prefix+"thumb_size"));
if (properties.getProperty(prefix+"default_rating") !=null) this.default_rating= Integer.parseInt(properties.getProperty(prefix+"default_rating"));
// copy common parameters to the auxiliary camera ones
updateAuxFromMain();
String aux_prefix = prefix + AUX_PREFIX;
......@@ -591,6 +622,7 @@ public class EyesisCorrectionParameters {
gd.addCheckbox ("Select aberration kernels for CLT directory", false);
gd.addStringField ("x3d model version", this.x3dModelVersion, 20); // 10a
gd.addStringField ("JP4 source image copy model subdirectory", this.jp4SubDir, 20); // 10b
gd.addStringField ("x3d output directory", this.x3dDirectory, 60);
gd.addCheckbox ("Select x3d output directory", false);
gd.addCheckbox ("Use individual subdirectory for each 3d model (timestamp as name)", this.use_x3d_subdirs);
......@@ -599,8 +631,9 @@ public class EyesisCorrectionParameters {
"When using timestamp as a subdirectory, add this prefix");
gd.addStringField ("x3d subdirectory suffix", this.x3dSubdirSuffix, 10,
"When using timestamp as a subdirectory, add this suffix");
gd.addStringField ("ML output directory", this.mlDirectory, 60);
gd.addCheckbox ("Select ML output directory", false);
gd.addStringField ("ML output directory", this.mlDirectory, 60,
"Non-empty directory with no \"/\" separator makes it a subdirectory of the model version directory");
gd.addCheckbox ("Select ML output directory", false,"Erase text field or use \"/\" in it to enable absolute directory path selection");
gd.addStringField("Equirectangular maps directory (may be empty)", this.equirectangularDirectory, 60);
gd.addCheckbox("Select equirectangular maps directory", false);
......@@ -640,6 +673,22 @@ public class EyesisCorrectionParameters {
gd.addCheckbox ("Remove unused sensor data", this.removeUnusedSensorData);
gd.addCheckbox ("Swap top and equator images", this.swapSubchannels01);
gd.addTab("Thumbnails","Thumbnail image generation");
gd.addNumericField("Thumbnail image width", this.thumb_width, 0,4,"pix",
"");
gd.addNumericField("Thumbnail image height", this.thumb_height, 0,4,"pix",
"");
gd.addNumericField("Thumbnail image center horizontally", this.thumb_h_center, 2,6,"",
"0.0 - touch left margin, 1.0 - touch right margin");
gd.addNumericField("Thumbnail image center vertically", this.thumb_v_center, 2,6,"",
"0.0 - touch top margin, 1.0 - touch bottom margin");
gd.addNumericField("Thumbnail relative image size", this.thumb_size, 2,6,"",
"1.0 - maximal to fit frame");
gd.addNumericField("Default scene rating", this.default_rating, 0,2,"",
"Determins scene filtering");
// WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
......@@ -689,13 +738,14 @@ public class EyesisCorrectionParameters {
this.dctKernelDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectDCTKernelDirectory(false, true);
this.cltKernelDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectCLTKernelDirectory(false, true);
this.x3dModelVersion= gd.getNextString(); // 10a
this.jp4SubDir= gd.getNextString(); // 10b
this.x3dDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectX3dDirectory(false, true);
this.use_x3d_subdirs= gd.getNextBoolean();
this.x3dSubdirPrefix= gd.getNextString();
this.x3dSubdirSuffix= gd.getNextString();
this.mlDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectMlDirectory(false, true);
this.mlDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectMlDirectory(null, false, true);
this.equirectangularDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectEquirectangularDirectory(false, false);
this.resultsDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectResultsDirectory(false, true);
......@@ -723,7 +773,14 @@ public class EyesisCorrectionParameters {
this.planeAsJPEG= gd.getNextBoolean();
// this.equirectangularSuffixA= gd.getNextString();
this.removeUnusedSensorData= gd.getNextBoolean();
this.swapSubchannels01= gd.getNextBoolean();
this.swapSubchannels01= gd.getNextBoolean();
this.thumb_width= (int) gd.getNextNumber();
this.thumb_height= (int) gd.getNextNumber();
this.thumb_h_center= gd.getNextNumber();
this.thumb_v_center= gd.getNextNumber();
this.thumb_size= gd.getNextNumber();
this.default_rating= (int) gd.getNextNumber();
return true;
}
......@@ -742,6 +799,7 @@ public class EyesisCorrectionParameters {
gd.addCheckbox ("Select source directory", false); // 3
gd.addStringField ("x3d model version", this.x3dModelVersion, 60); // 10a
gd.addStringField ("jp4 source copy subdirectory", this.jp4SubDir, 60); // 10b
gd.addStringField ("x3d output directory", this.x3dDirectory, 60); // 8
gd.addCheckbox ("Select x3d output (top model) directory", false); // 9
......@@ -753,8 +811,9 @@ public class EyesisCorrectionParameters {
gd.addStringField ("x3d subdirectory prefix", this.x3dSubdirPrefix, 10, // 14a
"When using timestamp as a subdirectory, add this prefix");
gd.addStringField ("ML output directory", this.mlDirectory, 60); // 8d
gd.addCheckbox ("Select ML output directory", false); // 8e
gd.addStringField ("ML output directory", this.mlDirectory, 60,
"Non-empty directory with no \"/\" separator makes it a subdirectory of the model version directory");
gd.addCheckbox ("Select ML output directory", false,"Erase text field or use \"/\" in it to enable absolute directory path selection");
gd.addMessage ("============ Main camera============");
......@@ -774,7 +833,6 @@ public class EyesisCorrectionParameters {
gd.addStringField ("x3d subdirectory suffix", this.x3dSubdirSuffix, 10, // 20a
"When using timestamp as a subdirectory, add this suffix");
gd.addMessage ("============ Auxiliary camera============");
gd.addStringField ("Aux sensor calibration directory", this.aux_camera.sensorDirectory, 60); // 4b
gd.addCheckbox ("Select aux sensor calibration directory", false); // 5b
......@@ -824,12 +882,13 @@ public class EyesisCorrectionParameters {
this.sourceDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectSourceDirectory(false, false); // 3
this.x3dModelVersion= gd.getNextString(); // 10a
this.jp4SubDir= gd.getNextString(); // 10b
this.x3dDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectX3dDirectory(false, true); // 9
this.use_x3d_subdirs= gd.getNextBoolean(); // 10
this.sourcePrefix= gd.getNextString(); // 13
this.sourceSuffix= gd.getNextString(); // 14
this.x3dSubdirPrefix= gd.getNextString(); // 14a
this.mlDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectMlDirectory(false, true); // 8d
this.mlDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectMlDirectory(null,false, true); // 8d
// main camera
this.sensorDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectSensorDirectory(false, false); // 5
......@@ -1410,7 +1469,14 @@ public class EyesisCorrectionParameters {
return dir;
}
public String selectMlDirectory(boolean smart, boolean newAllowed) {
public String selectMlDirectory(String name, boolean smart, boolean newAllowed) {
if ((name != null) && (this.mlDirectory.length()>0) && (!this.mlDirectory.contains(Prefs.getFileSeparator()))) {
// relative to the X3D model version
String x3d_version_dir = selectX3dDirectory(name, this.x3dModelVersion, smart, newAllowed);
if (x3d_version_dir != null) {
return x3d_version_dir + Prefs.getFileSeparator() + this.mlDirectory;
}
}
String dir= CalibrationFileManagement.selectDirectory(
smart,
newAllowed, // save
......
......@@ -2443,7 +2443,7 @@ public class EyesisCorrections {
}
}
if (hasAlphaHighByte){
if (hasAlphaHighByte && (jpegQuality <= 0)){
if (png){
if (debugLevel > 0) System.out.println("Saving RGBA result to "+path+".png");
(new EyesisTiff()).savePNG_ARGB32(
......
......@@ -552,7 +552,7 @@ private Panel panel1,
addButton("CLT infinity corr", panelClt2, color_conf_process);
addButton("CLT ext infinity corr", panelClt2, color_conf_process);
addButton("CLT reset 3D", panelClt2, color_stop);
addButton("CLT Extrinsics", panelClt2, color_process);
addButton("MAIN extrinsics", panelClt2, color_process);
addButton("CLT Poly corr", panelClt2, color_process);
addButton("CLT 3D", panelClt2, color_process);
addButton("CLT planes", panelClt2, color_conf_process);
......@@ -583,19 +583,21 @@ private Panel panel1,
// addButton("CLT 2*4 images", panelClt4, color_conf_process);
// addButton("CLT 2*4 images - 2", panelClt4, color_conf_process);
// addButton("CLT 2*4 images - 3", panelClt4, color_conf_process);
addButton("SHOW extrinsics", panelClt4, color_configure);
addButton("MAIN extrinsics", panelClt4, color_process);
addButton("RIG extrinsics", panelClt4, color_conf_process);
addButton("AUX extrinsics", panelClt4, color_process);
addButton("Rig8 images", panelClt4, color_conf_process);
addButton("Rig infinity calibration", panelClt4, color_conf_process);
addButton("AUX Extrinsics", panelClt4, color_process);
addButton("AUX show fine", panelClt4, color_configure);
// addButton("Rig enhance", panelClt4, color_conf_process);
// addButton("Rig enhance", panelClt4, color_conf_process);
// /"Reset GT"
addButton("Reset GT", panelClt4, color_stop);
addButton("Ground truth 0", panelClt4, color_configure);
// addButton("Ground truth 0", panelClt4, color_configure);
addButton("Ground truth", panelClt4, color_conf_process);
addButton("Show biscan", panelClt4, color_configure);
addButton("Poles GT", panelClt4, color_process);
addButton("ML export", panelClt4, color_conf_process);
addButton("Rig planes", panelClt4, color_conf_process);
addButton("JP4 copy", panelClt4, color_conf_process);
add(panelClt4);
......@@ -4253,9 +4255,9 @@ private Panel panel1,
/// ============================================
} else if (label.equals("CLT 3D") || label.equals("CLT Extrinsics") || label.equals("CLT Poly corr")) {
} else if (label.equals("CLT 3D") || label.equals("MAIN extrinsics") || label.equals("CLT Poly corr")) {
boolean adjust_extrinsics = label.equals("CLT Extrinsics") || label.equals("CLT Poly corr");
boolean adjust_extrinsics = label.equals("MAIN extrinsics") || label.equals("CLT Poly corr");
boolean adjust_poly = label.equals("CLT Poly corr");
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
......@@ -4333,8 +4335,8 @@ private Panel panel1,
}
*/
return;
} else if (label.equals("AUX Extrinsics") || label.equals("AUX Poly corr")) {
boolean adjust_extrinsics = label.equals("AUX Extrinsics") || label.equals("AUX Poly corr");
} else if (label.equals("AUX extrinsics") || label.equals("AUX Poly corr")) {
boolean adjust_extrinsics = label.equals("AUX extrinsics") || label.equals("AUX Poly corr");
boolean adjust_poly = label.equals("AUX Poly corr");
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
......@@ -4567,13 +4569,13 @@ private Panel panel1,
getPairImages2(true);
return;
/* ======================================================================== */
} else if (label.equals("Rig infinity calibration")) {
} else if (label.equals("RIG extrinsics")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
infinityRig();
return;
/* ======================================================================== */
} else if (label.equals("AUX show fine")) {
} else if (label.equals("SHOW extrinsics")) {
if (QUAD_CLT == null){
QUAD_CLT = new QuadCLT (
QuadCLT.PREFIX,
......@@ -4599,6 +4601,8 @@ private Panel panel1,
}
}
QUAD_CLT_AUX.showExtrinsicCorr("aux");// show_fine_corr("aux");
QUAD_CLT_AUX.geometryCorrection.showRig();// show_fine_corr("aux");
QuadCLT dbg_QUAD_CLT = QUAD_CLT;
QuadCLT dbg_QUAD_CLT_AUX = QUAD_CLT_AUX;
......@@ -4649,6 +4653,12 @@ private Panel panel1,
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
exportMLData();
return;
/* ======================================================================== */
} else if (label.equals("JP4 copy")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
copyJP4src();
return;
/* ======================================================================== */
} else if (label.equals("CLT rig edit")) {
......@@ -5163,7 +5173,7 @@ private Panel panel1,
return true;
}
// boolean adjust_extrinsics = label.equals("CLT Extrinsics") || label.equals("CLT Poly corr");
// boolean adjust_extrinsics = label.equals("MAIN extrinsics") || label.equals("CLT Poly corr");
// boolean adjust_poly = label.equals("CLT Poly corr");
public boolean clt3d(
boolean adjust_extrinsics,
......@@ -5285,8 +5295,8 @@ private Panel panel1,
public boolean exportMLData() {
long startTime=System.nanoTime();
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null)) {
String msg = "DSI data is not available. Please run \"CLT 3D\" first";
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.rig_pre_poles_ds == null)) {
String msg = "DSI data is not available. Please run \"Ground truth\" first";
IJ.showMessage("Error",msg);
System.out.println(msg);
return false;
......@@ -5325,6 +5335,94 @@ private Panel panel1,
return true;
}
public boolean copyJP4src() {
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null)) {
if (QUAD_CLT == null){
QUAD_CLT = new QuadCLT (
QuadCLT.PREFIX,
PROPERTIES,
EYESIS_CORRECTIONS,
CORRECTION_PARAMETERS);
if (DEBUG_LEVEL > 0){
System.out.println("Created new QuadCLT instance, will need to read CLT kernels");
}
}
String configPath=getSaveCongigPath();
if (configPath.equals("ABORT")) return false;
EYESIS_CORRECTIONS.initSensorFiles(DEBUG_LEVEL);
int numChannels=EYESIS_CORRECTIONS.getNumChannels();
CHANNEL_GAINS_PARAMETERS.modifyNumChannels(numChannels);
if (!QUAD_CLT.CLTKernelsAvailable()){
if (DEBUG_LEVEL > 0){
System.out.println("Reading CLT kernels");
}
QUAD_CLT.readCLTKernels(
CLT_PARAMETERS,
THREADS_MAX,
UPDATE_STATUS, // update status info
DEBUG_LEVEL);
if (DEBUG_LEVEL > 1){
QUAD_CLT.showCLTKernels(
THREADS_MAX,
UPDATE_STATUS, // update status info
DEBUG_LEVEL);
}
}
if (!QUAD_CLT.geometryCorrectionAvailable()){
if (DEBUG_LEVEL > 0){
System.out.println("Calculating geometryCorrection");
}
if (!QUAD_CLT.initGeometryCorrection(DEBUG_LEVEL+2)){
return false;
}
}
/*
boolean OK = clt3d(
false, // boolean adjust_extrinsics,
false); // boolean adjust_poly);
if (! OK) {
String msg = "DSI data is not available and \"CLT 3D\" failed";
IJ.showMessage("Error",msg);
System.out.println(msg);
return false;
}
*/
}
if (!prepareRigImages()) return false;
String configPath=getSaveCongigPath();
if (configPath.equals("ABORT")) return false;
if (DEBUG_LEVEL > -2){
System.out.println("++++++++++++++ Copying JP4 source files ++++++++++++++");
}
try {
TWO_QUAD_CLT.copyJP4src( // actually there is no sense to process multiple image sets. Combine with other processing?
QUAD_CLT, // QuadCLT quadCLT_main,
QUAD_CLT_AUX, // QuadCLT quadCLT_aux,
CLT_PARAMETERS, // EyesisCorrectionParameters.DCTParameters dct_parameters,
DEBUG_LEVEL);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //final int debugLevel);
if (configPath!=null) {
saveTimestampedProperties( // save config again
configPath, // full path or null
null, // use as default directory if path==null
true,
PROPERTIES);
}
return true;
}
public boolean infinityRig() {
if (!prepareRigImages()) return false;
String configPath=getSaveCongigPath();
......
......@@ -890,6 +890,19 @@ public class GeometryCorrection {
recalcRXY();
return true;
}
public void showRigOffsets()
{
System.out.println("=== Inter-camera adjustments ===");
System.out.println(" Baseline "+ this.baseline +"mm");
System.out.println(" Angle to the aux camera from the main "+ (180.0/Math.PI*this.aux_angle)+"°");
System.out.println("Auxilliary camera forward from the plane of the main one (not used) "+ this.aux_z +"mm");
System.out.println(" Auxilliary camera azimuth (positive - to the right) "+ (par_scales[AUX_AZIMUTH_INDEX] * this.aux_azimuth) + "pix");
System.out.println(" Auxilliary camera tilt (positive - looking up) "+ (par_scales[AUX_TILT_INDEX] * this.aux_tilt)+"pix");
System.out.println(" Auxilliary camera roll (positive - clockwise) "+ (par_scales[AUX_ROLL_INDEX] * this.aux_roll)+"pix");
System.out.println(" Relative zoom - difference from 1.0 in parts parts per 1/1000 "+ (par_scales[AUX_ZOOM_INDEX] * this.aux_zoom) +"pix");
}
}
public boolean editRig() {
......@@ -899,6 +912,10 @@ public class GeometryCorrection {
return this.rigOffset.editOffsetsPixels();
}
public void showRig() {
this.rigOffset.showRigOffsets();
}
public boolean setRigOffsetFromProperies(String parent_prefix,Properties properties) {
RigOffset rigOffset = new RigOffset();
boolean gotit = rigOffset.getProperties(parent_prefix, properties);
......
......@@ -310,6 +310,7 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
boolean showDemux=showImage && demux;
if (demux) showImage=false;
double [] xtraExif=new double[1]; // ExposureTime
double [] lla = null;
try {
imp = openJpegOrGif(directory, fileName);
if (imp == null) {
......@@ -320,6 +321,12 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
if (ElphelMakerNote==null) ElphelMakerNote = readElphelMakerNote(directory, fileName, 14,xtraExif); /* after or 8.0.8.32 */
if (ElphelMakerNote==null) ElphelMakerNote = readElphelMakerNote(directory, fileName, 12,xtraExif); /* after or 8.0.7.3 */
if (ElphelMakerNote==null) ElphelMakerNote = readElphelMakerNote(directory, fileName, 8 ,xtraExif); /* before 8.0.7.3 */
lla = readGpsLLA(directory, fileName);
if (lla != null) {
imp.setProperty("LATITUDE", String.format("%f",lla[0]));
imp.setProperty("LONGITUDE", String.format("%f",lla[1]));
imp.setProperty("ALTITUDE", String.format("%f",lla[2]));
}
}
} catch (IOException e) {
IJ.showStatus("");
......@@ -850,6 +857,78 @@ public class JP46_Reader_camera extends PlugInFrame implements ActionListener {
return note;
}
double [] readGpsLLA(String directory, String fileName) throws IOException
{
RandomAccessFile in = new RandomAccessFile(directory + fileName, "r");
byte[] head = new byte[4096]; /* just read the beginning of the file */
in.readFully(head);
in.close(); // was no close()! -? "too many open files"
if ((head[this.ExifOffset]!=0x4d) || (head[this.ExifOffset+1]!=0x4d)) {
IJ.showMessage("JP46 Reader", "Exif Header not found in " + directory + fileName);
return null;
}
// skip to gps header
byte [] sig = {0x2, 0x2, 0x0, 0x0};
int i = this.ExifOffset + 2;
boolean match=false;
for (i = this.ExifOffset + 2; i < (head.length - sig.length); i++ ) {
match=true;
for (int j=0;j<sig.length;j++)if (head[i+j]!=sig[j]){
match=false;
break;
}
if (match) break;
}
i += sig.length;
if (i >= (head.length-4)) {
/* IJ.showMessage("JP46 Reader", "MakerNote tag not found in "+directory + fileName+ ", finished at offset="+i); // re-enable with DEBUG_LEVEL*/
return null;
}
// System.out.println(String.format("offset=0x%04x", i));
double [] lla = new double[3];
boolean [] lla_sign = new boolean[3];
for (int ntag = 0; ntag < 10; ntag++) {
// read 2 big endian bytesof tag, and 2 - type
int tag = ((head[i+0] << 8) & 0xff00) + ((head[i+1] << 0) & 0x00ff);
int typ = ((head[i+2] << 8) & 0xff00) + ((head[i+3] << 0) & 0x00ff);
int len = ((head[i+4] <<24) & 0xff000000) + ((head[i+5] <<16) & 0x00ff0000) + ((head[i+ 6] << 8) & 0x0000ff00) + ((head[i+ 7] << 0) & 0x000000ff);
int val = ((head[i+8] <<24) & 0xff000000) + ((head[i+9] <<16) & 0x00ff0000) + ((head[i+10] << 8) & 0x0000ff00) + ((head[i+11] << 0) & 0x000000ff);
// System.out.println(String.format("ntag=%2d tag = 0x%04x type = 0x%04x len = 0x%08x value = 0x%08x", ntag, tag, typ, len, val));
i+=12;
switch (tag) {
case 1: lla_sign[0] = ((val >> 24) & 0xff) == 0x53; break; // S GPSLatitudeRef
case 2: int [] lat_arr = readExifBE(head, this.ExifOffset + val , 2 * len); //GPSLatitude
lla[0] = 1.0*lat_arr[0]/lat_arr[1] + (1.0/60)* lat_arr[2]/lat_arr[3] + (1.0/3600)* lat_arr[4]/lat_arr[5];
break;
case 3: lla_sign[1] = ((val >> 24) & 0xff) == 0x57; break; // W GPSLongitudeRef
case 4: int [] long_arr = readExifBE(head, this.ExifOffset + val , 2 * len); // GPSLongitude
lla[1] = 1.0*long_arr[0]/long_arr[1] + (1.0/60)* long_arr[2]/long_arr[3] + (1.0/3600)* long_arr[4]/long_arr[5];
break;
case 5: lla_sign[2] = ((val >> 24) & 0xff) != 0x0; break; // GPSAltitudeRef
case 6: int [] alt_arr = readExifBE(head, this.ExifOffset + val , 2 * len); // GPSLongitude
lla[2] = 1.0*alt_arr[0]/alt_arr[1];
break;
}
}
for (int j = 0; j < lla.length; j++) {
if (lla_sign[j]) lla[j] *= -1;
}
// System.out.println("Lat = "+lla[0]+" Long = "+lla[1]+ " alt = "+lla[2]+"m");
return lla;
}
int [] readExifBE(byte [] head, int offset, int len) {
int [] data = new int [len];
for (int i = 0; i < len; i++) {
int offs = offset + 4*i;
data[i] = ((head[offs + 0] << 24) & 0xff000000) +
((head[offs + 1] << 16) & 0x00ff0000) +
((head[offs + 2] << 8) & 0x0000ff00) +
((head[offs + 3] << 0) & 0x000000ff);
}
return data;
}
long[] readElphelMakerNoteURL(String url, int len, double [] xtraExif) throws IOException {
URL camURL = null;
URLConnection urlConn = null;
......
......@@ -1261,7 +1261,8 @@ public class MeasuredLayers {
}
if (iworst < 0){
if (debugLevel > 0) {
System.out.println("**** this may be BUG in getDisparityStrengthML() can not find the worst sample - all tiles fit perfectly ****");
System.out.println("**** this may be BUG in getDisparityStrengthML() can not find the worst sample - all tiles fit perfectly ****, num_in_sample="+
num_in_sample+", stX="+stX+", stY="+stY);
}
// this can happen if some samples are the same and all the pixels fit exactly - use all of them
break;
......@@ -1354,7 +1355,8 @@ public class MeasuredLayers {
//remove_far_only
}
if (iworst < 0){
System.out.println("**** this is a BUG2 in getDisparityStrengthML() ****"); // all smpl_d are NaNs
System.out.println("**** this may be BUG2 in getDisparityStrengthML() can not find the worst sample - all tiles fit perfectly ****, num_in_sample="+
num_in_sample+", stX="+stX+", stY="+stY);
break;
}
// remove worst sample
......@@ -1378,7 +1380,7 @@ public class MeasuredLayers {
}
} else {
num_in_sample = 0;
System.out.println("**** this is a BUG in getDisparityStrengthML(), shoud not happen ? ****");
System.out.println("**** this is a BUG in getDisparityStrengthML(), should not happen ? ****");
}
}
}
......@@ -1453,6 +1455,12 @@ public class MeasuredLayers {
}
ds[0][indx] = sd;
ds[1][indx] = sw * lapWeight[dy][dx] /sum_wnd; // average weights, multiply by window //** TODO: change
if ((ds[0][indx] ==0.0) && (ds[0][indx] ==0.0)) {
System.out.println("**** this may be BUG5 in getDisparityStrengthML() ****, num_in_sample="+
num_in_sample+", stX="+stX+", stY="+stY+" ds[0]["+indx+"]="+ds[0][indx]+", ds[1]["+indx+"]="+ds[1][indx]);
ds[1][indx] = 0.0;
}
}
} else {
num_in_sample = 0;
......
......@@ -42,6 +42,7 @@ public class PoleProcessor {
double mean_disparity = 0.0;
double target_disparity = 0.0;
double target_previous = Double.NaN;
boolean skip_update = false; // disparity change is below threshold, no need to update
double mean_x = 0.0;
double mean_y = 0.0;
double strength = 0.0;
......@@ -255,11 +256,11 @@ public class PoleProcessor {
double min_strength,
double disp_adiff,
double disp_rdiff,
double [][] norn_ds)
double [][] norn_ds,
int debugLevel)
{
int extra_margin = 2;
int debugLevel = -1;
int dbg_tileX = 128; // 221;// 128;
int dbg_tileX = -128; // 221;// 128;
int dbg_tileY = 87; // 130; // 87;
if (debugLevel > -2) {
if (eBox.contains(new Point(dbg_tileX, dbg_tileY))) {
......@@ -289,8 +290,10 @@ public class PoleProcessor {
int x0 = (int) Math.round(x);
boolean sep = false;
if ((x0 < 0) || (x0 > hor_profile.length )) {
System.out.println(String.format("Disabling cluster {%d, %d, %d, %d} disp= %f as it is not separated on right or left. x0= %d",
eBox.x, eBox.y, eBox.width, eBox.height, target_disparity, x0));
if (debugLevel > -2) {
System.out.println(String.format("Disabling cluster {%d, %d, %d, %d} disp= %f as it is not separated on right or left. x0= %d",
eBox.x, eBox.y, eBox.width, eBox.height, target_disparity, x0));
}
return false;
}
for (int i = x0+extra_margin; i < hor_profile.length; i++) {
......@@ -300,8 +303,10 @@ public class PoleProcessor {
}
}
if (!sep) {
System.out.println(String.format("Disabling cluster {%d, %d, %d, %d} disp= %f as it is not separated on right. x0= %d",
eBox.x, eBox.y, eBox.width, eBox.height, target_disparity, x0));
if (debugLevel > -2) {
System.out.println(String.format("Disabling cluster {%d, %d, %d, %d} disp= %f as it is not separated on right. x0= %d",
eBox.x, eBox.y, eBox.width, eBox.height, target_disparity, x0));
}
return false;
}
sep = false;
......@@ -312,11 +317,11 @@ public class PoleProcessor {
}
}
if (!sep) {
System.out.println(String.format("Disabling cluster {%d, %d, %d, %d} disp= %f as it is not separated on left. x0= %d",
eBox.x, eBox.y, eBox.width, eBox.height, target_disparity, x0));
if (debugLevel > -2) {
System.out.println(String.format("Disabling cluster {%d, %d, %d, %d} disp= %f as it is not separated on left. x0= %d",
eBox.x, eBox.y, eBox.width, eBox.height, target_disparity, x0));
}
}
return sep;
}
......@@ -503,8 +508,9 @@ public class PoleProcessor {
public PoleCluster[] checkAndSplit(
double [][] norm_ds,
int min_dist, // minimal distance
boolean must_zero) {
if ((eBox.x == 61) && (eBox.y== 128)) {
boolean must_zero,
int debugLevel) {
if ((eBox.x == -61) && (eBox.y== 128)) {
System.out.println("Debugging "+this.toString());
}
if (eBox.width < 2) {
......@@ -591,7 +597,9 @@ public class PoleProcessor {
int dx = dsp.nTile % tilesX - eBox.x;
two_clusters[(dx < cut)? 0 : 1].addDs(dsp);
}
System.out.println("Splitting cluster "+this.toString()+" into 2: "+two_clusters[0]+toString()+" and "+two_clusters[1].toString());
if (debugLevel > -2) {
System.out.println("Splitting cluster "+this.toString()+" into 2: "+two_clusters[0]+toString()+" and "+two_clusters[1].toString());
}
}
return two_clusters;
......@@ -817,7 +825,8 @@ public class PoleProcessor {
public void filterByMask(
boolean trim_bottom)
boolean trim_bottom,
int debugLevel)
{
if (trim_bottom) {
......@@ -827,8 +836,10 @@ public class PoleProcessor {
}
int height = indx/eBox.width + 1;
if (height < eBox.height) {
System.out.println(String.format("filterByMask() Trimming {%3d, %3d, %2d, %2d}:%7.5f to height %2d",
eBox.x, eBox.y, eBox.width,eBox.height, target_disparity, height));
if (debugLevel > -2) {
System.out.println(String.format("filterByMask() Trimming {%3d, %3d, %2d, %2d}:%7.5f to height %2d",
eBox.x, eBox.y, eBox.width,eBox.height, target_disparity, height));
}
xc_center -= 0.5 * slope * (eBox.height - height);
eBox.height = height;
boolean [] mask = new boolean[eBox.width * eBox.height];
......@@ -857,6 +868,7 @@ public class PoleProcessor {
return target_disparity - target_previous;
}
public double applyMeasuredDisparity(
double min_diff, // do not update if last difference was smaller than requested
double disparity_scale, // target disparity to differential disparity scale (baseline ratio) (~0.2)
double diff_power, // bias towards higher disparities - (disparity+offset) is raised to this power and applied to weight
// if 0.0 - do not apply value to weight
......@@ -865,6 +877,7 @@ public class PoleProcessor {
double keep_bottom, // do not cut more that this fraction of the bounding box height
int debugLevel) // debug level
{
if (skip_update) return getTargetDiff();
int cut = (int) Math.round(Math.min(eBox.height * keep_bottom, cut_bottom));
int height = eBox.height - cut;
double sw=0.0, swd = 0.0;
......@@ -888,6 +901,7 @@ public class PoleProcessor {
double diff = disparity_scale * swd;
target_previous = target_disparity;
target_disparity += diff;
skip_update |= (Math.abs(diff) < min_diff);
if (debugLevel > 0) {
System.out.println("applyMeasuredDisparity() for cluster "+this.toString()+" target disparity change: "+diff);
}
......@@ -1255,7 +1269,9 @@ public class PoleProcessor {
PoleCluster [] two_clusters = cluster.checkAndSplit(
norm_ds,
min_dist,
must_zero);
must_zero,
debugLevel);
if (two_clusters != null) {
num_split++;
clusters.remove(nClust);
......@@ -1263,14 +1279,20 @@ public class PoleProcessor {
if (two_clusters[1].getNumTiles() > 0) {
clusters.add(nClust,two_clusters[1]);
} else {
System.out.println("Cluster 1 "+two_clusters[1]+ " has no tiles - discarding");
if (debugLevel > -2) {
System.out.println("Cluster 1 "+two_clusters[1]+ " has no tiles - discarding");
}
}
if (two_clusters[0].getNumTiles() > 0) {
clusters.add(nClust,two_clusters[0]);
} else {
System.out.println("Cluster 0 "+two_clusters[0]+ " has no tiles - discarding");
if (debugLevel > -2) {
System.out.println("Cluster 0 "+two_clusters[0]+ " has no tiles - discarding");
}
}
if (debugLevel > -2) {
System.out.println("Number of clusters: "+clusters.size());
}
System.out.println("Number of clusters: "+clusters.size());
}
......@@ -1476,13 +1498,15 @@ public class PoleProcessor {
}
}
for (PoleCluster cluster: clusters){
int layer = cluster.getLayer();
double disp = cluster.getTargetDisparity(); // getMeanDisp();
Rectangle box = new Rectangle(cluster.getEBox());
int nTile = box.y * tilesX + box.x;
for (int dy = 0; dy < box.height; dy++) {
for (int dx = 0; dx < box.width;dx++) {
dbg_layers[layer][tnImage.getNeibIndex(nTile, dx, dy)] = disp; // should never be out of bounds
if (!cluster.skip_update) {
int layer = cluster.getLayer();
double disp = cluster.getTargetDisparity(); // getMeanDisp();
Rectangle box = new Rectangle(cluster.getEBox());
int nTile = box.y * tilesX + box.x;
for (int dy = 0; dy < box.height; dy++) {
for (int dx = 0; dx < box.width;dx++) {
dbg_layers[layer][tnImage.getNeibIndex(nTile, dx, dy)] = disp; // should never be out of bounds
}
}
}
}
......@@ -1496,7 +1520,7 @@ public class PoleProcessor {
final ArrayList<PoleCluster> clusters
) {
final TileNeibs tnImage = biCamDSI.tnImage;
// final int num_tiles = tnImage.sizeX * tnImage.sizeY;
// final int num_tiles = tnImage.sizeX * tnImage.sizeY;
final int tilesX = tnImage.sizeX;
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
......@@ -1507,17 +1531,19 @@ public class PoleProcessor {
public void run() {
for (int nClust = ai.getAndIncrement(); nClust < num_clust; nClust = ai.getAndIncrement()) {
PoleCluster cluster = clusters.get(nClust);
Rectangle box = cluster.getEBox();
int layer = cluster.getLayer();
if (reset_data) {
cluster.resetDsPairs();
}
int nTile = box.x + tilesX * box.y;
for (int dy = 0; dy < box.height; dy++) {
for (int dx = 0; dx < box.width; dx++) {
int nTile1 = tnImage.getNeibIndex(nTile, dx, dy); // should always be inside image
if (!Double.isNaN(measured_layers[layer][0][nTile1])) {
cluster.addDs(nTile1, measured_layers[layer][0][nTile1], measured_layers[layer][1][nTile1]);
if (!cluster.skip_update) {
Rectangle box = cluster.getEBox();
int layer = cluster.getLayer();
if (reset_data) {
cluster.resetDsPairs();
}
int nTile = box.x + tilesX * box.y;
for (int dy = 0; dy < box.height; dy++) {
for (int dx = 0; dx < box.width; dx++) {
int nTile1 = tnImage.getNeibIndex(nTile, dx, dy); // should always be inside image
if (!Double.isNaN(measured_layers[layer][0][nTile1])) {
cluster.addDs(nTile1, measured_layers[layer][0][nTile1], measured_layers[layer][1][nTile1]);
}
}
}
}
......@@ -1601,7 +1627,8 @@ public class PoleProcessor {
public void filterByMask(
final boolean trim_bottoms,
final ArrayList<PoleCluster> clusters)
final ArrayList<PoleCluster> clusters,
final int debugLevel)
{
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
......@@ -1612,7 +1639,7 @@ public class PoleProcessor {
public void run() {
for (int nClust = ai.getAndIncrement(); nClust < num_clust; nClust = ai.getAndIncrement()) {
PoleCluster cluster = clusters.get(nClust);
cluster.filterByMask(trim_bottoms);
cluster.filterByMask(trim_bottoms, debugLevel);
}
}
};
......@@ -1625,7 +1652,8 @@ public class PoleProcessor {
final double disp_adiff,
final double disp_rdiff,
final double [][] norn_ds,
final ArrayList<PoleCluster> clusters)
final ArrayList<PoleCluster> clusters,
final int debugLevel)
{
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
......@@ -1638,12 +1666,15 @@ public class PoleProcessor {
PoleCluster cluster = clusters.get(nClust);
boolean sep = cluster.checkRightLeft(
min_strength, // double min_strength,
disp_adiff, // double disp_adiff,
disp_rdiff, // double disp_rdiff,
norn_ds); // [][] norn_ds);
disp_adiff, // double disp_adiff,
disp_rdiff, // double disp_rdiff,
norn_ds, // double [][] norn_ds);
debugLevel); // final int debugLevel
if (!sep) {
System.out.println(String.format("Disabling cluster {%d, %d, %d, %d} disp= %f as it is not separated on right or left",
cluster.eBox.x, cluster.eBox.y, cluster.eBox.width, cluster.eBox.height, cluster.target_disparity));
if (debugLevel > -2) {
System.out.println(String.format("Disabling cluster {%d, %d, %d, %d} disp= %f as it is not separated on right or left",
cluster.eBox.x, cluster.eBox.y, cluster.eBox.width, cluster.eBox.height, cluster.target_disparity));
}
cluster.disabled = true;
}
}
......@@ -1654,6 +1685,7 @@ public class PoleProcessor {
}
public double applyMeasuredDisparity(
final double min_diff, // do not update if last difference was smaller than requested
final double disparity_scale, // target disparity to differential disparity scale (baseline ratio)
final double diff_power, // bias towards higher disparities - (disparity+offset) is raised to this power and applied to weight
// if 0.0 - do not apply value to weight
......@@ -1672,16 +1704,19 @@ public class PoleProcessor {
public void run() {
for (int nClust = ai.getAndIncrement(); nClust < num_clust; nClust = ai.getAndIncrement()) {
PoleCluster cluster = clusters.get(nClust);
double diff = cluster.applyMeasuredDisparity(
disparity_scale, // double disparity_scale, // target disparity to differential disparity scale (baseline ratio)
diff_power, // double diff_power, // bias towards higher disparities - (disparity+offset) is raised to this power and applied to weight
// if 0.0 - do not apply value to weight
diff_offset, // double diff_offset, // add to measured differential disparity before raising to specified power
cut_bottom, // int cut_bottom, // cut few tile rows from the very bottom - they may be influenced by ground objects
keep_bottom, // double keep_bottom, // do not cut more that this fraction of the bounding box height
debugLevel); // int debugLevel); // debug level
if (debugLevel > -2) {
System.out.println("applyMeasuredDisparity() for cluster "+cluster.toString()+" -> target disparity change: "+diff);
if (!cluster.skip_update) {
double diff = cluster.applyMeasuredDisparity(
min_diff, // double min_diff, // do not update if last difference was smaller than requested
disparity_scale, // double disparity_scale, // target disparity to differential disparity scale (baseline ratio)
diff_power, // double diff_power, // bias towards higher disparities - (disparity+offset) is raised to this power and applied to weight
// if 0.0 - do not apply value to weight
diff_offset, // double diff_offset, // add to measured differential disparity before raising to specified power
cut_bottom, // int cut_bottom, // cut few tile rows from the very bottom - they may be influenced by ground objects
keep_bottom, // double keep_bottom, // do not cut more that this fraction of the bounding box height
debugLevel); // int debugLevel); // debug level
if (debugLevel > -2) {
System.out.println("applyMeasuredDisparity() for cluster "+cluster.toString()+" -> target disparity change: "+diff); // + " skip_update="+cluster.skip_update);
}
}
}
}
......@@ -1690,13 +1725,14 @@ public class PoleProcessor {
ImageDtt.startAndJoin(threads);
double max_diff = 0.0;
for (PoleCluster cluster: clusters) {
if (Math.abs(cluster.getTargetDiff()) > max_diff) {
if (!cluster.skip_update && (Math.abs(cluster.getTargetDiff()) > max_diff)) {
max_diff = Math.abs(cluster.getTargetDiff());
}
}
return max_diff;
}
public void printClusterStats(
PoleProcessorParameters poleProcessorParameters,
final int min_filter,
......@@ -1903,7 +1939,9 @@ public class PoleProcessor {
final boolean trim_bottoms = true; // false; // true;
filterByMask(
trim_bottoms, // final boolean trim_bottoms,
pole_clusters); // final ArrayList<PoleCluster> clusters)
pole_clusters, // final ArrayList<PoleCluster> clusters)
debugLevel); // final int debugLevel)
if (debugLevel > -2) {
......@@ -1919,7 +1957,9 @@ public class PoleProcessor {
clt_parameters.poles.sep_disp_adiff, // final double disp_adiff,
clt_parameters.poles.sep_disp_rdiff, // final double disp_rdiff,
norm_ds, // final double [][] norn_ds,
pole_clusters); // final ArrayList<PoleCluster> clusters)
pole_clusters, // final ArrayList<PoleCluster> clusters)
debugLevel); // final int debugLevel)
int num_removed =removeFilteredClusters(
clt_parameters.poles, //PoleProcessorParameters poleProcessorParameters
pole_clusters, // ArrayList<PoleCluster> clusters,
......@@ -1936,6 +1976,7 @@ public class PoleProcessor {
}
double max_target_diff = applyMeasuredDisparity(
clt_parameters.poles.min_refine_diff, // double min_diff, // do not update if last difference was smaller than requested
clt_parameters.poles.disparity_scale, // final double disparity_scale, // target disparity to differential disparity scale (baseline ratio)
clt_parameters.poles.diff_power, // final double diff_power, // bias towards higher disparities - (disparity+offset) is raised to this power and applied to weight
// if 0.0 - do not apply value to weight
......@@ -1967,6 +2008,7 @@ public class PoleProcessor {
debugLevel + 0); //final int debugLevel)
max_target_diff = applyMeasuredDisparity(
clt_parameters.poles.min_refine_diff, // double min_diff, // do not update if last difference was smaller than requested
clt_parameters.poles.disparity_scale, // final double disparity_scale, // target disparity to differential disparity scale (baseline ratio)
clt_parameters.poles.diff_power, // final double diff_power, // bias towards higher disparities - (disparity+offset) is raised to this power and applied to weight
// if 0.0 - do not apply value to weight
......@@ -1976,10 +2018,9 @@ public class PoleProcessor {
pole_clusters, // final ArrayList<PoleCluster> clusters,
debugLevel); // final int debugLevel) // debug level
if (debugLevel > -2) {
System.out.println("applyMeasuredDisparity() -> "+max_target_diff+" (max_diff)");
System.out.println("applyMeasuredDisparity():" +nRefine+ " -> "+max_target_diff+" (max_diff)");
}
if (debugLevel > 0) {
double [][] dbg_layers = dbgClusterLayers( // layer and eBox should be set
clt_parameters.poles, //PoleProcessorParameters poleProcessorParameters
......@@ -2009,7 +2050,8 @@ public class PoleProcessor {
// select measured:
filterByMask(
false, // trim_bottoms, // final boolean trim_bottoms,
pole_clusters); // final ArrayList<PoleCluster> clusters)
pole_clusters, // final ArrayList<PoleCluster> clusters)
debugLevel); // final int debugLevel)
}
......@@ -2022,16 +2064,15 @@ public class PoleProcessor {
pole_clusters, // ArrayList<PoleProcessor.PoleCluster> pole_clusters,
norm_ds); // double [][] norm_ds
}
if (max_target_diff < clt_parameters.poles.min_refine_diff) {
break;
}
} // for (int nRefine = 0; nRefine < max_refines; nRefine ++) {
double [][] poleDisparityStrength = exportPoleDisparityStrength(
clt_parameters.poles, //PoleProcessorParameters poleProcessorParameters
0, // -1, // int filter_value,
pole_clusters); // ArrayList<PoleCluster> clusters)
/* double [][] all_ds = biScan.getDisparityStrength(
false, // only_strong,
false, // only_trusted,
false); // true); // only_enabled);
*/
double [][] all_ds = {src_ds[0].clone(),src_ds[1].clone()};
for (int nTile = 0; nTile < all_ds[0].length; nTile++) {
......@@ -2043,41 +2084,54 @@ public class PoleProcessor {
}
}
// for (int nTile = 0; nTile < all_ds[0].length; nTile++) {
// if (Double.isNaN(all_ds[0][nTile]) || (all_ds[0][nTile] < 0.001)) {
// all_ds[0][nTile] = Double.NaN;
// all_ds[1][nTile] = 0.0;
// }
// }
// if (debugLevel> -2) {
// biScan.showScan(quadCLT_main.image_name+"-POLES", poleDisparityStrength);
// biScan.showScan(quadCLT_main.image_name+"-ALL-AND-POLES", all_ds);
// }
// System.out.println("quadCLT_main.tp.clt_3d_passes_size="+quadCLT_main.tp.clt_3d_passes_size+", quadCLT_main.tp.clt_3d_passes.size()="+quadCLT_main.tp.clt_3d_passes.size());
// CLTPass3d scan_last = quadCLT_main.tp.clt_3d_passes.get( quadCLT_main.tp.clt_3d_passes.size() -1); // get really last one
// boolean [] selection = scan_last.getSelected();
for (int nTile = 0; nTile < all_ds[0].length; nTile++) {
if (!Double.isNaN(poleDisparityStrength[0][nTile])) {
selection[nTile] = true; // add to source selection
}
}
if (debugLevel > -4) {
System.out.println(" === final \"pole\" clusters ===");
printClusterStats(
clt_parameters.poles, //PoleProcessorParameters poleProcessorParameters
0, // minimal filter value
pole_clusters);
}
return all_ds;
/*
quadCLT_main.tp.trimCLTPasses(false); // remove rig composite scan if any
CLTPass3d rig_scan = quadCLT_main.tp.compositeScan(
all_ds[0], // final double [] disparity,
all_ds[1], // final double [] strength,
selection, // final boolean [] selected,
debugLevel); // final int debugLevel)
rig_scan.texture_tiles = scan_last.texture_tiles;
// scan_last
quadCLT_main.tp.clt_3d_passes.add(rig_scan);
quadCLT_main.tp.saveCLTPasses(true); // rig pass
return true;
*/
}
public int zero_tiles_check(
String title,
double [][] ds,
boolean debug)
{
double [][] zero_tiles = new double [2][ds[0].length];
int num_strong_zeros = 0;
for (int nTile = 0; nTile < zero_tiles.length; nTile++) {
zero_tiles[0][nTile] = Double.NaN;
zero_tiles[1][nTile] = Double.NaN;
if ((ds[1][nTile] != 0.0) && !(ds[0][nTile] > 0.0)) {
zero_tiles[0][nTile] = ds[0][nTile];
zero_tiles[1][nTile] = ds[1][nTile];
ds[0][nTile] = Double.NaN;
ds[1][nTile] = 0.0;
num_strong_zeros++;
}
}
if (debug && (num_strong_zeros > 0)) {
String [] titles = {"disparity","zero_disparity", "strength", "zero_strength"};
double [][] dbg_layers = {ds[0], zero_tiles[0], ds[1], zero_tiles[1]};
(new showDoubleFloatArrays()).showArrays(
dbg_layers,
tilesX,
tilesY,
true,
title+"-ZERO-STRONG-BUGS",
titles);
}
return num_strong_zeros;
}
public void debugClusterRefineImages(
......
......@@ -24,10 +24,19 @@
//import java.awt.Polygon;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import ij.CompositeImage;
......@@ -67,6 +76,7 @@ public class QuadCLT {
TileProcessor tp = null;
String image_name = null;
double [] gps_lla = null;
double [][][] image_data = null;
boolean [][] saturation_imp = null; // (near) saturated pixels or null
boolean is_aux = false;
......@@ -4730,7 +4740,7 @@ public class QuadCLT {
public boolean editRig()
{
if (!is_aux) {
System.out.println("Rig offsets can only be edited for the auxiliary camera, not for the amin one");
System.out.println("Rig offsets can only be edited for the auxiliary camera, not for the main one");
return false;
}
// GeometryCorrection gc = this.geometryCorrection;
......@@ -7700,13 +7710,16 @@ public class QuadCLT {
System.out.println("Wavefront object file saved to "+wfOutput.obj_path);
System.out.println("Wavefront material file saved to "+wfOutput.mtl_path);
}
// Save KML and ratings files if they do not exist (so not to overwrite edited ones), make them world-writable
writeKml (debugLevel);
writeRatingFile (debugLevel);
Runtime.getRuntime().gc();
System.out.println("output3d(): generating 3d output files finished at "+
IJ.d2s(0.000000001*(System.nanoTime()-this.startStepTime),3)+" sec, --- Free memory="+Runtime.getRuntime().freeMemory()+" (of "+Runtime.getRuntime().totalMemory()+")");
return true;
// return imp_bgnd; // relative (to x3d directory) path - (String) imp_bgnd.getProperty("name");
}
......@@ -9079,5 +9092,160 @@ public class QuadCLT {
IJ.d2s(0.000000001*(System.nanoTime()-this.startTime),3)+" sec, --- Free memory="+Runtime.getRuntime().freeMemory()+" (of "+Runtime.getRuntime().totalMemory()+")");
}
public void setGpsLla(
String source_file)
{
ImagePlus imp=(new JP46_Reader_camera(false)).open(
"", // path,
source_file,
"", //arg - not used in JP46 reader
true, // un-apply camera color gains
null, // new window
false); // do not show
if (imp.getProperty("LATITUDE") != null){
gps_lla = new double[3];
for (int i = 0; i < 3; i++) {
gps_lla[i] = Double.NaN;
}
if (imp.getProperty("LATITUDE") != null) gps_lla[0] =Double.parseDouble((String) imp.getProperty("LATITUDE"));
if (imp.getProperty("LONGITUDE") != null) gps_lla[1] =Double.parseDouble((String) imp.getProperty("LONGITUDE"));
if (imp.getProperty("ALTITUDE") != null) gps_lla[2] =Double.parseDouble((String) imp.getProperty("ALTITUDE"));
}
}
public boolean writeKml(
int debugLevel )
{
String [] sourceFiles_main=correctionsParameters.getSourcePaths();
// String [] sourceFiles_aux=quadCLT_main.correctionsParameters.getSourcePaths();
setGpsLla(sourceFiles_main[0]);
String set_name = image_name;
if (set_name == null ) {
QuadCLT.SetChannels [] set_channels=setChannels(debugLevel);
set_name = set_channels[0].set_name;
}
if (gps_lla != null) {
String kml_copy_dir= correctionsParameters.selectX3dDirectory(
set_name, // quad timestamp. Will be ignored if correctionsParameters.use_x3d_subdirs is false
null,
true, // smart,
true); //newAllowed, // save
double ts = Double.parseDouble(set_name.replace('_', '.'));
(new X3dOutput()).generateKML(
kml_copy_dir+ Prefs.getFileSeparator()+set_name+".kml", // String path,
false, // boolean overwrite,
"", // String icon_path, //<href>x3d/1487451413_967079.x3d</href> ?
ts, // double timestamp,
gps_lla); // double [] lla)
} else {
if (debugLevel > -2) {
System.out.println("GPS data not available, skipping KML file generation (TODO: maybe make some default LLA?)");
}
}
return true;
}
public boolean createThumbNailImage(
ImagePlus imp,
String dir,
String name,
int debugLevel)
{
String thumb_path = dir + Prefs.getFileSeparator() + name+".jpeg";
if (new File(thumb_path).exists()) {
System.out.println("file "+thumb_path+" exists, skipping thumbnail generation");
return false;
}
int image_width = imp.getWidth();
int image_height = imp.getHeight();
double scale_h = 1.0 * correctionsParameters.thumb_width/image_width;
double scale_v = 1.0 * correctionsParameters.thumb_height/image_height;
// double scale = Math.min(scale_h, scale_v) /correctionsParameters.thumb_size;
double scale = scale_h / correctionsParameters.thumb_size;
// ImageProcessor ip = imp.getChannelProcessor();
ImageProcessor ip = imp.getProcessor().duplicate();
ip.setInterpolationMethod(ImageProcessor.BICUBIC);
// ip.setInterpolationMethod(ImageProcessor.BILINEAR);
ip.blurGaussian(2.0);
ip.scale(scale, scale);
// Rectangle rs = new Rectangle(
// (int)Math.round(0.5*image_width*(1.0-scale)),
// (int)Math.round(0.5*image_height*(1.0-scale)),
// (int)Math.round(image_width*scale),
// (int)Math.round(image_height*scale));
// int scaled_width = rs.width; // ip.getWidth();
// int scaled_height = rs.height; // ip.getHeight();
// int lm = (int) Math.round ((scaled_width-correctionsParameters.thumb_width)* correctionsParameters.thumb_h_center);
// int tm = (int) Math.round ((scaled_height-correctionsParameters.thumb_height)* correctionsParameters.thumb_v_center);
int lm = (int) Math.round (((image_width*scale)-correctionsParameters.thumb_width)* correctionsParameters.thumb_h_center + (0.5*image_width*(1.0-scale)));
int tm = (int) Math.round (((image_height*scale)-correctionsParameters.thumb_height)* correctionsParameters.thumb_v_center + (0.5*image_height*(1.0-scale)));
Rectangle r = new Rectangle(lm,tm,correctionsParameters.thumb_width,correctionsParameters.thumb_height);
ip.setRoi(r);
ImageProcessor ip2 = ip.crop();
ImagePlus ip_thumb = new ImagePlus(name,ip2);
eyesisCorrections.saveAndShow(
ip_thumb,
dir,
false,
false,
correctionsParameters.JPEG_quality, // jpegQuality); // jpegQuality){// <0 - keep current, 0 - force Tiff, >0 use for JPEG
(debugLevel > -2) ? debugLevel : 1); // int debugLevel (print what it saves)
return true;
}
public boolean writeRatingFile(
int debugLevel
)
{
String set_name = image_name;
if (set_name == null ) {
QuadCLT.SetChannels [] set_channels = setChannels(debugLevel);
set_name = set_channels[0].set_name;
}
String model_dir= correctionsParameters.selectX3dDirectory(
set_name, // quad timestamp. Will be ignored if correctionsParameters.use_x3d_subdirs is false
null,
true, // smart,
true); //newAllowed, // save
String fname = model_dir+ Prefs.getFileSeparator()+"rating.txt";
File rating_file = new File(fname);
if (rating_file.exists()) {
if (debugLevel > -2){
System.out.println("file "+rating_file.getPath()+" exists, skipping overwrite");
}
return false;
}
List<String> lines = Arrays.asList(correctionsParameters.default_rating+"");
Path path = Paths.get(fname);
try {
Files.write(path,lines, Charset.forName("UTF-8"));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return false;
}
try {
Path fpath = Paths.get(rating_file.getCanonicalPath());
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(fpath);
perms.add(PosixFilePermission.OTHERS_WRITE);
Files.setPosixFilePermissions(fpath, perms);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
}
}
......@@ -1926,6 +1926,10 @@ public class TilePlanes {
for (int indx = 0; indx < disp_str[nl][0].length; indx++){
if (tile_sel[nl][indx]) {
double w = disp_str[nl][1][indx];
if ((w > 0.0) && !(disp_str[nl][0][indx] > 0.0)) {
System.out.println("BUG!!!: getPlaneFromMeas(): disp_str[nl][0]["+indx+"]="+disp_str[nl][0][indx]+", disp_str[nl][1]["+indx+"]="+disp_str[nl][1][indx]);
continue;
}
if (w > 0.0){
tiles_xyzw[nl][indx] = new double [4];
double d = disp_str[nl][0][indx];
......@@ -2020,6 +2024,7 @@ public class TilePlanes {
acovar [2][2] += w * z * z;
if (Double.isNaN(acovar [0][0])) {
System.out.println("--*--BUG! acovar[0][0] is NaN");
return null;
}
}
}
......
......@@ -20,6 +20,10 @@
** -----------------------------------------------------------------------------**
**
*/
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import ij.IJ;
......@@ -708,6 +712,18 @@ public class TwoQuadCLT {
quadCLT_main.correctionsParameters.JPEG_quality, // jpegQuality); // jpegQuality){// <0 - keep current, 0 - force Tiff, >0 use for JPEG
(debugLevel > 0) ? debugLevel : 1); // int debugLevel (print what it saves)
}
String model_path= quadCLT_main.correctionsParameters.selectX3dDirectory(
name, // quad timestamp. Will be ignored if correctionsParameters.use_x3d_subdirs is false
null,
true, // smart,
true); //newAllowed, // save
quadCLT_main.createThumbNailImage(
imps_RGB[0],
model_path,
"thumb",
debugLevel);
}
}
......@@ -1210,6 +1226,8 @@ if (debugLevel > -100) return true; // temporarily !
return true;
}
public boolean processPoles(
QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux,
......@@ -1238,19 +1256,26 @@ if (debugLevel > -100) return true; // temporarily !
if (debugLevel> -1) {
biScan.showScan(quadCLT_main.image_name+"LastBiScan-"+scan_index, null);
}
if (poleProcessor_persistent == null) {
// if (poleProcessor_persistent == null) {
poleProcessor_persistent = new PoleProcessor(
biCamDSI_persistent,
this, // TwoQuadCLT twoQuadCLT,
quadCLT_main.tp.getTilesX(),
quadCLT_main.tp.getTilesY());
}
// }
PoleProcessor pp = poleProcessor_persistent;
boolean [] selection = quadCLT_main.tp.rig_pre_poles_sel.clone();
int num_bugs_corrected= pp.zero_tiles_check(
"pre-poles",
quadCLT_main.tp.rig_pre_poles_ds, // double [][] ds,
true); // boolean debug)
if (num_bugs_corrected > 0) {
System.out.println("Corrected "+num_bugs_corrected+" bugs, where disparity is <= 0 with non-zero strength before poles");
}
double [][] poles_ds = pp.processPoles(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, //QuadCLT quadCLT_aux,
// biScan, // BiScan biScan,
quadCLT_main.tp.rig_pre_poles_ds, // double [][] src_ds, // source disparity, strength pair
selection, // boolean [] selection, // source tile selection, will be modified
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
......@@ -1258,16 +1283,17 @@ if (debugLevel > -100) return true; // temporarily !
updateStatus, // final boolean updateStatus,
debugLevel); // final int globalDebugLevel)
// System.out.println("quadCLT_main.tp.clt_3d_passes_size="+quadCLT_main.tp.clt_3d_passes_size+", quadCLT_main.tp.clt_3d_passes.size()="+quadCLT_main.tp.clt_3d_passes.size());
num_bugs_corrected= pp.zero_tiles_check(
"post-poles",
poles_ds, // double [][] ds,
true); // boolean debug)
if (num_bugs_corrected > 0) {
System.out.println("Corrected "+num_bugs_corrected+" bugs, where disparity is <= 0 with non-zero strength after poles");
}
quadCLT_main.tp.rig_post_poles_ds = poles_ds; // Rig disparity and strength before processing poles
quadCLT_main.tp.rig_post_poles_sel = selection; // Rig tile selection before processing poles
CLTPass3d scan_last = quadCLT_main.tp.clt_3d_passes.get( quadCLT_main.tp.clt_3d_passes.size() -1); // get really last one
//
//
// boolean [] selection = scan_last.getSelected();
// for (int nTile = 0; nTile < all_ds[0].length; nTile++) {
// if (!Double.isNaN(poleDisparityStrength[0][nTile])) {
// selection[nTile] = true;
// }
// }
quadCLT_main.tp.trimCLTPasses(false); // remove rig composite scan if any
CLTPass3d rig_scan = quadCLT_main.tp.compositeScan(
......@@ -1339,7 +1365,8 @@ if (debugLevel > -100) return true; // temporarily !
final int tilesX = quadCLT_main.tp.getTilesX();
final int tilesY = quadCLT_main.tp.getTilesY();
BiCamDSI biCamDSI = new BiCamDSI( tilesX, tilesY, threadsMax);
boolean [][] dbg_sel = (debugLevel > -4)? new boolean [8][]:null;// was 4
// boolean [][] dbg_sel = (debugLevel > -4)? new boolean [8][]:null;// was 4
boolean [][] dbg_sel = (debugLevel > -2)? new boolean [8][]:null;// was 4
if (dbg_sel!=null) dbg_sel[0] = infinity_select;
if (dbg_sel!=null) dbg_sel[1] = was_select;
if (clt_parameters.rig.ltfar_en) {
......@@ -1504,6 +1531,8 @@ if (debugLevel > -100) return true; // temporarily !
// quadCLT_main.tp.rig_pre_poles_sel = selection; // Rig tile selection before processing poles
quadCLT_main.tp.rig_pre_poles_ds = rig_disparity_strength; // Rig disparity and strength before processing poles
quadCLT_main.tp.rig_pre_poles_sel = selection; // Rig tile selection before processing poles
quadCLT_main.tp.rig_post_poles_ds = null;
quadCLT_main.tp.rig_post_poles_sel = null;
if (debugLevel > -4) {
System.out.println("Saved quadCLT_main.tp.rig_pre_poles_ds and quadCLT_main.tp.rig_pre_poles_sel");
......@@ -1514,32 +1543,53 @@ if (debugLevel > -100) return true; // temporarily !
System.out.println("Processing poles");
}
if (poleProcessor_persistent == null) {
poleProcessor_persistent = new PoleProcessor(
biCamDSI_persistent,
this, // TwoQuadCLT twoQuadCLT,
quadCLT_main.tp.getTilesX(),
quadCLT_main.tp.getTilesY());
}
PoleProcessor pp = poleProcessor_persistent;
selection = quadCLT_main.tp.rig_pre_poles_sel.clone();
double [][] poles_ds = pp.processPoles(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, //QuadCLT quadCLT_aux,
// biScan, // BiScan biScan,
quadCLT_main.tp.rig_pre_poles_ds, // double [][] src_ds, // source disparity, strength pair
selection, // boolean [] selection, // source tile selection, will be modified
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int globalDebugLevel)
quadCLT_main.tp.rig_post_poles_ds = poles_ds; // Rig disparity and strength before processing poles
quadCLT_main.tp.rig_post_poles_sel = selection; // Rig tile selection before processing poles
if (debugLevel > -4) {
System.out.println("Saved quadCLT_main.tp.rig_post_poles_ds and quadCLT_main.tp.rig_post_poles_sel");
}
f_rig_disparity_strength = poles_ds;
// if (poleProcessor_persistent == null) {
poleProcessor_persistent = new PoleProcessor(
biCamDSI_persistent,
this, // TwoQuadCLT twoQuadCLT,
quadCLT_main.tp.getTilesX(),
quadCLT_main.tp.getTilesY());
// }
PoleProcessor pp = poleProcessor_persistent;
selection = quadCLT_main.tp.rig_pre_poles_sel.clone();
int num_bugs_corrected= pp.zero_tiles_check(
"pre-poles",
quadCLT_main.tp.rig_pre_poles_ds, // double [][] ds,
true); // boolean debug)
if (num_bugs_corrected > 0) {
System.out.println("Corrected "+num_bugs_corrected+" bugs, where disparity is <= 0 with non-zero strength before poles");
}
double [][] poles_ds = pp.processPoles(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, //QuadCLT quadCLT_aux,
quadCLT_main.tp.rig_pre_poles_ds, // double [][] src_ds, // source disparity, strength pair
selection, // boolean [] selection, // source tile selection, will be modified
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
(debugLevel > -2) ? clt_parameters.poles.poles_debug_level:debugLevel);//
// (debugLevel > -4) ? clt_parameters.poles.poles_debug_level:debugLevel);//
// debugLevel); // final int globalDebugLevel)
num_bugs_corrected= pp.zero_tiles_check(
"post-poles",
poles_ds, // double [][] ds,
true); // boolean debug)
if (num_bugs_corrected > 0) {
System.out.println("Corrected "+num_bugs_corrected+" bugs, where disparity is <= 0 with non-zero strength after poles");
}
quadCLT_main.tp.rig_post_poles_ds = poles_ds; // Rig disparity and strength before processing poles
quadCLT_main.tp.rig_post_poles_sel = selection; // Rig tile selection before processing poles
if (debugLevel > -4) {
System.out.println("Saved quadCLT_main.tp.rig_post_poles_ds and quadCLT_main.tp.rig_post_poles_sel");
}
f_rig_disparity_strength = poles_ds;
} else {
if (debugLevel > -4) {
System.out.println("Skipped processing poles");
......@@ -1557,6 +1607,24 @@ if (debugLevel > -100) return true; // temporarily !
quadCLT_main.tp.clt_3d_passes.add(rig_scan);
quadCLT_main.tp.saveCLTPasses(true); // rig pass
// generate ML data if enabled
if (clt_parameters.rig.ml_generate) {
outputMLData(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel)
if (clt_parameters.rig.ml_copyJP4) {
copyJP4src(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
debugLevel); // final int debugLevel)
}
}
}
public double [][][][][] getRigTextures(
......@@ -1625,6 +1693,70 @@ if (debugLevel > -100) return true; // temporarily !
}
public void copyJP4src(
QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux,
EyesisCorrectionParameters.CLTParameters clt_parameters,
final int debugLevel) // throws Exception
{
// quadCLT_main.writeKml(debugLevel);
// quadCLT_main.writeRatingFile(debugLevel);
String [] sourceFiles_main=quadCLT_main.correctionsParameters.getSourcePaths();
// String [] sourceFiles_aux=quadCLT_main.correctionsParameters.getSourcePaths();
String set_name = quadCLT_main.image_name;
if (set_name == null ) {
QuadCLT.SetChannels [] set_channels=quadCLT_main.setChannels(debugLevel);
set_name = set_channels[0].set_name;
}
if (quadCLT_main.gps_lla != null) {
String kml_copy_dir= quadCLT_main.correctionsParameters.selectX3dDirectory(
set_name, // quad timestamp. Will be ignored if correctionsParameters.use_x3d_subdirs is false
null,
true, // smart,
true); //newAllowed, // save
double ts = Double.parseDouble(set_name.replace('_', '.'));
(new X3dOutput()).generateKML(
kml_copy_dir+ Prefs.getFileSeparator()+set_name+"-test"+".kml", // String path,
false, // boolean overwrite,
"", // String icon_path, //<href>x3d/1487451413_967079.x3d</href> ?
ts, // double timestamp,
quadCLT_main.gps_lla); // double [] lla)
}
// setGpsLla(quadCLT_aux, sourceFiles_aux[0]);
String jp4_copy_path= quadCLT_main.correctionsParameters.selectX3dDirectory(
set_name, // quad timestamp. Will be ignored if correctionsParameters.use_x3d_subdirs is false
quadCLT_main.correctionsParameters.jp4SubDir,
true, // smart,
true); //newAllowed, // save
File dir = (new File(jp4_copy_path)); // .getParentFile();
if (!dir.exists()){
dir.mkdirs();
System.out.println("Created "+dir);
}
for (String fname:sourceFiles_main) {
File file = new File(fname);
try {
Files.copy(
(file).toPath(),
(new File(jp4_copy_path + Prefs.getFileSeparator()+file.getName())).toPath(),
StandardCopyOption.REPLACE_EXISTING);
System.out.println("Copied "+fname+" -> "+dir);
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Failed to copy "+fname+" -> "+dir);
}
}
// System.out.println("jp4_copy_path = "+jp4_copy_path);
// System.out.println("Do something useful here");
}
public void outputMLData(
QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux,
......@@ -1633,32 +1765,28 @@ if (debugLevel > -100) return true; // temporarily !
final boolean updateStatus,
final int debugLevel) // throws Exception
{
if ((quadCLT_main.tp == null) || (quadCLT_main.tp.clt_3d_passes == null)) {
String msg = "DSI data not available. Please run \"CLT 3D\" first";
if ((quadCLT_main.tp == null) || (quadCLT_main.tp.rig_pre_poles_ds == null)) {
String msg = "DSI data not available. Please run \"Ground truth\" first";
IJ.showMessage("Error",msg);
System.out.println(msg);
return;
}
double [][] rig_disparity_strength = quadCLT_main.getGroundTruthByRig();
double [][] rig_disparity_strength = clt_parameters.rig.ml_poles?quadCLT_main.tp.rig_post_poles_ds : quadCLT_main.tp.rig_pre_poles_ds;
if (rig_disparity_strength == null) {
rig_disparity_strength = groundTruthByRig(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel-2); // final int debugLevel);
if (rig_disparity_strength != null) {
quadCLT_main.tp.rig_disparity_strength = rig_disparity_strength;
System.out.println("DSI data for the scene after poles extraction is not available. You may enable it and re-run \"Ground truth\" command or run \"Poles GT\"");
return;
}
if (debugLevel > -4) {
if (clt_parameters.rig.ml_poles) {
System.out.println("==== Generating ML data for the DSI that includes extracted vertical poles ====");
} else {
System.out.println("outputMLData(): failed to get ground truth data, aborting");
return;
System.out.println("==== Generating ML data for the DSI that DOES NOT include extracted vertical poles ====");
}
}
String ml_directory= quadCLT_main.correctionsParameters.selectMlDirectory(
true, // smart,
true); //newAllowed, // save
quadCLT_main.image_name,
true, // smart,
true); //newAllowed, // save
Correlation2d corr2d = new Correlation2d(
clt_parameters.img_dtt, // ImageDttParameters imgdtt_params,
clt_parameters.transform_size, // int transform_size,
......@@ -4354,7 +4482,7 @@ if (debugLevel > -100) return true; // temporarily !
int width = tilesX * ml_width;
int height = tilesY * ml_width;
String title = ml_title+ (use8bpp?"08":"32")+"B-"+(keep_aux?"A":"")+(keep_inter?"I":"")+(keep_hor_vert?"O":"")+(ml_keep_tbrl?"T":"")+
(keep_debug?"D":"")+"-FZ"+ml_fatzero+"-OFFS"+disp_offset;
(keep_debug?"D":"")+"-FZ"+ml_fatzero+"-OFFS"+String.format("%8.5f",disp_offset).trim();
int [] aux_indices = {
ImageDtt.ML_TOP_AUX_INDEX, // 8 - top pair 2d correlation center area (auxiliary camera)
ImageDtt.ML_BOTTOM_AUX_INDEX, // 9 - bottom pair 2d correlation center area (auxiliary camera)
......@@ -4572,10 +4700,16 @@ if (debugLevel > -100) return true; // temporarily !
if (show ) {
imp_ml.show();
}
File dir = new File(ml_directory);
if (!dir.exists()){
dir.mkdirs();
System.out.println("Created "+dir);
}
String path = ml_directory+=Prefs.getFileSeparator()+imp_ml.getTitle();
FileSaver fs=new FileSaver(imp_ml);
fs.saveAsTiff(path+".tiff");
if (debugLevel > -2) {
if (debugLevel > -4) {
System.out.println("Saved ML data to "+path+".tiff");
}
}
......
......@@ -5,7 +5,7 @@
** Copyright (C) 2017 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
**
** X3dOutput.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
......@@ -21,9 +21,15 @@
** -----------------------------------------------------------------------------**
**
*/
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.Set;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
......@@ -34,7 +40,6 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
......@@ -52,6 +57,8 @@ public class X3dOutput {
Element el_TopGroup;
public int max_line_length = 0; // 100; // 0 - no limit
public X3dOutput() {}
public X3dOutput(
EyesisCorrectionParameters.CLTParameters clt_parameters,
EyesisCorrectionParameters.CorrectionParameters correctionsParameters,
......@@ -81,15 +88,15 @@ public class X3dOutput {
x3dDoc.appendChild(el_X3d);
el_Scene = x3dDoc.createElement("Scene");
el_X3d.appendChild(el_Scene);
el_TopGroup = x3dDoc.createElement("Group");
double [][] bbox = getBBox();
el_TopGroup.setAttribute("class","GroupTop");
el_TopGroup.setAttribute("id", "GroupTop");
el_TopGroup.setAttribute("bboxCenter", String.format("%.3f %.3f %.3f ",bbox[0][0],bbox[0][1],bbox[0][2]));
el_TopGroup.setAttribute("bboxSize", String.format("%.3f %.3f %.3f ",bbox[1][0],bbox[1][1],bbox[1][2]));
el_Scene.appendChild(el_TopGroup);
CLTPass3d bgnd_pass = clt_3d_passes.get(0);
......@@ -109,7 +116,7 @@ public class X3dOutput {
}
el_Scene.appendChild(el_Bgnd);
}
public void addCluster(
String url,
String id,
......@@ -156,12 +163,12 @@ public class X3dOutput {
String sindex = sb_coord_index.toString(); // for both coordIndex and texCoordIndex
String scoord = sb_coords.toString();
String stcoord = sb_tex_coords.toString();
Element el_shape = x3dDoc.createElement("Shape");
el_Scene.appendChild(el_shape);
if (id != null) el_shape.setAttribute("id",id);
if (class_name != null) el_shape.setAttribute("class",class_name);
Element el_appearance = x3dDoc.createElement("Appearance");
el_shape.appendChild(el_appearance);
......@@ -169,17 +176,17 @@ public class X3dOutput {
Element el_material = x3dDoc.createElement("Material");
el_appearance.appendChild(el_material);
el_material.setAttribute("diffuseColor", "0.376471 0.5 0.376471");
*/
*/
Element el_imageTexture = x3dDoc.createElement("ImageTexture");
el_imageTexture.setAttribute("url",url);
el_appearance.appendChild(el_imageTexture);
Element el_IFC = x3dDoc.createElement("IndexedFaceSet");
el_IFC.setAttribute("coordIndex", sindex); // can it be reused?
el_IFC.setAttribute("texCoordIndex", sindex);
el_shape.appendChild(el_IFC);
Element el_coordinate = x3dDoc.createElement("Coordinate");
el_coordinate.setAttribute("point", scoord);
el_IFC.appendChild(el_coordinate);
......@@ -187,12 +194,12 @@ public class X3dOutput {
Element el_texCoordinate = x3dDoc.createElement("TextureCoordinate");
el_texCoordinate.setAttribute("point", stcoord);
el_IFC.appendChild(el_texCoordinate);
}
// close document, generate x3d file
public void generateX3D(String path)
{
......@@ -205,9 +212,9 @@ public class X3dOutput {
// Output to console for testing
// StreamResult result = new StreamResult(System.out);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(source, result);
System.out.println("x3d file saved to "+path);
System.out.println("x3d file is saved to "+path);
} catch (TransformerException tfe) {
tfe.printStackTrace();
......@@ -217,10 +224,162 @@ public class X3dOutput {
public double [][] getBBox() // center: x,y,z, size:x,y,z
{
double depth = geometry_correction.getZFromDisparity(clt_parameters.bgnd_range);
double depth = geometry_correction.getZFromDisparity(clt_parameters.bgnd_range);
double width = depth * geometry_correction.getFOVWidth();
double height = depth * geometry_correction.getFOVHeight();
double [][] bbox = {{0, 0, -depth/2},{width,height,depth}};
return bbox;
}
public void generateKML(
String path,
boolean overwrite,
String icon_path, //<href>x3d/1487451413_967079.x3d</href> ?
double timestamp,
double [] lla)
{
if (!overwrite) {
if (new File(path).exists()) {
System.out.println("KML file "+path+" exists, skipping KML generation");
return;
}
}
Document kmlDoc;
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
kmlDoc = docBuilder.newDocument();
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
return;
}
// root elements
Element el_kml = kmlDoc.createElement("kml");
el_kml.setAttribute("xmlns","http://earth.google.com/kml/2.2");
kmlDoc.appendChild(el_kml);
Element el_Document = addElement(kmlDoc, el_kml,"Document");
Element el_PhotoOverlay = addElement(kmlDoc, el_Document, "PhotoOverlay"); // kmlDoc.createElement("PhotoOverlay");
addTextElement(kmlDoc, el_PhotoOverlay, "name", "test");
addTextElement(kmlDoc, el_PhotoOverlay, "description", "this kml description");
addTextElement(kmlDoc, el_PhotoOverlay, "visibility", "1");
addTextElement(kmlDoc, el_PhotoOverlay, "shape", "rectangle");
Element el_TimeStamp = addElement(kmlDoc, el_PhotoOverlay, "TimeStamp");
addTextElement(kmlDoc, el_TimeStamp, "when", String.format("%f",timestamp));
Element el_Camera = addElement(kmlDoc, el_PhotoOverlay, "Camera");
addTextElement(kmlDoc, el_Camera, "latitude", String.format("%f",lla[0]));
addTextElement(kmlDoc, el_Camera, "longitude", String.format("%f",lla[1]));
addTextElement(kmlDoc, el_Camera, "altitude", String.format("%f",lla[2]));
addTextElement(kmlDoc, el_Camera, "heading", String.format("%f",0.0));
addTextElement(kmlDoc, el_Camera, "tilt", String.format("%f",90.0));
addTextElement(kmlDoc, el_Camera, "roll", String.format("%f",0.0));
if (icon_path != null) {
Element el_Icon = addElement(kmlDoc, el_PhotoOverlay, "Icon");
addTextElement(kmlDoc, el_Icon, "href", icon_path);
}
Element el_ExtendedData = addElement(kmlDoc, el_PhotoOverlay, "ExtendedData");
Element el_OriginalData = addElement(kmlDoc, el_ExtendedData, "OriginalData");
addTextElement(kmlDoc, el_OriginalData, "latitude", String.format("%f",lla[0]));
addTextElement(kmlDoc, el_OriginalData, "longitude", String.format("%f",lla[1]));
addTextElement(kmlDoc, el_OriginalData, "altitude", String.format("%f",lla[2]));
addTextElement(kmlDoc, el_OriginalData, "heading", String.format("%f",0.0));
addTextElement(kmlDoc, el_OriginalData, "tilt", String.format("%f",90.0));
addTextElement(kmlDoc, el_OriginalData, "roll", String.format("%f",0.0));
try {
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(kmlDoc);
StreamResult result = new StreamResult(new File(path));
// Output to console for testing
// StreamResult result = new StreamResult(System.out);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(source, result);
System.out.println("kml file is saved to "+path);
} catch (TransformerException tfe) {
tfe.printStackTrace();
}
try {
Path fpath = Paths.get((new File(path)).getCanonicalPath());
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(fpath);
perms.add(PosixFilePermission.OTHERS_WRITE);
Files.setPosixFilePermissions(fpath, perms);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Element addTextElement(Document doc, Element parent, String name, String text)
{
Element child = doc.createElement(name);
child.setTextContent(text);
parent.appendChild(child);
return child;
}
Element addElement(Document doc, Element parent, String name)
{
Element child = doc.createElement(name);
parent.appendChild(child);
return child;
}
}
/*
* <?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
<PhotoOverlay>
<name>test</name>
<visibility>1</visibility>
<shape>rectangle</shape>
<TimeStamp>
<when>1487451413.967079</when>
</TimeStamp>
<Camera>
<longitude>-111.93292339</longitude>
<latitude>40.72350154</latitude>
<altitude>1305.1</altitude>
<heading>68.8186</heading>
<tilt>90</tilt>
<roll>0</roll>
</Camera>
<Icon>
<href>x3d/1487451413_967079.x3d</href>
</Icon>
<ExtendedData>
<OriginalData>
<longitude>-111.9328843</longitude>
<latitude>40.7233861</latitude>
<altitude>1305.1</altitude>
<heading>65</heading>
<tilt>90</tilt>
<roll>0</roll>
</OriginalData>
</ExtendedData>
<description></description></PhotoOverlay>
</Document>
</kml>
<?xml version="1.0" encoding="UTF-8"?>
<x3d profile="Interchange" version="3.3">
<Scene>
<Group bboxCenter="0.000 0.000 -1419.899 " bboxSize="3704.001 2766.569 2839.798 " class="GroupTop" id="GroupTop"/>
*/
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