Commit dbd2a71c authored by Andrey Filippov's avatar Andrey Filippov

Fixing batch mode with new features

parent c0c2cd6a
......@@ -225,6 +225,66 @@ public class BiCamDSI {
return selection;
}
/**
* Select small/thin near objects over infinity
* @param min_strength minimal strength of the tile and neighbors
* @param min_neibs minimal number of neighbors with close disparity
* @param min_disparity minimal disaparity
* @param disp_atolerance disparity absolute tolerance (to qualify for a similar neighbor)
* @param disp_rtolerance disparity relative tolerance (adds to absolute)
* @param infinity_select tile, previously assigned to infinity (or null)
* @param selection existing selection (to add to) or null
* @param disparity array of tile disparity values (may have NaN-s)
* @param strength array of tile strength values
* @return new selection (new or added to existing)
*/
public boolean [] selectNearOverInfinity(
double min_strength,
int min_neibs,
double min_disparity,
double disp_atolerance,
double disp_rtolerance,
boolean [] infinity_select,
boolean [] selection,
double [] disparity,
double [] strength) {
int num_tiles = disparity.length;
if (infinity_select == null) {
infinity_select = new boolean [num_tiles];
for (int nTile = 0; nTile < num_tiles; nTile++) infinity_select[nTile] = true;
}
if (selection == null) selection = new boolean [num_tiles];
boolean [] new_sel = selection.clone();
//tnImage
for (int nTile =0; nTile <num_tiles; nTile++)
if ( infinity_select[nTile] &&
!selection[nTile] &&
(strength[nTile] >= min_strength ) &&
(disparity[nTile] >= min_disparity)){
int nn = 0;
double tolerance = disp_atolerance + disparity[nTile] * disp_rtolerance;
double min_d = Math.max(disparity[nTile] - tolerance, min_disparity);
double max_d = disparity[nTile] + tolerance;
for (int dir = 0; dir < 8; dir++) {
int nTile1 = tnImage.getNeibIndex(nTile, dir);
if ( (nTile1 >=0) &&
((strength [nTile1] >= min_strength ) || selection[nTile1]) && // strong or already selected
(disparity[nTile1] >= min_d) &&
(disparity[nTile1] <= max_d)){
nn++;
/// if (selection[nTile]) nn++; // count selected as 2 ?
}
}
if (nn >= min_neibs) {
new_sel[nTile] = true;
}
}
for (int nTile =0; nTile <num_tiles; nTile++) {
selection[nTile] |= new_sel[nTile];
}
return selection;
}
/**
* Select far tiles (even lone) over infinity areas that have sufficient disparity and strength
* @param min_far_strength minimal tile strength (may be 0 as the tiles are already filtered)
......
......@@ -211,6 +211,15 @@ public class BiQuadParameters {
public double ltfar_trusted_s = 0.4; // Add even single tiles over infinity if strength (and disparity too) is sufficient
public double ltfar_trusted_d = 0.2; // Add even single tiles over infinity if disparity (and strength too) is sufficient
// Parameters to select near (too near to be processed as poles) objects over infinity background
public double ltgrp_min_strength = 0.2; // Minimal strength of the tile and neighbors
public int ltgrp_min_neibs = 2; // minimal number of neighbors with close disparity
public double ltgrp_gr_min_disparity = 0.5; // Minimal group disparity
public double ltgrp_gr_disp_atolerance = 0.2; // Group disparity absolute tolerance (to qualify for a similar neighbor)
public double ltgrp_gr_disp_rtolerance = 0.1; // Group disparity relative tolerance (adds to absolute)
// rig selection filtering
......@@ -581,10 +590,22 @@ public class BiQuadParameters {
gd.addMessage("Filtering selection of non-infinity tiles");
gd.addNumericField("Add even single tiles over infinity if STRENGTH (and disparity too) is sufficient", this.ltfar_trusted_s, 4,6,"",
"Add strong tiles over infinity areas that have both strenth and disparity above respective thersholds (re-add them after filtering)");
"Add strong tiles over infinity areas that have both strenth and disparity above respective thresholds (re-add them after filtering)");
gd.addNumericField("Add even single tiles over infinity if DISPARITY (and strength too) is sufficient", this.ltfar_trusted_d, 4,6,"pix",
"Add strong tiles over infinity areas that have both strenth and disparity above respective thersholds (re-add them after filtering)");
"Add strong tiles over infinity areas that have both strenth and disparity above respective thresholds (re-add them after filtering)");
gd.addMessage("Parameters to select near (too near to be processed as poles) objects over infinity background");
gd.addNumericField("Minimal strength of the tile and neighbors", this.ltgrp_min_strength, 4,6,"",
"Tile will be added to selection if the tile over infinity selection is strong enough and has several neighbors (of 8) with similar disparity and also strong");
gd.addNumericField("Minimal number of neighbors with close disparity", this.ltgrp_min_neibs, 0,3,"tiles",
"For thin objects (poles, wires) there may be just 2 neighbors");
gd.addNumericField("Minimal group disparity", this.ltgrp_gr_min_disparity, 4,6,"pix",
"Only process tiles that are close enough (and their qualifying neighbors too)");
gd.addNumericField("Group disparity absolute tolerance (to qualify for a similar neighbor)", this.ltgrp_gr_disp_atolerance, 4,6,"pix",
"Neighbors should have disparity different by not more than this");
gd.addNumericField("Group disparity relative tolerance", this.ltgrp_gr_disp_rtolerance, 4,6,"pix/pix",
"Increase disparity tolerance by this for each absolute disparity pixel");
gd.addTab("Rig selection","Rig tile selection filter");
......@@ -814,6 +835,13 @@ public class BiQuadParameters {
this.ltfar_trusted_s= gd.getNextNumber();
this.ltfar_trusted_d= gd.getNextNumber();
this.ltgrp_min_strength= gd.getNextNumber();
this.ltgrp_min_neibs= (int) gd.getNextNumber();
this.ltgrp_gr_min_disparity= gd.getNextNumber();
this.ltgrp_gr_disp_atolerance= gd.getNextNumber();
this.ltgrp_gr_disp_rtolerance= gd.getNextNumber();
this.rf_master_infinity= gd.getNextBoolean();
this.rf_master_near= gd.getNextBoolean();
this.rf_pre_expand= (int) gd.getNextNumber();
......@@ -1013,6 +1041,13 @@ public class BiQuadParameters {
properties.setProperty(prefix+"ltfar_trusted_s", this.ltfar_trusted_s+"");
properties.setProperty(prefix+"ltfar_trusted_d", this.ltfar_trusted_d+"");
properties.setProperty(prefix+"ltgrp_min_strength", this.ltgrp_min_strength+"");
properties.setProperty(prefix+"ltgrp_min_neibs", this.ltgrp_min_neibs+"");
properties.setProperty(prefix+"ltgrp_gr_min_disparity", this.ltgrp_gr_min_disparity+"");
properties.setProperty(prefix+"ltgrp_gr_disp_atolerance", this.ltgrp_gr_disp_atolerance+"");
properties.setProperty(prefix+"ltgrp_gr_disp_rtolerance", this.ltgrp_gr_disp_rtolerance+"");
properties.setProperty(prefix+"rf_master_infinity", this.rf_master_infinity+"");
properties.setProperty(prefix+"rf_master_near", this.rf_master_near+"");
properties.setProperty(prefix+"rf_pre_expand", this.rf_pre_expand+"");
......@@ -1210,6 +1245,12 @@ public class BiQuadParameters {
if (properties.getProperty(prefix+"ltfar_trusted_s")!=null) this.ltfar_trusted_s=Double.parseDouble(properties.getProperty(prefix+"ltfar_trusted_s"));
if (properties.getProperty(prefix+"ltfar_trusted_d")!=null) this.ltfar_trusted_d=Double.parseDouble(properties.getProperty(prefix+"ltfar_trusted_d"));
if (properties.getProperty(prefix+"ltgrp_min_strength")!=null) this.ltgrp_min_strength=Double.parseDouble(properties.getProperty(prefix+"ltgrp_min_strength"));
if (properties.getProperty(prefix+"ltgrp_min_neibs")!=null) this.ltgrp_min_neibs=Integer.parseInt(properties.getProperty(prefix+"ltgrp_min_neibs"));
if (properties.getProperty(prefix+"ltgrp_gr_min_disparity")!=null) this.ltgrp_gr_min_disparity=Double.parseDouble(properties.getProperty(prefix+"ltgrp_gr_min_disparity"));
if (properties.getProperty(prefix+"ltgrp_gr_disp_atolerance")!=null)this.ltgrp_gr_disp_atolerance=Double.parseDouble(properties.getProperty(prefix+"ltgrp_gr_disp_atolerance"));
if (properties.getProperty(prefix+"ltgrp_gr_disp_rtolerance")!=null)this.ltgrp_gr_disp_rtolerance=Double.parseDouble(properties.getProperty(prefix+"ltgrp_gr_disp_rtolerance"));
if (properties.getProperty(prefix+"rf_master_infinity")!=null) this.rf_master_infinity=Boolean.parseBoolean(properties.getProperty(prefix+"rf_master_infinity"));
if (properties.getProperty(prefix+"rf_master_near")!=null) this.rf_master_near=Boolean.parseBoolean(properties.getProperty(prefix+"rf_master_near"));
if (properties.getProperty(prefix+"rf_pre_expand")!=null) this.rf_pre_expand=Integer.parseInt(properties.getProperty(prefix+"rf_pre_expand"));
......@@ -1408,6 +1449,12 @@ public class BiQuadParameters {
bqp.ltfar_trusted_s= this.ltfar_trusted_s;
bqp.ltfar_trusted_d= this.ltfar_trusted_d;
bqp.ltgrp_min_strength = this.ltgrp_min_strength;
bqp.ltgrp_min_neibs = this.ltgrp_min_neibs;
bqp.ltgrp_gr_min_disparity = this.ltgrp_gr_min_disparity;
bqp.ltgrp_gr_disp_atolerance = this.ltgrp_gr_disp_atolerance;
bqp.ltgrp_gr_disp_rtolerance = this.ltgrp_gr_disp_rtolerance;
bqp.rf_master_infinity= this.rf_master_infinity;
bqp.rf_master_near= this.rf_master_near;
bqp.rf_pre_expand= this.rf_pre_expand;
......
......@@ -135,6 +135,12 @@ public class EyesisCorrectionParameters {
public boolean clt_batch_assign = true; // Assign tiles to surfaces
public boolean clt_batch_gen3d = true; // Generate 3d output: x3d and/or obj+mtl
public boolean clt_batch_dbg1 = true; // Generate debug images if a single set is selected
public boolean clt_batch_dsi = true; // Create and save DSI combo image with the model
public boolean clt_batch_dsi_aux = false; // Calculate and save aux camera DSI (currently it is offset from the main/rig data
public boolean clt_batch_save_extrinsics = true; // Save cameras extrinsic parameters with the model
public boolean clt_batch_save_all = true; // Save all parameters with the model
public String x3dModelVersion="v01";
public String jp4SubDir="jp4";
......@@ -263,6 +269,11 @@ public class EyesisCorrectionParameters {
cp.clt_batch_assign= this.clt_batch_assign;
cp.clt_batch_gen3d= this.clt_batch_gen3d;
cp.clt_batch_dbg1= this.clt_batch_dbg1;
cp.clt_batch_dsi= this.clt_batch_dsi;
cp.clt_batch_dsi_aux= this.clt_batch_dsi_aux;
cp.clt_batch_save_extrinsics= this.clt_batch_save_extrinsics;
cp.clt_batch_save_all= this.clt_batch_save_all;
}
......@@ -413,6 +424,11 @@ public class EyesisCorrectionParameters {
properties.setProperty(prefix+"clt_batch_gen3d", this.clt_batch_gen3d+"");
properties.setProperty(prefix+"clt_batch_dbg1", this.clt_batch_dbg1+"");
properties.setProperty(prefix+"clt_batch_dsi", this.clt_batch_dsi+"");
properties.setProperty(prefix+"clt_batch_dsi_aux", this.clt_batch_dsi_aux+"");
properties.setProperty(prefix+"clt_batch_save_extrinsics", this.clt_batch_save_extrinsics+"");
properties.setProperty(prefix+"clt_batch_save_all", this.clt_batch_save_all+"");
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+"");
......@@ -557,6 +573,11 @@ 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+"clt_batch_dsi")!= null) this.clt_batch_dsi=Boolean.parseBoolean(properties.getProperty(prefix+"clt_batch_dsi"));
if (properties.getProperty(prefix+"clt_batch_dsi_aux")!= null) this.clt_batch_dsi_aux=Boolean.parseBoolean(properties.getProperty(prefix+"clt_batch_dsi_aux"));
if (properties.getProperty(prefix+"clt_batch_save_extrinsics")!= null) this.clt_batch_save_extrinsics=Boolean.parseBoolean(properties.getProperty(prefix+"clt_batch_save_extrinsics"));
if (properties.getProperty(prefix+"clt_batch_save_all")!= null) this.clt_batch_save_all=Boolean.parseBoolean(properties.getProperty(prefix+"clt_batch_save_all"));
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"));
......@@ -899,6 +920,18 @@ public class EyesisCorrectionParameters {
gd.addCheckbox ("Assign tiles to surfaces", this.clt_batch_assign); // 27
gd.addCheckbox ("Generate 3d output: x3d and/or obj+mtl", this.clt_batch_gen3d); // 28
gd.addCheckbox ("Generate debug images if a single set is selected", this.clt_batch_dbg1); // 29
gd.addCheckbox ("Create DSI combo image", this.clt_batch_dsi,
"Save main camera, dual-quad rig and optionally aux camera combo DSI image with the model");
gd.addCheckbox ("Include aux camera DSI data in the combo DSI", this.clt_batch_dsi_aux,
"Currently DSI for the AUX camera is offset (by the rig baseline) from the main and rig DSI. Aux DSI requires extra processing time");
gd.addCheckbox ("Save field adjustment data with the model", this.clt_batch_save_extrinsics,
"This data can be used to restore specific filed-adjusted cameras extrinsics used when the model was generated");
gd.addCheckbox ("Save all parameters with the model", this.clt_batch_save_all,
"Save a copy of all parameters with the model");
if (clt_parameters != null) {
// gd.addMessage ("============ selected CLT parameters ============");
gd.addTab ("CLT", "Modify selected CLT parameters");
......@@ -968,6 +1001,10 @@ public class EyesisCorrectionParameters {
this.clt_batch_assign= gd.getNextBoolean(); // 27
this.clt_batch_gen3d= gd.getNextBoolean(); // 28
this.clt_batch_dbg1= gd.getNextBoolean(); // 29
this.clt_batch_dsi= gd.getNextBoolean();
this.clt_batch_dsi_aux= gd.getNextBoolean();
this.clt_batch_save_extrinsics= gd.getNextBoolean();
this.clt_batch_save_all= gd.getNextBoolean();
if (clt_parameters != null) {
clt_parameters.grow_disp_max = gd.getNextNumber();
clt_parameters.gain_equalize = gd.getNextBoolean();
......
......@@ -588,6 +588,8 @@ private Panel panel1,
addButton("MAIN extrinsics", panelClt4, color_process);
addButton("AUX extrinsics", panelClt4, color_process);
addButton("RIG extrinsics", panelClt4, color_conf_process);
addButton("SAVE extrinsics", panelClt4,color_process); //, "Save configuration");
addButton("Rig8 images", panelClt4, color_conf_process);
// addButton("Rig enhance", panelClt4, color_conf_process);
......@@ -598,6 +600,7 @@ private Panel panel1,
addButton("Poles GT", panelClt4, color_process);
addButton("ML export", panelClt4, color_conf_process);
addButton("JP4 copy", panelClt4, color_conf_process);
addButton("DSI show", panelClt4, color_process);
addButton("Rig batch", panelClt4, color_process);
......@@ -4366,12 +4369,12 @@ private Panel panel1,
if (!CLT_PARAMETERS.showTsDialog()) return;
boolean OK = QUAD_CLT.assignCLTPlanes(
double [][] assign_dbg = QUAD_CLT.assignCLTPlanes(
CLT_PARAMETERS, // EyesisCorrectionParameters.DCTParameters dct_parameters,
THREADS_MAX, //final int threadsMax, // maximal number of threads to launch
UPDATE_STATUS, //final boolean updateStatus,
DEBUG_LEVEL); //final int debugLevel);
if (!OK){
if (assign_dbg == null){
System.out.println("Could not assign tiles to surfaces, probably \"CLT planes\" command did not run");
return;
}
......@@ -4506,6 +4509,11 @@ private Panel panel1,
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
infinityRig();
return;
/* ======================================================================== */
} else if (label.equals("SAVE extrinsics")) {
saveExtrinsics();
return;
/* ======================================================================== */
} else if (label.equals("SHOW extrinsics")) {
if (QUAD_CLT == null){
......@@ -4617,6 +4625,11 @@ private Panel panel1,
}
QUAD_CLT_AUX.editRig();
return;
/* ======================================================================== */
} else if (label.equals("DSI show")) {
showDSI();
return;
//JTabbedTest
// End of buttons code
}
......@@ -5009,7 +5022,7 @@ private Panel panel1,
public boolean rigPlanes() {
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null)) {
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null) || (QUAD_CLT.tp.clt_3d_passes.size() == 0)) {
String msg = "DSI data is not available. Please run \"CLT 3D\" first";
IJ.showMessage("Error",msg);
System.out.println(msg);
......@@ -5259,7 +5272,7 @@ private Panel panel1,
public boolean groundTruth() {
long startTime=System.nanoTime();
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null)) {
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null) || (QUAD_CLT.tp.clt_3d_passes.size() == 0)) {
boolean OK = clt3d(
false, // boolean adjust_extrinsics,
false); // boolean adjust_poly);
......@@ -5300,7 +5313,7 @@ private Panel panel1,
public boolean rigDSI() {
long startTime=System.nanoTime();
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null)) {
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null) || (QUAD_CLT.tp.clt_3d_passes.size() == 0)) {
boolean OK = clt3d(
false, // boolean adjust_extrinsics,
false); // boolean adjust_poly);
......@@ -5347,7 +5360,7 @@ private Panel panel1,
public boolean batchRig() {
long startTime=System.nanoTime();
/* if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null)) {
/* if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null) || (QUAD_CLT.tp.clt_3d_passes.size() == 0)) {
boolean OK = clt3d(
false, // boolean adjust_extrinsics,
......@@ -5364,6 +5377,7 @@ private Panel panel1,
if (!prepareRigImages()) return false;
String configPath=getSaveCongigPath();
if (configPath.equals("ABORT")) return false;
setAllProperties(PROPERTIES); // batchRig may save properties with the model. Extrinsics will be updated, others should be set here
if (DEBUG_LEVEL > -2){
System.out.println("++++++++++++++ Running batch processing of dual-quad camera rig ++++++++++++++");
}
......@@ -5377,6 +5391,7 @@ private Panel panel1,
CHANNEL_GAINS_PARAMETERS, //CorrectionColorProc.ColorGainsParameters channelGainParameters,
RGB_PARAMETERS, //EyesisCorrectionParameters.RGBParameters rgbParameters,
EQUIRECTANGULAR_PARAMETERS, // EyesisCorrectionParameters.EquirectangularParameters equirectangularParameters,
PROPERTIES, // Properties properties,
THREADS_MAX, //final int threadsMax, // maximal number of threads to launch
UPDATE_STATUS, //final boolean updateStatus,
DEBUG_LEVEL);
......@@ -5528,7 +5543,32 @@ private Panel panel1,
return true;
}
public boolean saveExtrinsics() {
String [] patterns= {".corr-xml",".xml"};
String path= selectFile(true, // save
"Save configuration selection", // title
"Select configuration file", // button
new MultipleExtensionsFileFilter(patterns, "XML Configuration files (*.corr-xml)"), // filter
CORRECTION_PARAMETERS.resultsDirectory); // may be ""
if (path==null) return false;
if (TWO_QUAD_CLT == null) {
return false;
}
TWO_QUAD_CLT.saveProperties(
path, // String path, // full name with extension or w/o path to use x3d directory
null, // Properties properties, // if null - will only save extrinsics)
DEBUG_LEVEL); // int debugLevel)
return true;
}
public boolean showDSI() {
if (TWO_QUAD_CLT == null) {
System.out.println("TWO_QUAD_CLT is not initialized");
return false;
}
TWO_QUAD_CLT.showDSI();
return true;
}
public boolean infinityRig() {
if (!prepareRigImages()) return false;
......@@ -6725,8 +6765,6 @@ private Panel panel1,
}
/* ======================================================================== */
public void setAllProperties(Properties properties){
// QuadCLT qc = QUAD_CLT;
// QuadCLT aqc = QUAD_CLT_AUX;
properties.setProperty("MASTER_DEBUG_LEVEL",MASTER_DEBUG_LEVEL+"");
properties.setProperty("UPDATE_STATUS", UPDATE_STATUS+ "");
SPLIT_PARAMETERS.setProperties("SPLIT_PARAMETERS.", properties);
......@@ -6735,9 +6773,7 @@ private Panel panel1,
DEBAYER_PARAMETERS.setProperties("DEBAYER_PARAMETERS.", properties);
NONLIN_PARAMETERS.setProperties("NONLIN_PARAMETERS.", properties); // keep for Eyesis, not used fro Quad CLT
COLOR_PROC_PARAMETERS.setProperties("COLOR_PROC_PARAMETERS.", properties);
// COLOR_CALIB_PARAMETERS.setProperties("COLOR_CALIB_PARAMETERS.", properties);
RGB_PARAMETERS.setProperties("RGB_PARAMETERS.", properties);
// FILE_PARAMETERS.setProperties("FILE_PARAMETERS.", properties);
PROCESS_PARAMETERS.setProperties("PROCESS_PARAMETERS.", properties);
CORRECTION_PARAMETERS.setProperties("CORRECTION_PARAMETERS.", properties);
CHANNEL_GAINS_PARAMETERS.setProperties("CHANNEL_GAINS_PARAMETERS.", properties);
......@@ -6750,8 +6786,8 @@ private Panel panel1,
properties.setProperty("THREADS_MAX",THREADS_MAX+""); // 100, testing multi-threading, limit maximal number of threads
properties.setProperty("GAUSS_WIDTH",GAUSS_WIDTH+""); // 0.4 (0 - use Hamming window)
properties.setProperty("PSF_SUBPIXEL_SHOULD_BE_4",PSF_SUBPIXEL_SHOULD_BE_4+""); // 4, sub-pixel decimation
if (QUAD_CLT != null) QUAD_CLT.setProperties(QuadCLT.PREFIX);
if (QUAD_CLT_AUX != null) QUAD_CLT_AUX.setProperties(QuadCLT.PREFIX_AUX);
if (QUAD_CLT != null) QUAD_CLT.setProperties(QuadCLT.PREFIX, null);
if (QUAD_CLT_AUX != null) QUAD_CLT_AUX.setProperties(QuadCLT.PREFIX_AUX, null);
}
/* ======================================================================== */
public void getAllProperties(Properties properties){
......@@ -6763,7 +6799,6 @@ private Panel panel1,
DEBAYER_PARAMETERS.getProperties("DEBAYER_PARAMETERS.", properties);
NONLIN_PARAMETERS.getProperties("NONLIN_PARAMETERS.", properties); // keep for Eyesis, not used fro Quad CLT
COLOR_PROC_PARAMETERS.getProperties("COLOR_PROC_PARAMETERS.", properties);
// COLOR_CALIB_PARAMETERS.getProperties("COLOR_CALIB_PARAMETERS.", properties);
RGB_PARAMETERS.getProperties("RGB_PARAMETERS.", properties);
PROCESS_PARAMETERS.getProperties("PROCESS_PARAMETERS.", properties);
CORRECTION_PARAMETERS.getProperties("CORRECTION_PARAMETERS.", properties);
......
......@@ -926,7 +926,12 @@ public class LinkPlanes {
this_plane.initMergedValue(dir,other_planes.length); // filled with NaN
for (int np = 0; np < other_planes.length; np ++){
if (other_planes[np] != null) {
TilePlanes.PlaneData other_plane = this_plane.getPlaneToThis(
if (nsTile0 == 790) {
System.out.println("?LinkPlanes.matchPlanes() DEBUG1:");
System.out.println("?LinkPlanes.matchPlanes() DEBUG1:");
}
TilePlanes.PlaneData other_plane = this_plane.getPlaneToThis( // returns NaN with FRONTO
other_planes[np],
dl - 2); // debugLevel);
if (other_plane !=null) { // now always, but may add later
......
......@@ -203,7 +203,10 @@ public class QuadCLT {
// public void setProperties(){
// setProperties(this.properties_prefix);
// }
public void setProperties(String prefix){ // save
public void setProperties(String prefix, Properties properties){ // save
if (properties == null) {
properties = this.properties;
}
// System.out.println("setProperties("+prefix+")");
for (int n = 0; n < fine_corr.length; n++){
for (int d = 0; d < fine_corr[n].length; d++){
......@@ -5610,7 +5613,7 @@ public class QuadCLT {
IJ.d2s(0.000000001*(System.nanoTime()-this.startStepTime),3)+" sec, --- Free memory="+Runtime.getRuntime().freeMemory()+" (of "+Runtime.getRuntime().totalMemory()+")");
}
public boolean assignCLTPlanes(
public double [][] assignCLTPlanes(
EyesisCorrectionParameters.CLTParameters clt_parameters,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
......@@ -5618,14 +5621,14 @@ public class QuadCLT {
{
if (tp == null){
System.out.println("showCLTPlanes(): tp is null");
return false;
return null;
}
if (tp.clt_3d_passes == null){
System.out.println("showCLTPlanes(): tp.clt_3d_passes is null");
return false;
return null;
}
this.startStepTime=System.nanoTime();
boolean ok = tp.assignTilesToSurfaces(
double [][] assign_dbg = tp.assignTilesToSurfaces(
clt_parameters,
geometryCorrection,
threadsMax,
......@@ -5635,7 +5638,7 @@ public class QuadCLT {
Runtime.getRuntime().gc();
System.out.println("assignCLTPlanes(): processing finished at "+
IJ.d2s(0.000000001*(System.nanoTime()-this.startStepTime),3)+" sec, --- Free memory="+Runtime.getRuntime().freeMemory()+" (of "+Runtime.getRuntime().totalMemory()+")");
return ok;
return assign_dbg;
}
......@@ -9199,13 +9202,13 @@ public class QuadCLT {
} else continue; // if (correctionsParameters.clt_batch_surf)
if (correctionsParameters.clt_batch_assign) {
boolean ok = tp.assignTilesToSurfaces(
double [][] assign_dbg = tp.assignTilesToSurfaces(
clt_parameters,
geometryCorrection,
threadsMax,
updateStatus,
debugLevelInner);
if (!ok) continue;
if (assign_dbg == null) continue;
} else continue; // if (correctionsParameters.clt_batch_assign)
if (correctionsParameters.clt_batch_gen3d) {
......
......@@ -1818,7 +1818,12 @@ public class SuperTiles{
}
sel_list.add(new Selections2(new_sel));
}
if (sel_list.isEmpty()) {
if (dl > 2){
System.out.println("dispClusterizeHighest(): nsTile="+nsTile+": nothing found");
}
continue;
}
plane_selections[nsTile] = new boolean [sel_list.size()][][]; //plane_sels;
for (int np = 0; np < plane_selections[nsTile].length; np++) {
plane_selections[nsTile][np] = sel_list.get(np).getSel();
......@@ -2546,6 +2551,8 @@ public class SuperTiles{
final int dbg_X,
final int dbg_Y)
{
// TODO: Make a configurable parameters (0 should also work)
final int min_fresh_used = 1; // minimal number of new tiles not already used by the other direction (hor/vert)
final int tilesX = tileProcessor.getTilesX();
final int tilesY = tileProcessor.getTilesY();
......@@ -2816,6 +2823,7 @@ public class SuperTiles{
new_planes_selections[np] = planes_selections[nsTile][np];
new_plane_types[np] = hor_planes[nsTile][np];
}
int planes_added = 0;
for (int nnp = 0; nnp < num_planes; nnp++) { // SelStrength ss:selStrengthList){
SelStrength ss = selStrengthList.get(nnp);
new_plane_types[np] = ss.type != 0; // 0 - vert, 1 - hor;
......@@ -2831,6 +2839,27 @@ public class SuperTiles{
// Filling small gaps in new selections before marking them as "used"
boolean [] used_before = (ss.type == 0) ? used_vert[nsTile][ml] : used_hor[nsTile][ml];
boolean [] this_used = sels_all[ss.type][ss.indx][ml].clone();
// See how many really new tiles has this_used;
int num_really_new = 0;
for (int i = 0; i < num_tiles; i++) if (this_used[i] && !used_vert[nsTile][ml][i] && !used_hor[nsTile][ml][i]) {
num_really_new++;
}
// see if is enough
if (num_really_new < min_fresh_used) {
for (int i = 0; i < num_tiles; i++){
used_before[i] |= this_used[i]; // Still mark them as used on this orientation
}
this_used = new boolean[this_used.length]; // unselect all
if (dl > 1){
System.out.println("initialDiscriminateTiles():"+nsTile+" selection does not provide enough previously unused tiles");
}
// disable these tiles in this orientation used
} else {
planes_added++;
}
boolean [] this_used_expanded = this_used.clone();
tnStile.growSelection(
2,
......@@ -2882,6 +2911,13 @@ public class SuperTiles{
}
np++;
}
if (planes_added == 0) {
if (dl > 1){
System.out.println("initialDiscriminateTiles():"+nsTile+": No new planes added");
}
continue;
}
planes_selections[nsTile] = new_planes_selections;
hor_planes[nsTile] = new_plane_types;
if (dl > 2){
......@@ -3456,7 +3492,7 @@ public class SuperTiles{
plFrontoOffs, // final double plFrontoOffs, // increasing weight of the near tiles by using difference between the reduced average as weight. <= 0 - disable
PlFrontoPow, // double fronto_pow, // = 1.0; // increase weight even more
hor_planes, // final boolean [][] hor_planes, // returns plane types (hor/vert)
debugLevel + 0, // 1, // 0, // 1, // + 2, // 1, // final int debugLevel,
debugLevel+(debug_initial_discriminate? 3:0), // 1, // 0, // 1, // + 2, // 1, // final int debugLevel,
dbg_X, // final int dbg_X,
dbg_Y); // final int dbg_Y)
this.planes = new_planes; // save as "measured" (as opposed to "smoothed" by neighbors) planes
......
/**
**
** TileAssignment - handle tile surfaces
**
** Copyright (C) 2017 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** TileAssignment.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
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
import java.awt.Point;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
//import ij.IJ;
public class TileAssignment {
private TileSurface ts;
private CLTPass3d p3d; // last/ combined FPGA data
private EyesisCorrectionParameters.CLTParameters clt_parameters;
private double [][][] dispStrength; // indexed as a surface (full supertiles), not as image
private boolean [] valid_ml;
private double [][] tile_tones;
private double [][][] tone_diff_weight; // for each surface (not image) tile, for each of 8 directions,
//a pair of normalized tone difference and weight (both weight and diff == 0.0 for connections to/from undefined tiles
private double kR = 1.0; // relative weight of red to green ratio
private double kB = 1.0; // relative weight of blue to green ratio
private double fatZero = 0.01; // for colors, normalized to 0..1.0 range
private int surfTilesX;
private int surfTilesY;
private int imgTilesX;
private int imgTilesY;
private TileNeibs tnImage;
private TileNeibs tnSurface;
private boolean [][][] valid_surf; // per measured layer, per surface tile, per surface layer
// from clt_parameters
private double dispNorm;
private TACosts cost_coeff;
private double minFgBg; // = 0.1; // Minimal foreground/ background separation to look for weak FG edge
private double minFgEdge; // = 0.2; // Minimal foreground edge strength (stronger edges will have proportionally smaller costs)
private double minColSep; // = 0.05; // Minimal surface separation that requires color change
private double minColDiff; // = 0.01; // Minimal color variation (larger proportionally reduces cost)
private double dispOutlier; // = 1.0; // Disparity difference limit (to handle outliers)
private double strengthDiffPwr; // = 0.25; // Strength power when calculating disparity error
private double strengthBestPwr; // = 0.0; // Strength power when calculating disparity error over best
private double strengthDiff9Pwr; // = 0.5; // Strength power when calculating disparity error for group of 9
private double taColSigma; // = 1.5; // Gaussian sigma to blur color difference between tiles along each direction
private double taColFraction; // = 0.3; // Relative amount of the blurred color difference in the mixture
private double shrinkWeakFgnd = 0.5; // 0.5; //reduce cost of multiple weak_fgnd links of the same tile
private double shrinkColor = 0.5; // 0.0; //reduce cost of surface transitions w/o color change
static double [] NEIB_WEIGHTS = {0.5,0.25, 0.5, 0.25, 0.5,0.25, 0.5, 0.25, 1.0};
static int INDEX_R = 0;
static int INDEX_B = 1;
static int INDEX_G = 2;
static int INDEX_A = 3;
public boolean mutual_weak_fgnd = false; // set to true when using 3x3 grid, false for 5x5;
public class TACosts{
public double empty; // Cost of a tile that is not assigned
public double nolink; // Cost of a tile not having any neighbor in particular direction
public double swtch; // Cost of a tile switching to a neighbor that does not have a link
public double color; // Cost of a tile switching to a disconnected neighbor divided by a color mismatch
public double diff; // Cost of a weighted normalized tile disparity error
public double diff_best; // Cost of a weighted normalized tile disparity error above best surface
public double diff9; // Cost of a weighted normalized tile disparity error for tile and 8 neighbors (DC)
public double weak_fgnd; // Cost of a weak foreground edge
public double flaps; // Cost of using supertile "flaps" (not in the center 8x8 tiles area)
public double ml_mismatch; // Cost of a measurement layer not having same layer in the same location or near
public TACosts (int mode)
{
this.empty = 1.0/0.35833; // 0.71715;
this.nolink = 1.0/0.83739; // 0.95952; // 1.50705;
this.swtch = 1.0/0.07604; // 0.05172; // 0.59474;
this.color = 1.0/6.69936; // 3.34968; // 0.21458; // 0.19294; // 2.25763;
this.diff = 1.0/0.11879; // 0.11039; // 1.94213;
this.diff_best = 1.0/0.02831; // 0.00628; // 0.06731;
this.diff9 = 1.0/0.04064; // 0.01350; // 1.09087;
this.weak_fgnd = 1.0/2.355492; // 1.177746; // 0.02172; // 0.01726; // 0.22250;
this.flaps = 1.0/0.1; // 0.00056; // 0.07229;
this.ml_mismatch = 1.0;
// ml_mismatch not yet implemented - is it needed - maybe some see-through data appears on one layer only
}
/*
empty= 0.00000 nolink= 1.50705 swtch= 0.59474 color= 2.25763 diff= 1.94213
diff_best= 0.06731 diff9= 1.09087 weak_fgnd= 0.22250 flaps= 0.07229 ml_mismatch= 0.00000
*/
public TACosts (EyesisCorrectionParameters.CLTParameters clt_parameters)
{
this.empty = clt_parameters.taEnEmpty? clt_parameters.taCostEmpty : 0.0;
this.nolink = clt_parameters.taEnNoLink? clt_parameters.taCostNoLink : 0.0;
this.swtch = clt_parameters.taEnSwitch? clt_parameters.taCostSwitch : 0.0;
this.color = clt_parameters.taEnColor? clt_parameters.taCostColor : 0.0;
this.diff = clt_parameters.taEnDiff? clt_parameters.taCostDiff : 0.0;
this.diff_best = clt_parameters.taEnDiffBest? clt_parameters.taCostDiffBest : 0.0;
this.diff9 = clt_parameters.taEnDiff9? clt_parameters.taCostDiff9 : 0.0;
this.weak_fgnd = clt_parameters.taEnWeakFgnd? clt_parameters.taCostWeakFgnd : 0.0;
this.flaps = clt_parameters.taEnFlaps? clt_parameters.taCostFlaps : 0.0;
this.ml_mismatch = clt_parameters.taEnMismatch? clt_parameters.taCostMismatch : 0.0;
// ml_mismatch not yet implemented - is it needed - maybe some see-through data appears on one layer only
}
public TACosts(){}
public TACosts(double [] vals)
{
set(vals);
}
public void set(double [] vals)
{
this.empty = vals[0];
this.nolink = vals[1];
this.swtch = vals[2];
this.color = vals[3];
this.diff = vals[4];
this.diff_best = vals[5];
this.diff9 = vals[6];
this.weak_fgnd = vals[7];
this.flaps = vals[8];
this.ml_mismatch = vals[9];
}
public double [] toArray(){
double [] rslt = {
this.empty,
this.nolink,
this.swtch,
this.color,
this.diff,
this.diff_best,
this.diff9,
this.weak_fgnd,
this.flaps,
this.ml_mismatch
};
return rslt;
}
public String [] getTitles()
{
String [] titles = {
"empty",
"nolink",
"swtch",
"color",
"diff",
"diff_best",
"diff9",
"weak_fgnd",
"flaps",
"ml_mismatch"};
return titles;
}
@Override
public String toString()
{
String s = "";
s+= String.format("empty= %8.5f nolink=%8.5f swtch= %8.5f color=%8.5f diff= %8.5f\n",empty, nolink, swtch, color, diff);
s+= String.format("diff_best=%8.5f diff9= %8.5f weak_fgnd=%8.5f flaps=%8.5f ml_mismatch=%8.5f\n",diff_best, diff9, weak_fgnd, flaps, ml_mismatch);
return s;
}
public double dotProd (TACosts costs){
double [] these = toArray();
double [] other = costs.toArray();
double prod = 0.0;
for (int i = 0; i < these.length; i++){
prod += these[i]*other[i];
}
return prod;
}
public void add (TACosts costs){
double [] these = toArray();
double [] other = costs.toArray();
for (int i = 0; i < these.length; i++){
these[i] += other[i];
}
set (these);
}
public void mul (TACosts costs){
double [] these = toArray();
double [] other = costs.toArray();
for (int i = 0; i < these.length; i++){
these[i] *= other[i];
}
set (these);
}
public void max (TACosts costs){
double [] these = toArray();
double [] other = costs.toArray();
for (int i = 0; i < these.length; i++){
these[i] = Math.max(these[i],other[i]);
}
set (these);
}
public void scale (double a){
double [] these = toArray();
for (int i = 0; i < these.length; i++){
these[i] *= a;
}
set (these);
}
}
/**
*
* @param ts
* @param p3d
* @param tile_sel
* @param dispStrength per measurement layer, combined disparity and strength array ([num_ml [2][])
* @param kR
* @param kB
* @param fatZero
*/
public TileAssignment (
EyesisCorrectionParameters.CLTParameters clt_parameters,
TileSurface ts,
CLTPass3d p3d,
double [][][] dispStrength,
double kR,
double kB,
double fatZero)
{
this.ts = ts;
this.p3d = p3d;
copyParams(clt_parameters);
this.clt_parameters = clt_parameters; // replace with copying specific ones
valid_ml = new boolean [dispStrength.length];
for (int ml = 0; ml < dispStrength.length; ml++){
valid_ml[ml] = dispStrength[ml] != null;
}
if (!Double.isNaN(kR)) this.kR = kR;
if (!Double.isNaN(kB)) this.kB = kB;
if (!Double.isNaN(fatZero)) this.fatZero = fatZero;
this.surfTilesX = ts.getSTilesX() * ts.getSuperTileSize();
this.surfTilesY = ts.getSTilesY() * ts.getSuperTileSize();
this.imgTilesX = ts.getImageTilesX();
this.imgTilesY = ts.getImageTilesY();
this.tnImage = new TileNeibs(imgTilesX, imgTilesY);
this.tnSurface = new TileNeibs(surfTilesX, surfTilesY);
setDispStrength(dispStrength);
setTones(p3d);
}
public void copyParams(EyesisCorrectionParameters.CLTParameters clt_parameters)
{
this.dispNorm = clt_parameters.plDispNorm;
this.minFgBg = clt_parameters.taMinFgBg;
this.minFgEdge = clt_parameters.taMinFgEdge;
this.minColSep = clt_parameters.taMinColSep;
this.minColDiff = clt_parameters.taMinColDiff;
this.dispOutlier = clt_parameters.taOutlier;
this.strengthDiffPwr = clt_parameters.taDiffPwr;
this.strengthBestPwr = clt_parameters.taBestPwr;
this.strengthDiff9Pwr = clt_parameters.taDiff9Pwr;
this.taColSigma = clt_parameters.taColSigma;
this.taColFraction = clt_parameters.taColFraction;
this.cost_coeff = new TACosts (clt_parameters);
this.cost_coeff.mul(new TACosts (0)); // make average ~=1.0 for each used component
}
public void setDispStrength(
double [][][] ds)
{
this.dispStrength = new double [ds.length][][];
for (int ml = 0; ml < ds.length; ml++) if (ds[ml] != null){
this.dispStrength[ml] = new double [ surfTilesX * surfTilesY][];
for (int nTile = 0; nTile < ds[ml][0].length; nTile++){
int nSurfTile = ts.getSurfaceTileIndex(nTile);
this.dispStrength[ml][nSurfTile] = new double[2]; // ds[ml][nTile];
this.dispStrength[ml][nSurfTile][0] = ds[ml][0][nTile];
this.dispStrength[ml][nSurfTile][1] = ds[ml][1][nTile];
}
}
}
public int getSurfTilesX(){
return surfTilesX;
}
public int getSurfTilesY(){
return surfTilesY;
}
// private int surfTilesX;
// private int surfTilesY;
public void setTones(CLTPass3d p3d)
{
double [][] tt = p3d.getTileRBGA(4);
this.tile_tones = new double [surfTilesX * surfTilesY][tt.length];
for (int nTile = 0; nTile < tt[0].length; nTile++){
int nSurfTile = ts.getSurfaceTileIndex(nTile);
for (int j = 0; j < tt.length; j++){
this.tile_tones[nSurfTile][j] = tt[j][nTile];
}
}
this.tone_diff_weight = new double [surfTilesX * surfTilesY][8][2];
// final int numTiles = imgTilesX * imgTilesY;
final Thread[] threads = ImageDtt.newThreadArray(ts.getThreadsMax());
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nSurfTile = ai.getAndIncrement(); nSurfTile < tone_diff_weight.length; nSurfTile = ai.getAndIncrement()) {
if (nSurfTile >= 0){
for (int dir = 0; dir < 4; dir++){
int nSurfTile1 = tnSurface.getNeibIndex(nSurfTile, dir);
if (nSurfTile1 >= 0){
tone_diff_weight[nSurfTile][dir] =
getDiffWeight (
tile_tones[nSurfTile],
tile_tones[nSurfTile1]);
tone_diff_weight[nSurfTile1][(dir + 4) % 8] = tone_diff_weight[nSurfTile][dir];
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
public void blurMixTones(
final boolean use_sqrt,
final boolean weighted) // blur weighted
{
this.tone_diff_weight = blurMixTones(
this.tone_diff_weight, // final double [][][] tone_diffs,
this.taColSigma, // final double sigma,
this.taColFraction, // final double fraction,
use_sqrt,
weighted); // final boolean weighted)
}
public double [][][] blurMixTones(
final double [][][] tone_diffs,
final double sigma,
final double fraction,
final boolean use_sqrt,
final boolean weighted) // blur weighted
{
final int num_tiles = surfTilesX * surfTilesY;
final double [][] dir_blur = new double [4][num_tiles];
final double [][] dir_weight = new double [4][num_tiles];
final Thread[] threads = ImageDtt.newThreadArray(ts.getThreadsMax());
final AtomicInteger ai = new AtomicInteger(0);
final double [][][] mixed_diff_weight = new double [surfTilesX * surfTilesY][8][2];
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int dir = ai.getAndIncrement(); dir < 4; dir = ai.getAndIncrement()) {
for (int nSurfTile = 0; nSurfTile < num_tiles; nSurfTile++){
double w = tone_diffs[nSurfTile][dir][1];
double dw = tone_diffs[nSurfTile][dir][0] ;
if (use_sqrt) dw = Math.sqrt(dw);
if (weighted) dw *= w;
dir_blur[dir][nSurfTile] = dw;
dir_weight[dir][nSurfTile] = w;
}
DoubleGaussianBlur gb =new DoubleGaussianBlur();
gb.blurDouble(dir_blur[dir], surfTilesX, surfTilesY, sigma, sigma, 0.01);
gb.blurDouble(dir_weight[dir], surfTilesX, surfTilesY, sigma, sigma, 0.01);
if (weighted){
for (int nSurfTile = 0; nSurfTile < num_tiles; nSurfTile++){
if (dir_weight[dir][nSurfTile] != 0.0) dir_blur[dir][nSurfTile] /= dir_weight[dir][nSurfTile];
}
}
int rdir = (dir + 4) % 8;
double rfract = 1.0 - fraction;
for (int nSurfTile = 0; nSurfTile < num_tiles; nSurfTile++){
int nSurfTile1 = tnSurface.getNeibIndex(nSurfTile, dir);
if (nSurfTile1 >= 0){
double d;
if (use_sqrt){
d = rfract * Math.sqrt(tone_diffs[nSurfTile][dir][0]) + fraction * dir_blur[dir][nSurfTile];
d *= d;
} else {
d =rfract * tone_diffs[nSurfTile][dir][0] + fraction * dir_blur[dir][nSurfTile];
}
mixed_diff_weight[nSurfTile][dir][0] = d;
mixed_diff_weight[nSurfTile][dir][1] = rfract * tone_diffs[nSurfTile][dir][1] + fraction * dir_weight[dir][nSurfTile];
mixed_diff_weight[nSurfTile1][rdir][0] = mixed_diff_weight[nSurfTile][dir][0];
mixed_diff_weight[nSurfTile1][rdir][1] = mixed_diff_weight[nSurfTile][dir][1];
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return mixed_diff_weight;
}
public void showToneDiffWeights3(String prefix){
String [] titles = {"diffs","sqrt","centers","weights"};
double [][] img_data = new double[titles.length][9 * surfTilesX * surfTilesY];
TileNeibs tnSurface3 = new TileNeibs( 3 * surfTilesX, 3 * surfTilesY);
for (int nSurfTile = 0; nSurfTile < tone_diff_weight.length; nSurfTile++){
int [] txy = tnSurface.getXY(nSurfTile);
int [] txy3 = {3 * txy[0] + 1, 3 * txy[1] + 1};
double sdw = 0.0, sw = 0.0;
int num_neibs = 0;
for (int dir = 0; dir < 8; dir++){
sw += tone_diff_weight[nSurfTile][dir][1];
sdw += tone_diff_weight[nSurfTile][dir][0] * tone_diff_weight[nSurfTile][dir][1];
int nSurfTile3 = tnSurface3.getNeibIndex(tnSurface3.getIndex(txy3[0],txy3[1]),dir);
img_data[0][nSurfTile3] = tone_diff_weight[nSurfTile][dir][0];
img_data[1][nSurfTile3] = Math.sqrt(tone_diff_weight[nSurfTile][dir][0]);
img_data[3][nSurfTile3] = tone_diff_weight[nSurfTile][dir][1];
if (tone_diff_weight[nSurfTile][dir][1] > 0.0) num_neibs ++;
}
if (sw > 0.0){
sdw /= sw;
}
if (num_neibs > 0){
sw /= num_neibs;
}
int nSurfTile3 = tnSurface3.getIndex(txy3[0],txy3[1]);
img_data[0][nSurfTile3] = sdw;
img_data[1][nSurfTile3] = Math.sqrt(sdw);
img_data[2][nSurfTile3] = sdw;
img_data[3][nSurfTile3] = sw;
}
(new showDoubleFloatArrays()).showArrays(img_data, 3 * surfTilesX, 3 * surfTilesY, true, prefix+"tone_diffs3", titles);
}
public void showToneDiffWeights1(String prefix){
double [][] img_data = new double[2][surfTilesX * surfTilesY];
for (int nSurfTile = 0; nSurfTile < tone_diff_weight.length; nSurfTile++){
double sdw = 0.0, sw = 0.0;
int num_neibs = 0;
for (int dir = 0; dir < 8; dir++){
sw += tone_diff_weight[nSurfTile][dir][1];
sdw += tone_diff_weight[nSurfTile][dir][0] * tone_diff_weight[nSurfTile][dir][1];
if (tone_diff_weight[nSurfTile][dir][1] > 0.0) num_neibs ++;
}
if (sw > 0.0){
sdw /= sw;
}
if (num_neibs > 0){
sw /= num_neibs;
}
img_data[0][nSurfTile] = sdw;
img_data[1][nSurfTile] = sw;
}
String [] titles = {"diffs","weights"};
(new showDoubleFloatArrays()).showArrays(img_data, surfTilesX, surfTilesY, true, prefix+"tone_diffs1", titles);
}
private double [] getDiffWeight(
double [] tone1,
double [] tone2)
{
double [] tone_weight = {0.0, Math.max(tone1[INDEX_A] * tone2[INDEX_A], 0.0)};
if (tone_weight[1] > 0.0){
double [][] scaled = {
{(Math.max(tone1[INDEX_R], 0.0) + fatZero) * kR, (Math.max(tone1[INDEX_B], 0.0) + fatZero) * kB, (Math.max(tone1[INDEX_G], 0.0) + fatZero) },
{(Math.max(tone2[INDEX_R], 0.0) + fatZero) * kR, (Math.max(tone2[INDEX_B], 0.0) + fatZero) * kB, (Math.max(tone2[INDEX_G], 0.0) + fatZero)}};
double rdiff2 = 0.0;
for (int i = 0; i < 3; i++){
double rd = (scaled[0][i] - scaled[1][i])/(scaled[0][i] + scaled[1][i]);
rdiff2 += rd*rd;
}
tone_weight[0] = rdiff2/3.0;
}
return tone_weight;
}
public void intValidSurf()
{
TileSurface.TileData [][] tileData = ts.getTileData();
int nSurfTiles = surfTilesX * surfTilesY;
valid_surf = new boolean [valid_ml.length][][]; // surfTilesX * surfTilesY][];
for (int ml = 0; ml < valid_ml.length; ml++) if (valid_ml[ml]) {
valid_surf[ml] = new boolean [nSurfTiles][];
}
for (int nSurfTile = 0; nSurfTile < nSurfTiles; nSurfTile++) if (tileData[nSurfTile] != null){
boolean [] surf_en = new boolean [tileData[nSurfTile].length];
for (int i = 0; i < surf_en.length; i++) {
surf_en[i] = true;
}
for (int ml = 0; ml < valid_ml.length; ml++) if (valid_surf[ml] != null){
valid_surf[ml][nSurfTile] = surf_en.clone();
}
}
}
/**
* limit layer options for assigned cells to a single (selected) option, disable all negative ones
* @param tileLayers
*/
public void restrictSingle (
final int [][] tileLayers)
{
for (int ml = 0; ml < valid_ml.length; ml++) if ((valid_surf[ml] != null) && (tileLayers[ml] != null)){
for (int nTile = 0; nTile < tileLayers[ml].length; nTile++) if (tileLayers[ml][nTile] != 0){
int nSurfTile = ts.getSurfaceTileIndex(nTile);
for (int ns = 0; ns < valid_surf[ml][nSurfTile].length; ns++){
valid_surf[ml][nSurfTile][ns] = false;
}
if (tileLayers[ml][nTile] > 0) valid_surf[ml][nSurfTile][tileLayers[ml][nTile] - 1] = true;
}
}
}
/**
* Limit layer options for assigned cells to a multiple options per tile cell
* @param options
*/
public void restrictMulti (
final int [][][] options)
{
for (int ml = 0; ml < valid_ml.length; ml++) if ((valid_surf[ml] != null) && (options[ml] != null)){
for (int nTile = 0; nTile < options[ml].length; nTile++) if ((options[ml][nTile] != null) && (options[ml][nTile].length > 0)){
int nSurfTile = ts.getSurfaceTileIndex(nTile);
for (int ns = 0; ns < valid_surf[ml][nSurfTile].length; ns++){
valid_surf[ml][nSurfTile][ns] = false;
}
for (int i = 0; i < options[ml][nTile].length; i++) {
valid_surf[ml][nSurfTile][options[ml][nTile][i] - 1] = true;
}
}
}
}
/**
* Get signed normalized difference from the measured disparity to the selected surface,
* limit it to +/-dispOutlier to reduce cost of the outliers
* @param ml measured layer (combo, quad, hor, vert)
* @param nSurfTile tile index in surface array (includes full supertiles)
* @param ns number of the surface
* @return signed disparity error, scaled down for large disparities
*/
public double dispDiff(
int ml,
int nSurfTile,
int ns,
boolean debug)
{
if (debug && ((dispStrength[ml] == null) || (dispStrength[ml][nSurfTile] == null))) {
String msg="dispDiff(): no data for ml="+ml+", nSurfTile="+nSurfTile+", ns="+ns;
System.out.println(msg);
return Double.NaN;
// IJ.showMessage(msg);
// throw new IllegalArgumentException (msg);
}
double dm = dispStrength[ml][nSurfTile][0];
double ds = ts.getTileData()[nSurfTile][ns].getDisparity();
double diff = dm - ds;
double d_av = 0.5 * (dm + ds);
if (d_av > dispNorm){
diff *= dispNorm/d_av;
}
if (diff > dispOutlier) diff = dispOutlier;
else if (diff < -dispOutlier) diff = -dispOutlier;
return diff;
}
/**
* Get absolute value of the normalized disparity difference from the measured value to the nearest surface
* @param ml measured layer (combo, quad, hor, vert)
* @param nSurfTile tile index in surface array (includes full supertiles)
* @return absolute value of the disparity error (scaled down for large disparities) to the nearest surface
*/
public double dispDiffBest(
int ml,
int nSurfTile,
boolean debug)
{
double best = Double.NaN;
if ((ts.getTileData() == null) || (ts.getTileData()[nSurfTile] == null)){
// System.out.println("dispDiffBest("+ml+","+nSurfTile+")");
return best;
}
for (int ns = 0; ns < ts.getTileData()[nSurfTile].length; ns++){
double diff = dispDiff(ml, nSurfTile, ns, debug);
double adiff = Math.abs(diff);
if (Double.isNaN(best) || (adiff < best)) {
best = adiff;
}
}
return best;
}
/**
* Get absolute value of the normalized disparity difference from the measured value to the farthest surface
* Used to estimate cost of un-assigned tiles
* @param ml measured layer (combo, quad, hor, vert)
* @param nSurfTile tile index in surface array (includes full supertiles)
* @return absolute value of the disparity error (scaled down for large disparities) to the farthest surface
*/
public double dispDiffWorst(
int ml,
int nSurfTile,
boolean debug)
{
double worst = Double.NaN;
if ((ts.getTileData() == null) || (ts.getTileData()[nSurfTile] == null)){
// System.out.println("dispDiffWorst("+ml+","+nSurfTile+")");
return worst;
}
for (int ns = 0; ns < ts.getTileData()[nSurfTile].length; ns++){
double diff = dispDiff(ml, nSurfTile, ns,debug);
double adiff = Math.abs(diff);
if (Double.isNaN(worst) || (adiff < worst)) {
worst = adiff;
}
}
return worst;
}
public TACosts [] getTileCosts(
boolean all_tiles,
int [][] tileLayers,
boolean debug)
{
TACosts [] ta_costs = new TACosts [surfTilesX * surfTilesY];
for (int nSurfTile = 0; nSurfTile < ta_costs.length; nSurfTile++){
boolean has_tile = false;
boolean has_block = false;
for (int ml = 0; ml < tileLayers.length; ml++) if(tileLayers[ml] != null) {
if (tileLayers[ml][nSurfTile] < 0) {
has_block = true;
break;
}
if (tileLayers[ml][nSurfTile] > 0) {
has_tile = true;
}
}
if (!has_block && (all_tiles || has_tile)){
ta_costs[nSurfTile] = getTileCosts(
nSurfTile, // int nSurfTile,
tileLayers, // int [][] tileLayers,
null, debug); // HashMap<Point,Integer> replacements)
}
} //for (int nSurfTile)
return ta_costs;
}
public double [] calcTileCosts(
int [][] tileLayers,
boolean debug)
{
double [] costs = new double [surfTilesX * surfTilesY];
for (int nSurfTile = 0; nSurfTile < costs.length; nSurfTile++){
boolean has_tile = false;
boolean has_block = false;
for (int ml = 0; ml < tileLayers.length; ml++) if(tileLayers[ml] != null) {
if (tileLayers[ml][nSurfTile] < 0) {
has_block = true;
break;
}
if (tileLayers[ml][nSurfTile] > 0) {
has_tile = true;
}
}
if (!has_block && has_tile){
TACosts ta_cost = getTileCosts(
nSurfTile, // int nSurfTile,
tileLayers, // int [][] tileLayers,
null, debug); // HashMap<Point,Integer> replacements)
costs[nSurfTile] = cost_coeff.dotProd(ta_cost);
}
}
return costs;
}
public void showTileCost(
String prefix,
int [][] tileLayers,
boolean debug)
{
double [] composite_costs = calcTileCosts(tileLayers, debug);
(new showDoubleFloatArrays()).showArrays(composite_costs, surfTilesX, surfTilesY, prefix+"composite_costs");
}
public void showTileCosts(
String prefix,
int [][] tileLayers,
boolean debug)
{
String [] titles = (new TACosts()).getTitles();
int num_stiles = surfTilesX*surfTilesY;
double [][] cost_components = new double[titles.length][surfTilesX * surfTilesY];
double [] NaNs = new double[titles.length];
for (int i = 0; i < NaNs.length; i++) NaNs[i] = Double.NaN;
for (int nSurfTile = 0; nSurfTile < num_stiles; nSurfTile++){
boolean has_tile = false;
boolean has_block = false;
for (int ml = 0; ml < tileLayers.length; ml++) if(tileLayers[ml] != null) {
if (tileLayers[ml][nSurfTile] < 0) {
has_block = true;
break;
}
if (tileLayers[ml][nSurfTile] > 0) {
has_tile = true;
}
}
double [] costs = NaNs;
if (!has_block) { // && has_tile){
TACosts ta_cost = getTileCosts(
nSurfTile, // int nSurfTile,
tileLayers, // int [][] tileLayers,
null, debug); // HashMap<Point,Integer> replacements)
ta_cost.mul(cost_coeff);
costs = ta_cost.toArray();
}
for (int i =0; i < cost_components.length; i++){
cost_components[i][nSurfTile] = costs[i];
}
}
(new showDoubleFloatArrays()).showArrays(cost_components, surfTilesX, surfTilesY, true, prefix+"cost_components", titles);
}
public TACosts [] statTileCosts(
int [][] tileLayers,
boolean debug)
{
TACosts [] ta_stats = {new TACosts(), new TACosts()}; // average, max
int num_tiles = 0;
int numSurfTiles =surfTilesX * surfTilesY;
for (int nSurfTile = 0; nSurfTile < numSurfTiles; nSurfTile++){
if (nSurfTile == 47459){
System.out.println("statTileCosts() nSurfTile="+nSurfTile);
}
boolean has_tile = false;
boolean has_block = false;
for (int ml = 0; ml < tileLayers.length; ml++) if(tileLayers[ml] != null) {
if (tileLayers[ml][nSurfTile] < 0) {
has_block = true;
break;
}
if (tileLayers[ml][nSurfTile] > 0) {
has_tile = true;
}
}
if (!has_block) { // && has_tile){
TACosts ta_cost = getTileCosts(
nSurfTile, // int nSurfTile,
tileLayers, // int [][] tileLayers,
null,debug); // HashMap<Point,Integer> replacements)
ta_stats[0].max(ta_cost);
ta_stats[1].add(ta_cost);
num_tiles++;
}
}
if (num_tiles > 0){
ta_stats[1].scale(1.0/num_tiles);
}
return ta_stats;
}
/**
* Get costs (not scaled) for the particular tile, add for all defined layers
* @param nSurfTile tile index in surface array (includes full supertiles)
* @param tileLayers current assignment
* @param replacements optional assignment modification (or null)
* @return TACosts instance with assigned values
*/
public TACosts getTileCosts(
int nSurfTile,
int [][] tileLayers,
HashMap<Point,Integer> replacements,
boolean debug)
{
TACosts costs = new TACosts();
int debugLevel = 0;
if (nSurfTile == -51360) { // 44831) { // 47459){
System.out.println("getTileCosts() nSurfTile="+nSurfTile);
debugLevel = 1;
}
int [][] around = new int [valid_ml.length][]; // contains layer + 1
for (int ml = 0; ml < valid_ml.length; ml++) if(valid_ml[ml]) {
around[ml] = new int [9];
}
int [] nSurfTiles = new int[9];
for (int dir = 0; dir < 9; dir++){
nSurfTiles[dir] = tnSurface.getNeibIndex(nSurfTile, dir);
if (nSurfTiles[dir] < 0) {
for (int ml = 0; ml < around.length; ml++) if (around[ml] != null){
around[ml][dir] = TileSurface.PROHOBITED;
}
} else {
for (int ml = 0; ml < around.length; ml++) if (around[ml] != null){
around[ml][dir] = tileLayers[ml][nSurfTiles[dir]];
if (replacements != null){
Integer isurf = replacements.get(new Point(ml, nSurfTiles[dir]));
if (isurf != null) {
around[ml][dir] = isurf; // substitute
}
}
}
}
}
//
// public double empty; // Cost of a tile that is not assigned
for (int ml = 0; ml < around.length; ml++) if (around[ml] != null){
if (around[ml][8] == 0) costs.empty +=1.0; // Cost of a tile that is not assigned
}
// public double nolink; // Cost of a tile not having any neighbor in particular direction
int num_weak_fgnd = 0; // to reduce multiple for teh same tile
int num_color_sep = 0; // to reduce multiple for teh same tile
for (int ml = 0; ml < around.length; ml++) if ((around[ml] != null) && (around[ml][8] > 0)){
if ((around[ml][8] - 1) >= ts.getTileData()[nSurfTile].length){
System.out.println("getTileCosts() BUG: nSurfTile="+nSurfTile);
}
int [] neibs = ts.getTileData()[nSurfTile][around[ml][8] - 1].getNeighbors();
for (int dir = 0; dir < 8; dir++) if (neibs[dir] >= 0){ // do not count non-existing connections
boolean link_this = false;
boolean link_other = false;
int ml1 = ml;
int neibp1 = neibs[dir] + 1;
if (around[ml][dir] > 0) {
if (around[ml][dir] == neibp1) {
link_this = true;
} else {
link_other = true;
}
} else if (around[ml][dir] == 0){
// see if some other ml contains this surface (ignore other surfaces
for (ml1 = 0; ml1 < around.length; ml1++) if ((ml1 != ml) && (around[ml1] != null)) {
if (around[ml1][dir] == neibp1){
link_this = true;
break; // ml1 will keep other ml
}
}
} else { // negative/prohibited
continue;
}
if (!link_this && !link_other){
costs.nolink +=1.0;
} else if (link_other) {
costs.swtch += 1.0; // cost for any switch
// check if it is fb->bg transition and fg is weak
double d_this = ts.getTileData()[nSurfTiles[dir]][neibs[dir]].getDisparity();
double d_other = ts.getTileData()[nSurfTiles[dir]][around[ml][dir] -1].getDisparity();
double disp_diff = d_this - d_other;
double d_av = 0.5 * (d_this + d_other);
if (d_av > dispNorm){
disp_diff *= dispNorm/d_av;
}
// disp_diff here is signed, positive if center is FG, other is BG
if (disp_diff > minFgBg) {
double strength = dispStrength[ml][nSurfTile][1];
strength = Math.max(strength, minFgEdge);
costs.weak_fgnd += minFgEdge / strength;
num_weak_fgnd++;
} else if (mutual_weak_fgnd && (disp_diff < -minFgBg)) {
double [] dsmeas_other = dispStrength[ml][nSurfTiles[dir]];
double strength = (dsmeas_other != null)? dsmeas_other[1]: 0.0; // measured strength on the other end or 0.0 if nothing there
strength = Math.max(strength, minFgEdge);
costs.weak_fgnd += minFgEdge / strength;
num_weak_fgnd++;
}
if (Math.abs(disp_diff) > minColSep){
double col_diff = tone_diff_weight[nSurfTile][dir][0];
col_diff= Math.max(col_diff,minColDiff);
costs.color += tone_diff_weight[nSurfTile][dir][1] * minColSep/col_diff;
num_color_sep++;
}
} else { // v, both can not coexist
// Anything to cost here?
}
}
// if (around[ml][8] == 0) costs.empty +=1.0; // each existing measurement layer that is not assigned
} //for (int ml = 0; ml < around.length; ml++) if ((around[ml] != null) && (around[ml][8] > 0))
// using /4.0 to maintain same value (==1.0) for half neighbors (straight edge)
if ((num_weak_fgnd > 0) && (shrinkWeakFgnd > 0.0)){
costs.weak_fgnd /= Math.pow(num_weak_fgnd/4.0, shrinkWeakFgnd);
}
if ((num_color_sep > 0) && (shrinkColor > 0.0)){
costs.color /= Math.pow(num_color_sep/4.0, shrinkColor);
}
double disp_diff_lpf = 0.0, disp_diff_weight = 0.0; // calculate LPF of the disparity signed error over all ML and 9 cells
double disp_diff2 = 0.0, disp_weight = 0.0; // calculate disparity error in the center, weighted
double disp_diff_over_best = 0.0; // , disp_weight_best = 0.0; // calculate disparity error in the center, weighted
for (int ml = 0; ml < around.length; ml++) if (around[ml] != null){
double diff=0.0, weight=0.0;
for (int dir = 0; dir < 9; dir++){
if (around[ml][dir] > 0){ // assigned
diff = dispDiff(
ml, // int ml,
nSurfTiles[dir], // int nSurfTile,
around[ml][dir] - 1, // int ns)
debug);
} else if ((dir == 8) && (around[ml][dir] == 0) ) { //no assigned (not prohibited) - center only, because worst does not have sign
diff = dispDiffWorst( // worst for all surfaces
ml, // int ml,
nSurfTiles[dir], // int nSurfTile,
debug);
}
if (dispStrength[ml][nSurfTile] != null) { // not a bug
if (strengthDiff9Pwr > 0.0) {
weight = dispStrength[ml][nSurfTile][1];
if (strengthDiff9Pwr != 1.0) {
weight = Math.pow(weight, strengthDiff9Pwr);
}
} else {
weight = 1.0;
}
weight *= NEIB_WEIGHTS[dir];
disp_diff_lpf += diff * weight;
disp_diff_weight += weight;
if (debugLevel > 0){
System.out.println("getTileCosts() nSurfTile = "+nSurfTile+"->"+dir+" disp_diff_lpf="+disp_diff_lpf+
" disp_diff_weight="+disp_diff_weight+" weight="+weight+ " diff="+diff+" around["+ml+"]["+dir+"]="+around[ml][dir]);
}
}
}
// now diff is for the center, weight needs to be re-calculated
if (strengthDiffPwr > 0.0) {
if ((dispStrength[ml] == null) || (dispStrength[ml][nSurfTile] == null)){
if (debug) {
System.out.println("getTileCosts() nSurfTile = "+nSurfTile+" ml = "+ml+" is it really a BUG - null pointer here?");
}
weight = 1.0;
} else {
weight = dispStrength[ml][nSurfTile][1]; // null pointer
if (strengthDiffPwr != 1.0) {
weight = Math.pow(weight, strengthDiffPwr);
}
}
} else {
weight = 1.0;
}
disp_diff2 += diff * diff * weight;
disp_weight += weight;
// and once more for the disparity over best
if (strengthBestPwr > 0.0) {
weight = dispStrength[ml][nSurfTile][1];
if (strengthBestPwr != 1.0) {
weight = Math.pow(weight, strengthBestPwr);
}
} else {
weight = 1.0;
}
disp_diff_over_best += (Math.abs(diff) - dispDiffBest( ml, nSurfTiles[8], debug)) * weight; // this one - not squared
}
if (disp_diff_weight > 0.0) {
disp_diff_lpf /= disp_diff_weight;
costs.diff9 += disp_diff_lpf * disp_diff_lpf;
if (debugLevel > 0){
System.out.println("getTileCosts() nSurfTile = "+nSurfTile+" disp_diff_lpf="+disp_diff_lpf+
" disp_diff_weight="+disp_diff_weight+" costs.diff9="+costs.diff9);
}
}
if (disp_weight > 0.0) {
costs.diff += disp_diff2 / disp_weight;
costs.diff_best += disp_diff_over_best / disp_weight;
}
int [] txy = tnSurface.getXY(nSurfTile);
int nSTile = (txy[0] / ts.getSuperTileSize()) + (txy[1] / ts.getSuperTileSize()) * ts.getSTilesX();
for (int ml = 0; ml < around.length; ml++) if ((around[ml] != null) && (around[ml][8] > 0)){
int parentSTile =ts.getTileData()[nSurfTile][around[ml][8] -1].getParentNsTile();
if (parentSTile != nSTile){
costs.flaps += 1.0;
}
}
return costs;
}
public int [][] imgToSurf (
int [][] tileLayersImg)
{
int [][] tileLayersSurf = new int[tileLayersImg.length][];
for (int ml = 0; ml < tileLayersImg.length; ml++) if (tileLayersImg[ml] != null){
tileLayersSurf[ml] = new int [tnSurface.getLength()];
for (int i = 0; i < tileLayersSurf[ml].length; i++){
tileLayersSurf[ml][i] = -1;
}
for (int nTile = 0; nTile < tileLayersImg[ml].length; nTile++){
int nSurfTile = tnSurface.getIndex(tnImage.getXY(nTile));
if (nSurfTile >= 0) {
tileLayersSurf[ml][nSurfTile] = tileLayersImg[ml][nTile];
}
}
}
return tileLayersSurf;
}
public int [][] surfToImg (
int [][] tileLayersSurf)
{
int [][] tileLayersImg = new int[tileLayersSurf.length][];
for (int ml = 0; ml < tileLayersSurf.length; ml++) if (tileLayersSurf[ml] != null){
tileLayersImg[ml] = new int [tnImage.getLength()];
for (int i = 0; i < tileLayersImg[ml].length; i++){
tileLayersImg[ml][i] = -1;
}
for (int nSurfTile = 0; nSurfTile < tileLayersSurf[ml].length; nSurfTile++){
int nImgTile = tnImage.getIndex(tnSurface.getXY(nSurfTile));
if (nImgTile >= 0) {
tileLayersImg[ml][nImgTile] = tileLayersSurf[ml][nSurfTile];
}
}
}
return tileLayersImg;
}
public void optimizeAssignment9(
final boolean noEdge,
final int [][] tileLayers,
final int debugLevel,
final int dbg_X,
final int dbg_Y)
{
mutual_weak_fgnd = true;
final int step = 3;
final int tries = 1000;
// final int dbg_tile = dbg_X + dbg_Y * surfTilesX;
final int dbg_tile = 47779; // 27083; // 44493;
final int num_tiles = surfTilesX * surfTilesY;
final int [][] tile_indices = new int [step*step][];
for (int sty = 0; sty < step; sty ++){
int num_y = (surfTilesY + step -1 - sty) / step;
for (int stx = 0; stx < step; stx ++){
int num_x = (surfTilesX + step -1 - stx) / step;
int indx1 = sty * step + stx;
int l = num_y * num_x;
tile_indices[indx1] = new int [l];
int indx2 = 0;
for (int y = 0; y < num_y; y++){
for (int x = 0; x < num_x; x++){
tile_indices[indx1][indx2++] = (sty + step * y) * surfTilesX + (stx + step * x);
}
}
}
}
final Thread[] threads = ImageDtt.newThreadArray((debugLevel > 1)? 1 : ts.getThreadsMax());
final int numThreads = threads.length;
final int [] improved = new int [numThreads];
final AtomicInteger ai_numThread = new AtomicInteger(0);
final AtomicInteger ai = new AtomicInteger(0);
final AtomicInteger ai_series = new AtomicInteger(0);
final AtomicBoolean [] dirty = new AtomicBoolean[surfTilesX * surfTilesY];
for (int nSurfTile = 0; nSurfTile < dirty.length; nSurfTile++){
boolean valid_tile = false; // bad may be only some ml?
for (int ml = 0; ml < tileLayers.length; ml++) if ((tileLayers[ml] != null) && (tileLayers[ml][nSurfTile] >= 0)){
valid_tile = true;
break;
}
if (valid_tile) dirty[nSurfTile] = new AtomicBoolean(true);
}
final boolean [][] bad_surface = new boolean[num_tiles][];
final TileSurface.TileData [][] tileData = ts.getTileData();
if (noEdge) {
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nSurfTile = ai.getAndIncrement(); nSurfTile < num_tiles; nSurfTile = ai.getAndIncrement()) {
if (tileData[nSurfTile] != null){
bad_surface[nSurfTile] = new boolean [tileData[nSurfTile].length];
for (int ns = 0; ns < tileData[nSurfTile].length; ns++) {
int []neibs = tileData[nSurfTile][ns].getNeighbors();
for (int i = 0; i < neibs.length; i++){
if (neibs[i] < 0){
bad_surface[nSurfTile][ns] = true;
}
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
for (int nTry = 0 ; nTry < tries; nTry++) {
for (int i = 0; i < improved.length; i++) improved[i] = 0;
int this_improved = 0;
for (int nSeries = 0; nSeries < tile_indices.length; nSeries++) {
final int fnSeries = nSeries;
ai.set(0);
ai_numThread.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
int numThread = ai_numThread.getAndIncrement(); // unique number of thread to write to rslt_diffs[numThread]
for (int iTile = ai.getAndIncrement(); iTile < tile_indices[fnSeries].length; iTile = ai.getAndIncrement()) {
int nSurfTile = tile_indices[fnSeries][iTile];
int dl = ((debugLevel > 1) && (nSurfTile == dbg_tile)) ? 3: debugLevel;
if (dl > 2){
System.out.println("optimizeAssignment9(), nSurfTile = "+nSurfTile+" dl = "+dl);
}
// if (dirty[nSurfTile].get()) {
if ((dirty[nSurfTile] != null) && dirty[nSurfTile].getAndSet(false)) {
int num_surf = tileData[nSurfTile].length;
int lowest_surf = 0;
for (; lowest_surf < num_surf; lowest_surf ++){
if ((bad_surface[nSurfTile] != null) && !bad_surface[nSurfTile][lowest_surf]) {
break;
}
}
if (lowest_surf >= num_surf) {
continue; // no valid surfaces at this location
}
double best_cost = cost_coeff.dotProd(getTileCosts(
nSurfTile, // int nSurfTile,
tileLayers, // int [][] tileLayers,
null, (dl > 1))); // HashMap<Point,Integer> replacements);
// int [] initial_indices = tileLayers[nSurfTile].clone();
int [] initial_indices = new int [valid_ml.length]; // 1-based
for (int ml = 0; ml < valid_ml.length; ml ++ ){
if (tileLayers[ml] != null) {
initial_indices[ml] = tileLayers[ml][nSurfTile]; // 1-based
}
}
int [] best_surf = null;
int [] surfaces = null; // new int [valid_ml.length];
int max_reset = 0; // = valid_ml.length; // maximal ml to reset
while (true) {
if (surfaces == null) {
surfaces = new int [valid_ml.length];
for (int ml = 0; ml < valid_ml.length; ml ++){
if (!valid_ml[ml] || (tileLayers[ml][nSurfTile] < 0)) {
surfaces[ml] = -1;
}
}
max_reset = valid_ml.length;
} else { // find ml to increase surface
for (max_reset = 0; max_reset < surfaces.length; max_reset++) if (surfaces[max_reset] >= 0){
for (surfaces[max_reset]++; surfaces[max_reset] < num_surf; surfaces[max_reset]++) {
if ((bad_surface[nSurfTile] == null) || !bad_surface[nSurfTile][surfaces[max_reset]]) {
break;
}
}
if (surfaces[max_reset] < num_surf) break;
}
if (max_reset >= surfaces.length){
break; // while (true) {
}
}
// reset all surfaces[] with indices < max_reset to lowest
for (int ml = 0; ml < max_reset; ml++ ) if (valid_ml[ml] && (surfaces[ml] >= 0)){
surfaces[ml] = lowest_surf;
}
// now surfaces[] contain next combination of surfaces to try
// tileLayers[nSurfTile] = surfaces;
for (int ml = 0; ml < valid_ml.length; ml ++ ){
if (tileLayers[ml] != null) {
tileLayers[ml][nSurfTile] = surfaces[ml] + 1; // 1-based from 0-based
}
}
double cost = cost_coeff.dotProd(getTileCosts( //
nSurfTile, // int nSurfTile,
tileLayers, // int [][] tileLayers,
null, (dl > 1))); // HashMap<Point,Integer> replacements);
if (cost < best_cost) {
best_cost = cost;
best_surf = surfaces.clone();
}
} // while (true)
if (best_surf != null){ // update
// tileLayers[nSurfTile] = best_surf;
for (int ml = 0; ml < valid_ml.length; ml ++ ){
if (tileLayers[ml] != null) {
tileLayers[ml][nSurfTile] = best_surf[ml] + 1; // 1-based from 0-based
}
}
for (int dir = 0; dir <8; dir++) {
int nSurfTile1 = tnSurface.getNeibIndex(nSurfTile, dir);
if ((nSurfTile1 >= 0) && (dirty[nSurfTile1] != null)){
dirty[nSurfTile1].set(true);
}
}
improved[numThread]++;
} else { // restore initial data
// tileLayers[nSurfTile] = initial_indices;
for (int ml = 0; ml < valid_ml.length; ml ++ ){
if (tileLayers[ml] != null) {
tileLayers[ml][nSurfTile] = initial_indices[ml]; // 1-based from 1-based
}
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (debugLevel > -1){
int num_better = 0;
for (int i = 0; i < improved.length; i++){
num_better += improved[i];
}
System.out.println("optimizeAssignment9(): pass = "+nTry+ ":"+nSeries+" improved:" + (num_better - this_improved));
this_improved = num_better;
}
} // for (int nSeries = 0; nSeries < tile_indices.length; nSeries++) {
// should be checked only after all series (now 9 passes) are finished - if anything was added - continue
int num_improved = 0;
for (int i = 0; i < improved.length; i++){
num_improved += improved[i];
}
if (debugLevel > -1){
System.out.println("optimizeAssignment9(): pass = "+nTry+ " improved:"+num_improved);
}
if (num_improved == 0) break;
}
}
public void optimizeAssignment25(
final boolean noEdge,
final int [][] tileLayers,
final int debugLevel,
final int dbg_X,
final int dbg_Y)
{
final int step = 5;
mutual_weak_fgnd = false;
final int tries = 1000;
// final int dbg_tile = dbg_X + dbg_Y * surfTilesX;
final int dbg_tile = 51360; // 51; // 44831; // 27083; // 44493;
final int num_tiles = surfTilesX * surfTilesY;
final int [][] tile_indices = new int [step*step][];
for (int sty = 0; sty < step; sty ++){
int num_y = (surfTilesY + step -1 - sty) / step;
for (int stx = 0; stx < step; stx ++){
int num_x = (surfTilesX + step -1 - stx) / step;
int indx1 = sty * step + stx;
int l = num_y * num_x;
tile_indices[indx1] = new int [l];
int indx2 = 0;
for (int y = 0; y < num_y; y++){
for (int x = 0; x < num_x; x++){
tile_indices[indx1][indx2++] = (sty + step * y) * surfTilesX + (stx + step * x);
}
}
}
}
final Thread[] threads = ImageDtt.newThreadArray((debugLevel > 1)? 1 : ts.getThreadsMax());
final int numThreads = threads.length;
final int [] improved = new int [numThreads];
final AtomicInteger ai_numThread = new AtomicInteger(0);
final AtomicInteger ai = new AtomicInteger(0);
final AtomicInteger ai_series = new AtomicInteger(0);
final AtomicBoolean [] dirty = new AtomicBoolean[surfTilesX * surfTilesY];
for (int nSurfTile = 0; nSurfTile < dirty.length; nSurfTile++){
boolean valid_tile = false; // bad may be only some ml?
for (int ml = 0; ml < tileLayers.length; ml++) if ((tileLayers[ml] != null) && (tileLayers[ml][nSurfTile] >= 0)){
valid_tile = true;
break;
}
if (valid_tile) dirty[nSurfTile] = new AtomicBoolean(true);
}
final boolean [][] bad_surface = new boolean[num_tiles][];
final TileSurface.TileData [][] tileData = ts.getTileData();
if (noEdge) {
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nSurfTile = ai.getAndIncrement(); nSurfTile < num_tiles; nSurfTile = ai.getAndIncrement()) {
if (tileData[nSurfTile] != null){
bad_surface[nSurfTile] = new boolean [tileData[nSurfTile].length];
for (int ns = 0; ns < tileData[nSurfTile].length; ns++) {
int []neibs = tileData[nSurfTile][ns].getNeighbors();
for (int i = 0; i < neibs.length; i++){
if (neibs[i] < 0){
bad_surface[nSurfTile][ns] = true;
}
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
for (int nTry = 0 ; nTry < tries; nTry++) {
for (int i = 0; i < improved.length; i++) improved[i] = 0;
int this_improved = 0;
for (int nSeries = 0; nSeries < tile_indices.length; nSeries++) {
final int fnSeries = nSeries;
ai.set(0);
ai_numThread.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
int numThread = ai_numThread.getAndIncrement(); // unique number of thread to write to rslt_diffs[numThread]
for (int iTile = ai.getAndIncrement(); iTile < tile_indices[fnSeries].length; iTile = ai.getAndIncrement()) {
int nSurfTile = tile_indices[fnSeries][iTile];
int dl = ((debugLevel > 1) && (nSurfTile == dbg_tile)) ? 3: debugLevel;
if (dl > 2){
System.out.println("optimizeAssignment25(), nSurfTile = "+nSurfTile+" dl = "+dl);
}
// if (dirty[nSurfTile].get()) {
if ((dirty[nSurfTile] != null) && dirty[nSurfTile].getAndSet(false)) {
int num_surf = tileData[nSurfTile].length;
int lowest_surf = 0;
for (; lowest_surf < num_surf; lowest_surf ++){
if ((bad_surface[nSurfTile] != null) && !bad_surface[nSurfTile][lowest_surf]) {
break;
}
}
if (lowest_surf >= num_surf) {
continue; // no valid surfaces at this location
}
double best_cost = 0.0;
if (dl > 2) {
System.out.println("optimizeAssignment25(), tileLayers[0]["+nSurfTile+"] = " + tileLayers[0][nSurfTile]);
// int [] dbg_layers = new int [tileLayers.length];
// for (int ml = 0; ml < tileLayers.length; ml++){
// dbg_layers[ml] = (tileLayers[ml] == null) ? -0: tileLayers[ml][nSurfTile];
// }
// System.out.println("optimizeAssignment25(), tileLayers["+nSurfTile+"] = " + dbg_layers);
}
for (int dir = 0; dir < 9; dir++) {
int nSurfTile1 = tnSurface.getNeibIndex(nSurfTile, dir);
if (nSurfTile1 >= 0){
// best_cost += cost_coeff.dotProd(getTileCosts(
// nSurfTile1, // int nSurfTile,
// tileLayers, // int [][] tileLayers,
// null)); // HashMap<Point,Integer> replacements);
TACosts ta_costs = getTileCosts(
nSurfTile1, // int nSurfTile,
tileLayers, // int [][] tileLayers,
null, (dl > 1)); // HashMap<Point,Integer> replacements);
double ccost = cost_coeff.dotProd(ta_costs);
best_cost += ccost;
if (dl > 2){
System.out.println("optimizeAssignment25(), nSurfTile = "+nSurfTile+" dir = "+dir +
" nSurfTile1="+nSurfTile1+" ccost = "+ccost+" best_cost="+best_cost);
System.out.println("ta_costs["+nSurfTile1+"]="+ta_costs.toString());
}
}
}
// int [] initial_indices = tileLayers[nSurfTile].clone();
int [] initial_indices = new int [valid_ml.length]; // 1-based
for (int ml = 0; ml < valid_ml.length; ml ++ ){
if (tileLayers[ml] != null) {
initial_indices[ml] = tileLayers[ml][nSurfTile]; // 1-based
}
}
int [] best_surf = null;
int [] surfaces = null; // new int [valid_ml.length];
int max_reset = 0; // = valid_ml.length; // maximal ml to reset
while (true) {
if (surfaces == null) {
surfaces = new int [valid_ml.length];
for (int ml = 0; ml < valid_ml.length; ml ++){
if (!valid_ml[ml] || (tileLayers[ml][nSurfTile] < 0)) {
surfaces[ml] = -1;
}
}
max_reset = valid_ml.length;
} else { // find ml to increase surface
for (max_reset = 0; max_reset < surfaces.length; max_reset++) if (surfaces[max_reset] >= 0){
for (surfaces[max_reset]++; surfaces[max_reset] < num_surf; surfaces[max_reset]++) {
if ((bad_surface[nSurfTile] == null) || !bad_surface[nSurfTile][surfaces[max_reset]]) {
break;
}
}
if (surfaces[max_reset] < num_surf) break;
}
if (max_reset >= surfaces.length){
break; // while (true) {
}
}
// reset all surfaces[] with indices < max_reset to lowest
for (int ml = 0; ml < max_reset; ml++ ) if (valid_ml[ml] && (surfaces[ml] >= 0)){
surfaces[ml] = lowest_surf;
}
// now surfaces[] contain next combination of surfaces to try
// tileLayers[nSurfTile] = surfaces;
for (int ml = 0; ml < valid_ml.length; ml ++ ){
if (tileLayers[ml] != null) {
tileLayers[ml][nSurfTile] = surfaces[ml] + 1; // 1-based from 0-based
}
}
double cost = 0.0;
if (dl > 2) {
System.out.println("optimizeAssignment25(), surfaces[0]= " + surfaces[0]);
}
for (int dir = 0; dir < 9; dir++) {
int nSurfTile1 = tnSurface.getNeibIndex(nSurfTile, dir);
if (nSurfTile1 >= 0){
TACosts ta_costs = getTileCosts(
nSurfTile1, // int nSurfTile,
tileLayers, // int [][] tileLayers,
null, (dl > 1)); // HashMap<Point,Integer> replacements);
double ccost = cost_coeff.dotProd(ta_costs);
cost+=ccost;
if (dl > 2){
System.out.println("optimizeAssignment25(), nSurfTile = "+nSurfTile+" dir = "+dir +
" nSurfTile1="+nSurfTile1+" ccost = "+ccost+" cost="+cost);
System.out.println("ta_costs["+nSurfTile1+"]="+ta_costs.toString());
}
}
}
if (cost < best_cost) {
best_cost = cost;
best_surf = surfaces.clone();
}
} // while (true)
if (best_surf != null){ // update
// tileLayers[nSurfTile] = best_surf;
for (int ml = 0; ml < valid_ml.length; ml ++ ){
if (tileLayers[ml] != null) {
tileLayers[ml][nSurfTile] = best_surf[ml] + 1; // 1-based from 0-based
}
}
for (int dir = 0; dir <8; dir++) {
int nSurfTile1 = tnSurface.getNeibIndex(nSurfTile, dir);
if ((nSurfTile1 >= 0) && (dirty[nSurfTile1] != null)){
dirty[nSurfTile1].set(true);
}
}
improved[numThread]++;
} else { // restore initial data
// tileLayers[nSurfTile] = initial_indices;
for (int ml = 0; ml < valid_ml.length; ml ++ ){
if (tileLayers[ml] != null) {
tileLayers[ml][nSurfTile] = initial_indices[ml]; // 1-based from 1-based
}
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (debugLevel > -1){
int num_better = 0;
for (int i = 0; i < improved.length; i++){
num_better += improved[i];
}
System.out.println("optimizeAssignment25(): pass = "+nTry+ ":"+nSeries+" improved:" + (num_better - this_improved));
this_improved = num_better;
}
} // for (int nSeries = 0; nSeries < tile_indices.length; nSeries++) {
// should be checked only after all series (now 9 passes) are finished - if anything was added - continue
int num_improved = 0;
for (int i = 0; i < improved.length; i++){
num_improved += improved[i];
}
if (debugLevel > -1){
System.out.println("optimizeAssignment25(): pass = "+nTry+ " improved:"+num_improved);
}
if (num_improved == 0) break;
}
}
}
......@@ -270,7 +270,9 @@ public class TilePlanes {
{
if (!force && (world_xyz == null)) return Double.NaN;
if (wvectors == null) return Double.NaN;
Matrix norm_disp = new Matrix(this.getWorldXYZ(this.correctDistortions, 0),3); // normal to plane from disparity space
double [] anorm_disp = this.getWorldXYZ(this.correctDistortions, 0);
if (anorm_disp == null) return Double.NaN;
Matrix norm_disp = new Matrix(anorm_disp,3); // normal to plane from disparity space
Matrix norm_world = new Matrix(wvectors[0],3); // normal to plane from disparity space
Matrix cp = cross3d(norm_disp, norm_world);
double cp2 = cp.transpose().times(cp).get(0, 0);
......@@ -1273,7 +1275,7 @@ public class TilePlanes {
}
if ((dispNorm > 0.0) && (zxy[0] > dispNorm)) {
almost_fronto = false; // disable fronto for near objects completely
// almost_fronto = false; // disable fronto for near objects completely
}
this.fronto = almost_fronto;
return almost_fronto;
......@@ -2163,6 +2165,8 @@ public class TilePlanes {
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]);
w = 0.0;
disp_str[nl][1][indx] = 0.0;
continue;
}
if (w > 0.0){
......@@ -3995,6 +3999,23 @@ public class TilePlanes {
px_py[0],
px_py[1],
this.correctDistortions);
if (Double.isNaN(disp)) {
System.out.println("getPlaneToThis(), px_py = {"+px_py[0]+", "+px_py[1]+"}, px_py_other = {"+px_py_other[0]+", "+px_py_other[1]+"}");
System.out.println("getPlaneToThis(), disp = "+disp);
System.out.println("getPlaneToThis(), pd="+ pd.toString());
System.out.println("getPlaneToThis(), otherPd="+ otherPd.toString());
System.out.println("getPlaneToThis(), pd.getWorldXYZ(this.correctDistortions)="+ pd.getWorldXYZ(this.correctDistortions));
System.out.println("getPlaneToThis(), wv1 = {"+ wv1[0]+", "+ wv1[1]+", "+ wv1[2]+"}");
System.out.println("getPlaneToThis(), wv2 = {"+ wv2[0]+", "+ wv2[1]+", "+ wv2[2]+"}");
double [] norm_xyz = pd.getWorldXYZ(this.correctDistortions);
System.out.println("getPlaneToThis(),norm_xyz="+ norm_xyz);
disp = geometryCorrection.getPlaneDisparity( // disparity (at this center) for crossing other supertile plane
norm_xyz, // will calculate if not yet done so. Should it use otherPd, not pd? and then clone later?
px_py[0],
px_py[1],
this.correctDistortions);
}
if (debugLevel > 0) {
System.out.println("getPlaneToThis(), px_py = {"+px_py[0]+", "+px_py[1]+"}, px_py_other = {"+px_py_other[0]+", "+px_py_other[1]+"}");
System.out.println("getPlaneToThis(), disp = "+disp);
......@@ -4178,6 +4199,15 @@ public class TilePlanes {
int debugLevel)
{
double delta = 0.0001;
// debugging:
if (world_xyz != null) {
double l2 = world_xyz[0]*world_xyz[0] + world_xyz[1]*world_xyz[1]+world_xyz[2]*world_xyz[2];
if (l2 < 0.5) {
System.out.println("getWorldXYZ(): l2="+l2); // +" this=\n"+this.toString());
world_xyz = null;
}
}
if (world_xyz != null) return world_xyz;
setCorrectDistortions(correct_distortions);
// get pixel coordinates of the plane origin point
......@@ -4271,6 +4301,10 @@ public class TilePlanes {
// convert plane normal vector to world coordinates
//world_xyz
world_xyz = norm_xyz.times((xyz.transpose().times(norm_xyz).get(0,0))).getColumnPackedCopy();
double l2 = world_xyz[0]*world_xyz[0] + world_xyz[1]*world_xyz[1]+world_xyz[2]*world_xyz[2];
if (l2 < 0.5) {
System.out.println("getWorldXYZ(): l2="+l2); // +" this=\n"+this.toString());
}
return world_xyz;
}
......
......@@ -2245,6 +2245,24 @@ public class TileProcessor {
System.out.println("showScan("+title+"): isMeasured()="+scan.isMeasured()+", isProcessed()="+scan.isProcessed()+", isCombo()="+scan.isCombo());
}
public double [][] getShowDS(
CLTPass3d scan,
boolean force_final)
{
double [][] dbg_img = getShowScan(scan);
double [][] ds = new double [2][];
if (!force_final && (dbg_img[2] != null)) {
ds[0] = dbg_img[2]; // disparity
} else {
ds[0] = dbg_img[1]; // final
}
if (!force_final && (dbg_img[7] != null)) {
ds[1] = dbg_img[7]; // strength
} else {
ds[1] = dbg_img[6]; // final strength
}
return ds;
}
public double [][] getShowScan(
CLTPass3d scan)
......@@ -4696,7 +4714,7 @@ public class TileProcessor {
}
public boolean assignTilesToSurfaces(
public double [][] assignTilesToSurfaces(
EyesisCorrectionParameters.CLTParameters clt_parameters,
GeometryCorrection geometryCorrection,
final int threadsMax, // maximal number of threads to launch
......@@ -4712,7 +4730,7 @@ public class TileProcessor {
SuperTiles st = scan_prev.getSuperTiles();
TileSurface tileSurface = st.getTileSurface();
if (tileSurface == null){
return false;
return null; // false;
}
// show testure_tiles
......@@ -5069,10 +5087,10 @@ public class TileProcessor {
(new showDoubleFloatArrays()).showArrays(dbg_tls, ta.getSurfTilesX(), ta.getSurfTilesY(), true, "tile_layers_surf");
}
if (!batch_mode && (debugLevel > -1)) {
ta.showTileCost("before_",tile_layers_surf);
ta.showTileCosts("before_",tile_layers_surf);
ta.showTileCost("before_",tile_layers_surf); // , true);
ta.showTileCosts("before_",tile_layers_surf); //, true);
}
TileAssignment.TACosts [] ta_stats = ta.statTileCosts(tile_layers_surf);
TileAssignment.TACosts [] ta_stats = ta.statTileCosts(tile_layers_surf);// ,(debugLevel > -1));
for (int i = 0; i < ta_stats.length; i++){
System.out.println(ta_stats[i].toString());
......@@ -5097,12 +5115,12 @@ public class TileProcessor {
(new showDoubleFloatArrays()).showArrays(dbg_tls, ta.getSurfTilesX(), ta.getSurfTilesY(), true, "optimized_tile_layers_surf");
}
if (!batch_mode && (debugLevel > -2)) {
ta.showTileCost("after_",tile_layers_surf);
ta.showTileCost("after_",tile_layers_surf); // , true);
}
if (!batch_mode && (debugLevel > -1)) {
ta.showTileCosts("after_",tile_layers_surf);
ta.showTileCosts("after_",tile_layers_surf); // , true);
}
ta_stats = ta.statTileCosts(tile_layers_surf);
ta_stats = ta.statTileCosts(tile_layers_surf); // , (debugLevel > -1));
System.out.println("Optimized:");
for (int i = 0; i < ta_stats.length; i++){
System.out.println(ta_stats[i].toString());
......@@ -5122,10 +5140,14 @@ public class TileProcessor {
tileSel, // final boolean [][] tileSel,
debugLevel); // final int debugLevel,
double [][] assignments_dbg = tileSurface.getShowAssignment(dispStrength);
if (!batch_mode && clt_parameters.tsShow && (debugLevel > -2)){
tileSurface.showAssignment(
"assignments", // String title,
dispStrength); // final double [][][] dispStrength)
String title_asgn = "assignments";
String [] titles_asgn = tileSurface.getTitlesAssignment(dispStrength);
(new showDoubleFloatArrays()).showArrays(assignments_dbg, tilesX, tilesY, true, title_asgn, titles_asgn);
/// tileSurface.showAssignment(
/// "assignments", // String title,
/// dispStrength); // final double [][][] dispStrength)
}
boolean [][] assigned_sel = tileSurface.extractSelection(
batch_mode ? -5: 0, // final int debugLevel,
......@@ -5261,7 +5283,7 @@ public class TileProcessor {
showDoubleFloatArrays sdfa_instance = new showDoubleFloatArrays(); // just for debugging?
sdfa_instance.showArrays(img_data, tilesX, tilesY, true, "final_surfaces",titles);
}
return true;
return assignments_dbg;
}
//======================
......
......@@ -76,6 +76,12 @@ public class TileSurface {
static int CLUST_NUM_CONFLICTS_B = 6;
static int CLUST_NUM_STATS = 7;
static int ASGN_DISP = 0;
static int ASGN_A_DISP = 1;
static int ASGN_A_NAN = 2;
static int ASGN_INDX = 3;
static int ASGN_STRENGTH = 4;
static int ASGN_NG = 5;
// private int nsTilesstSize = 0; // 8;
......@@ -2776,6 +2782,57 @@ public class TileSurface {
public void showAssignment(
String title,
final double [][][] dispStrength)
{
String [] titles = getTitlesAssignment(dispStrength);
double [][] img_data = getShowAssignment(dispStrength);
(new showDoubleFloatArrays()).showArrays(img_data, imageTilesX, imageTilesY, true, title, titles);
}
public double [][] getShowAssignment(
final double [][][] dispStrength)
{
double [][] img_data = new double [ASGN_NG * tileLayers.length][];
for (int ml = 0; ml < tileLayers.length; ml ++){
if (dispStrength[ml] != null) {
img_data[ASGN_NG * ml + ASGN_DISP] = dispStrength[ml][0];
img_data[ASGN_NG * ml + ASGN_STRENGTH] = dispStrength[ml][1];
img_data[ASGN_NG * ml + ASGN_A_DISP] = new double [dispStrength[ml][0].length];
img_data[ASGN_NG * ml + ASGN_A_NAN] = new double [dispStrength[ml][0].length];
img_data[ASGN_NG * ml + ASGN_INDX] = new double [dispStrength[ml][0].length];
for (int nTile = 0; nTile < dispStrength[ml][0].length; nTile++){
int nSurfTile = getSurfaceTileIndex(nTile);
if (tileLayers[ml][nTile] > 0){
img_data[ASGN_NG * ml + ASGN_A_DISP][nTile] = tileData[nSurfTile][tileLayers[ml][nTile]-1].getDisparity();
img_data[ASGN_NG * ml + ASGN_A_NAN][nTile] = tileData[nSurfTile][tileLayers[ml][nTile]-1].getDisparity();
} else {
img_data[ASGN_NG * ml + ASGN_A_DISP][nTile] = dispStrength[ml][0][nTile];
img_data[ASGN_NG * ml + ASGN_A_NAN][nTile] = Double.NaN;
}
img_data[ASGN_NG * ml + ASGN_INDX][nTile] = tileLayers[ml][nTile];
}
}
}
return img_data;
}
public String [] getTitlesAssignment(
final double [][][] dispStrength)
{
int ng = 5;
String [] titles = new String[ng * tileLayers.length];
for (int ml = 0; ml < tileLayers.length; ml ++){
titles[ng * ml + ASGN_DISP] = "disp_"+ml;
titles[ng * ml + ASGN_A_DISP] = "a_disp_"+ml;
titles[ng * ml + ASGN_A_NAN] = "a_nan_"+ml;
titles[ng * ml + ASGN_INDX] = "index_"+ml;
titles[ng * ml + ASGN_STRENGTH] = "strength_"+ml;
}
return titles;
}
public void showAssignment_old(
String title,
final double [][][] dispStrength)
{
int layer_disp = 0;
int layer_a_disp = 1;
......@@ -2816,6 +2873,7 @@ public class TileSurface {
sdfa_instance.showArrays(img_data, imageTilesX, imageTilesY, true, title, titles);
}
/**
* Unassign tiles that have too few connected other tiles (or total weight of the cluster is too small)
* This is a single-threaded method
......
......@@ -21,10 +21,14 @@
**
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Properties;
import ij.IJ;
import ij.ImagePlus;
......@@ -33,6 +37,22 @@ import ij.Prefs;
import ij.io.FileSaver;
public class TwoQuadCLT {
public static int DSI_DISPARITY_MAIN = 0;
public static int DSI_DISPARITY_AUX = 1;
public static int DSI_DISPARITY_RIG = 2;
public static int DSI_DISPARITY_X3D = 3;
public static int DSI_STRENGTH_MAIN = 4;
public static int DSI_STRENGTH_AUX = 5;
public static int DSI_STRENGTH_RIG = 6;
public static String [] DSI_SLICES =
{ "disparity_main",
"disparity_aux",
"disparity_rig",
"disparity_x3d",
"strength_main",
"strength_aux",
"strength_rig"};
public long startTime; // start of batch processing
public long startSetTime; // start of set processing
public long startStepTime; // start of step processing
......@@ -40,6 +60,7 @@ public class TwoQuadCLT {
PoleProcessor poleProcessor_persistent;
public QuadCLT quadCLT_main = null;
public QuadCLT quadCLT_aux = null;
public double [][] dsi = new double [DSI_SLICES.length][];
public TwoQuadCLT(
QuadCLT quadCLT_main,
......@@ -1437,6 +1458,9 @@ if (debugLevel > -100) return true; // temporarily !
selection, // boolean [] selection,
rig_disparity_strength[0], // double [] disparity,
rig_disparity_strength[1]); // double [] strength,
if (dbg_sel!=null) dbg_sel[3] = selection.clone();
if (clt_parameters.rig.rf_master_infinity) {
......@@ -1467,6 +1491,18 @@ if (debugLevel > -100) return true; // temporarily !
null, // boolean [] selection,
rig_disparity_strength[0], // double [] disparity,
rig_disparity_strength[1]); // double [] strength)
selection_lone = biCamDSI.selectNearOverInfinity(
clt_parameters.rig.ltgrp_min_strength, // double min_strength,
clt_parameters.rig.ltgrp_min_neibs, // int min_neibs,
clt_parameters.rig.ltgrp_gr_min_disparity, // double min_disparity,
clt_parameters.rig.ltgrp_gr_disp_atolerance, // double disp_atolerance,
clt_parameters.rig.ltgrp_gr_disp_rtolerance, // double disp_rtolerance,
infinity_select, // boolean [] infinity_select,
selection, // boolean [] selection,
rig_disparity_strength[0], // double [] disparity,
rig_disparity_strength[1]); // double [] strength,
// add this selection, but keep it too till after filtering
selection = biCamDSI.combineSelections(
selection, // boolean [] selection1,
......@@ -5323,6 +5359,7 @@ if (debugLevel > -100) return true; // temporarily !
CorrectionColorProc.ColorGainsParameters channelGainParameters,
EyesisCorrectionParameters.RGBParameters rgbParameters,
EyesisCorrectionParameters.EquirectangularParameters equirectangularParameters,
Properties properties,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int debugLevel) throws Exception
......@@ -5625,6 +5662,37 @@ if (debugLevel > -100) return true; // temporarily !
quadCLT_main.tp.resetCLTPasses();
quadCLT_aux.tp.resetCLTPasses();
if (quadCLT_main.correctionsParameters.clt_batch_dsi_aux) {
if (updateStatus) IJ.showStatus("Building basic DSI for the aux camera image set "+quadCLT_main.image_name+" (for DSI export)");
quadCLT_aux.preExpandCLTQuad3d( // returns ImagePlus, but it already should be saved/shown
imp_srcs_aux, // [srcChannel], // should have properties "name"(base for saving results), "channel","path"
saturation_imp_aux, // boolean [][] saturation_imp, // (near) saturated pixels or null
clt_parameters,
debayerParameters,
colorProcParameters,
rgbParameters,
threadsMax, // maximal number of threads to launch
updateStatus,
debugLevelInner);
if (updateStatus) IJ.showStatus("Expanding DSI for the aux camera image set "+quadCLT_main.image_name+" (for DSI export)");
quadCLT_aux.expandCLTQuad3d( // returns ImagePlus, but it already should be saved/shown
clt_parameters,
debayerParameters,
colorProcParameters,
channelGainParameters,
rgbParameters,
threadsMax, // maximal number of threads to launch
updateStatus,
debugLevel);
double [][] aux_last_scan = quadCLT_aux.tp.getShowDS(
quadCLT_aux.tp.clt_3d_passes.get( quadCLT_aux.tp.clt_3d_passes.size() -1),
false); // boolean force_final);
dsi[DSI_DISPARITY_AUX] = aux_last_scan[0];
dsi[DSI_STRENGTH_AUX] = aux_last_scan[1];
quadCLT_aux.tp.resetCLTPasses();
}
if (quadCLT_main.correctionsParameters.clt_batch_explore) {
if (updateStatus) IJ.showStatus("Building basic DSI for the main camera image set "+quadCLT_main.image_name+" (after all adjustments)");
quadCLT_main.preExpandCLTQuad3d( // returns ImagePlus, but it already should be saved/shown
......@@ -5647,6 +5715,15 @@ if (debugLevel > -100) return true; // temporarily !
threadsMax, // maximal number of threads to launch
updateStatus,
debugLevel);
double [][] main_last_scan = quadCLT_main.tp.getShowDS(
quadCLT_main.tp.clt_3d_passes.get( quadCLT_main.tp.clt_3d_passes.size() -1),
false); // boolean force_final);
dsi[DSI_DISPARITY_MAIN] = main_last_scan[0];
dsi[DSI_STRENGTH_MAIN] = main_last_scan[1];
// CLTPass3d scan_last = quadCLT_main.tp.clt_3d_passes.get( quadCLT_main.tp.clt_3d_passes.size() -1);
if (updateStatus) IJ.showStatus("Creating \"ground truth\" DSI using dual-camera rig "+quadCLT_main.image_name);
groundTruth( // actually there is no sense to process multiple image sets. Combine with other processing?
quadCLT_main, // QuadCLT quadCLT_main,
......@@ -5655,6 +5732,12 @@ if (debugLevel > -100) return true; // temporarily !
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevelInner-2); // final int debugLevel);
double [][] rig_last_scan = quadCLT_main.tp.getShowDS(
quadCLT_main.tp.clt_3d_passes.get( quadCLT_main.tp.clt_3d_passes.size() -1),
false); // boolean force_final);
dsi[DSI_DISPARITY_RIG] = rig_last_scan[0];
dsi[DSI_STRENGTH_RIG] = rig_last_scan[1];
} else {
continue;
......@@ -5677,13 +5760,17 @@ if (debugLevel > -100) return true; // temporarily !
if (quadCLT_main.correctionsParameters.clt_batch_assign) {
if (updateStatus) IJ.showStatus("Assigning tiles to candidate surfaces "+quadCLT_main.image_name);
boolean ok = quadCLT_main.tp.assignTilesToSurfaces(
double [][] assignments_dbg = quadCLT_main.tp.assignTilesToSurfaces(
clt_parameters,
quadCLT_main.geometryCorrection,
threadsMax,
updateStatus,
debugLevelInner);
if (!ok) continue;
if (assignments_dbg == null) continue;
dsi[DSI_DISPARITY_X3D] = assignments_dbg[TileSurface.ASGN_A_DISP];
// TODO use assignments_dbg
} else continue; // if (correctionsParameters.clt_batch_assign)
if (quadCLT_main.correctionsParameters.clt_batch_gen3d) {
......@@ -5699,6 +5786,22 @@ if (debugLevel > -100) return true; // temporarily !
} else continue; // if (correctionsParameters.clt_batch_gen3d)
if (quadCLT_main.correctionsParameters.clt_batch_dsi) {
saveDSI (clt_parameters);
}
if (quadCLT_main.correctionsParameters.clt_batch_save_extrinsics) {
saveProperties(
null, // String path, // full name with extension or w/o path to use x3d directory
null, // Properties properties, // if null - will only save extrinsics)
debugLevel);
}
if (quadCLT_main.correctionsParameters.clt_batch_save_all) {
saveProperties(
null, // String path, // full name with extension or w/o path to use x3d directory
properties, // Properties properties, // if null - will only save extrinsics)
debugLevel);
}
Runtime.getRuntime().gc();
if (debugLevel >-1) System.out.println("Processing set "+(nSet+1)+" (of "+set_channels_aux.length+") finished at "+
IJ.d2s(0.000000001*(System.nanoTime()-this.startTime),3)+" sec, --- Free memory="+Runtime.getRuntime().freeMemory()+" (of "+Runtime.getRuntime().totalMemory()+")");
......@@ -5715,5 +5818,89 @@ if (debugLevel > -100) return true; // temporarily !
}
public void saveDSI(
EyesisCorrectionParameters.CLTParameters clt_parameters)
{
String x3d_path= quadCLT_main.correctionsParameters.selectX3dDirectory( // for x3d and obj
quadCLT_main.correctionsParameters.getModelName(quadCLT_main.image_name), // quad timestamp. Will be ignored if correctionsParameters.use_x3d_subdirs is false
quadCLT_main.correctionsParameters.x3dModelVersion,
true, // smart,
true); //newAllowed, // save
String title = quadCLT_main.image_name+"-DSI_COMBO";
ImagePlus imp = (new showDoubleFloatArrays()).makeArrays(dsi,quadCLT_main.tp.getTilesX(), quadCLT_main.tp.getTilesY(), title, DSI_SLICES);
quadCLT_main.eyesisCorrections.saveAndShow(
imp, // ImagePlus imp,
x3d_path, // String path,
false, // boolean png,
false, // boolean show,
0); // int jpegQuality)
}
public void showDSI()
{
String title = quadCLT_main.image_name+"-DSI_COMBO";
(new showDoubleFloatArrays()).showArrays(dsi,quadCLT_main.tp.getTilesX(), quadCLT_main.tp.getTilesY(), true, title, DSI_SLICES);
}
public void saveProperties(
String path, // full name with extension or w/o path to use x3d directory
Properties properties, // if null - will only save extrinsics)
int debugLevel)
{
// update properties from potentially modified parameters (others should be updated
if (path == null) {
path = quadCLT_main.image_name + ((properties == null) ? "-EXTRINSICS":"")+".corr-xml";
}
if (!path.contains(Prefs.getFileSeparator())) {
String x3d_path= quadCLT_main.correctionsParameters.selectX3dDirectory( // for x3d and obj
quadCLT_main.correctionsParameters.getModelName(quadCLT_main.image_name), // quad timestamp. Will be ignored if correctionsParameters.use_x3d_subdirs is false
quadCLT_main.correctionsParameters.x3dModelVersion,
true, // smart,
true); //newAllowed, // save
path = x3d_path+Prefs.getFileSeparator()+path;
}
if (properties == null) {
properties = new Properties();
}
quadCLT_main.setProperties(QuadCLT.PREFIX,properties);
quadCLT_aux.setProperties(QuadCLT.PREFIX_AUX,properties);
OutputStream os;
try {
os = new FileOutputStream(path);
} catch (FileNotFoundException e1) {
// missing config directory
File dir = (new File(path)).getParentFile();
if (!dir.exists()){
dir.mkdirs();
try {
os = new FileOutputStream(path);
} catch (FileNotFoundException e2) {
IJ.showMessage("Error","Failed to create directory "+dir.getName()+" to save configuration file: "+path);
return;
}
} else {
IJ.showMessage("Error","Failed to open configuration file: "+path);
return;
}
}
try {
properties.storeToXML(os,
"last updated " + new java.util.Date(), "UTF8");
} catch (IOException e) {
IJ.showMessage("Error","Failed to write XML configuration file: "+path);
return;
}
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (debugLevel> -3) {
System.out.println("Configuration parameters are saved to "+path);
}
}
}
......@@ -228,6 +228,29 @@ import ij.process.ImageProcessor;
} else imp[i]=null;
return imp;
}
public ImagePlus makeArrays(double[][] pixels, int width, int height, String title, String [] titles) {
int i,j;
if (pixels==null) {
System.out.println("showDoubleFloatArrays.makeArrays(): - pixel array is null");
}
float [] fpixels;
ImageStack array_stack=new ImageStack(width,height);
boolean not_empty = false;
for (i=0;i<pixels.length;i++) if (pixels[i]!=null) {
not_empty = true;
fpixels=new float[pixels[i].length];
for (j=0;j<fpixels.length;j++) fpixels[j]=(float)pixels[i][j];
array_stack.addSlice(titles[i], fpixels);
}
if (not_empty) {
ImagePlus imp_stack = new ImagePlus(title, array_stack);
imp_stack.getProcessor().resetMinAndMax();
// imp_stack.show();
return imp_stack;
}
return null;
}
public ImagePlus [] makeArrays(double[][] pixels, int width, int height, String [] titles) {
int i,j;
float [] fpixels;
......
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