Commit 2ea2b2c9 authored by Andrey Filippov's avatar Andrey Filippov

More work on low-textured areas with bi-quad camera

parent b3cf8b8a
......@@ -5,7 +5,7 @@
**
** -----------------------------------------------------------------------------**
**
** TwoQuadCLT.java is free software: you can redistribute it and/or modify
** BiCamDSI.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.
......@@ -25,13 +25,52 @@ import java.util.ArrayList;
public class BiCamDSI {
// public int tilesX;
// public int tilesY;
TileNeibs tnImage; // = new TileNeibs(tilesX, tilesY)
TileNeibs tnImage; // = new TileNeibs(tilesX, tilesY)
int threadsMax;
ArrayList<BiScan> biScans;
public int addBiScan(
double [] disparity,
double [] strength,
boolean [] trusted,
boolean [] disabled) {
if (biScans == null) biScans = new ArrayList<BiScan>();
biScans.add(new BiScan(this, biScans.size(), disparity, strength, trusted, disabled));
return biScans.size()-1;
}
public int addBiScan(
double [][] disparity_bimap) {
return addBiScan(
disparity_bimap[ImageDtt.BI_TARGET_INDEX], // double [] disparity,
disparity_bimap[ImageDtt.BI_STR_CROSS_INDEX], // double [] strength,
null, // boolean [] trusted,
null); // boolean [] disabled)
}
public BiScan getLastBiScan() {
return getBiScan(-1);
}
public BiScan getBiScan(int indx) {
if (biScans.isEmpty()) return null;
return biScans.get((indx>=0)? indx: (biScans.size() - 1));
}
public double [] getTargetDisparity(int indx) {
BiScan biScan = getBiScan(indx);
if (biScan == null) return null;
return biScan.target_disparity;
}
public BiCamDSI(
int tilesX,
int tilesY) {
int tilesY,
int threadsMax) {
this.threadsMax = threadsMax;
tnImage = new TileNeibs(tilesX, tilesY);
}
......
......@@ -97,8 +97,49 @@ public class BiQuadParameters {
public int lt_stray_dist = 2; // How far to look (and erase) around a potentially falsely matched tile
public double lt_stray_over = 2.0; // stray tile should be this stronger than the strongest neighbor to be recognized
// Rig ltfar - recovering far objects that could not be resolved with just a single quad camera
// Rig plane-based low texture filtering (may replace lt_*
// int [] calcTrusted(
public boolean pf_last_priority = false; // If true, copy last valid tile, false - strongest
public double pf_trusted_strength = 0.25; // strength sufficient without neighbors
public double pf_strength_rfloor = 0.28; // fraction of trusted strength to subtract
public double pf_cond_rtrusted = 0.4; // strength sufficient with neighbors support, fraction of lt_trusted_strength
public double pf_strength_pow = 1.0; // raise strength-floor to this power
public double pf_disp_afloor = 0.1; // When selecting the best fit from the alternative disparities, divide by difference increased by this
public double pf_disp_rfloor = 0.02; // Increase pf_disp_afloor for large disparities
public int pf_smpl_radius = 5; // how far to extend around known tiles (probably should increase this value up to?
public int pf_smpl_num = 8; // Number after removing worst (should be >1)
public int pf_smpl_num_narrow = 5; // = 3; // Number after removing worst (should be >1)
public double pf_smpl_fract = 0.5; // Number of friends among all neighbors
public double pf_max_adiff = 0.15; // Maximal absolute difference betweenthe center tile and friends
public double pf_max_rdiff = 0.04; // Maximal relative difference between the center tile and friends
public double pf_max_atilt = 2.0; // pix per tile
public double pf_max_rtilt = 0.2; // (pix / disparity) per tile
public double pf_smpl_arms = 0.1; // Maximal RMS of the remaining tiles in a sample
public double pf_smpl_rrms = 0.005; // Maximal RMS/disparity in addition to smplRms
public double pf_damp_tilt = 0.001; // Tilt cost for damping insufficient plane data
public double pf_rwsigma = 0.7; // influence of far neighbors diminish as a Gaussian with this sigma
public double pf_rwsigma_narrow = 0.2; // used to determine initial tilt ( 1/radius)
// int trimWeakFG(
public boolean pf_en_trim_fg = false; // Trim weak FZG
public double pf_atolerance = 0.2; // When deciding closer/farther
public double pf_rtolerance = 0.04; // Same; scaled with disparity
public int pf_num_dirs = 8; // Number of directions to try when trimming hanging weak FG
public double pf_blind_dist = 0.5; // How far start tiles in selected direction
public boolean pf_strong_only_far = false; // Only strong trusted far tiles make this FG "hanging" (false - any trusted)
public int pf_num_strong_far = 1; // Number strong trusted far tiles make this FG "hanging"
public int pf_num_weak_far = 3; // Number weak trusted far tiles make this FG "hanging"
// int suggestNewScan(
public boolean pf_discard_cond = true; // Consider conditionally trusted tiles (not promoted to trusted) as empty,
public boolean pf_discard_weak = true; // If true, suggest new disparities over even weak trusted tiles
public boolean pf_discard_strong = false; // If true, suggest new disparities over even strong trusted tiles
public double pf_new_diff = 0.5; // Minimal disparity (in master camera pixels) difference between the new suggested and the already tried/measured one
public int pf_min_new = 5; // Minimal number of he new tiles during rig refine for plane filter
// Rig ltfar - recovering far objects that could not be resolved with just a single quad camera
public boolean ltfar_en = true; // Enable recovering far objects over infinity area
public boolean ltfar_auto_floor = true; // Automatically detect strength floor (false - use (lt_trusted_strength*lt_strength_rfloor)
public double ltfar_min_disparity = 0.04; // Minimal tile disparity (in master camera pixels) to try to recover
......@@ -116,6 +157,7 @@ public class BiQuadParameters {
public double ltfar_trusted_d = 0.2; // Add even single tiles over infinity if disparity (and strength too) is sufficient
// rig selection filtering
public boolean rf_master_infinity = true; // Combine with master camera selection over infinity
public boolean rf_master_near = false; // Combine with master camera selection over non-infinity
......@@ -131,6 +173,9 @@ public class BiQuadParameters {
public double rf_min_disp = 0.02; // Minimal tile disparity to keep in scan
public boolean rf_remove_unselected = true; // Remove tiles that are not selected
public int ml_hwidth = 2; // Half-width of the ML tiles to export (0-> 1x1, 1->3x3, 2 -> 5x5)
public double ml_disparity_sweep = 2.0; // Disparity sweep around ground truth, each side
public int ml_sweep_steps = 5; // Number of disparity sweep steps
......@@ -281,6 +326,82 @@ public class BiQuadParameters {
"Find the maximal strength of the neighbors, and consider a false match if the suspect is this times stronger");
gd.addTab("Rig plane filter","Rig plane-based filtering of low-textured areas");
gd.addCheckbox ("Copy tile from the last valid measurement, false - copy strongest", this.pf_last_priority,
"When copying data that was not measured in last scan, use the latest valid measurement. If unchecked - use the strongest disparity");
gd.addNumericField("Strength sufficient without neighbors", this.pf_trusted_strength, 4,6,"",
"Unconditionally trusted tile. Other stength values are referenceds as fraction of this value (after strength floor subtraction)");
gd.addNumericField("Fraction of trusted strength to subtract", this.pf_strength_rfloor, 4,6,"",
"Strength floor to subtract from all strength values");
gd.addNumericField("Strength sufficient with neighbors support, fraction of the trusted strength", this.pf_cond_rtrusted, 4,6,"",
"Strength that may be valid for the tile if there are neighbors in the same possibly tilted plane of the DSI (floor corrected)");
gd.addNumericField("Raise strength-floor to this power", this.pf_strength_pow, 4,6,"",
"Currently just 1.0 - lenear");
gd.addNumericField("Add to disparity mismatch when looking for the best fit", this.pf_disp_afloor, 4,6,"pix",
"When selecting the best fit from the alternative disparities, divide by difference increased by this");
gd.addNumericField("Add to disparity mismatch when looking for the best fit, per disparity pixel", this.pf_disp_rfloor, 4,6,"pix/pix",
"Add to the previous value proportionally to the absolute mdean disparity");
gd.addNumericField("How far to extend around known tiles (probably should increase this value up to?", this.pf_smpl_radius, 0,3,"tiles",
"Process a aquare centered at the current tile withthe side of twice this value plus 1 (2*pf_smpl_radius + 1)");
gd.addNumericField("Number after remaining in the sample square after removing worst fitting tiles", this.pf_smpl_num, 0,3,"",
"When fitting planes the outliers are removed until the number of remaining tiles equals this value");
gd.addNumericField("Number of remaining tiles when using narrow selection", this.pf_smpl_num_narrow, 0,3,"",
"Number of remaining tiles during initial palne fitting to the center pixels (it is later extended to include farther tiles)");
gd.addNumericField("Fraction of the reamining tiles of all non-zero tiles?", this.pf_smpl_fract, 4,6,"",
"This value is combined to the previous one (absilute). Maximal of absolute and relative times number of all non-empty tiles is used");
gd.addNumericField("Maximal absolute disparity difference between the plane and tiles that fit", this.pf_max_adiff, 4,6,"pix",
"Maximal absolute disparity difference for fitting. Combined with the next one (relative) ");
gd.addNumericField("Maximal relative (to center disparity) difference between the plane and tiles that fit",this.pf_max_rdiff, 4,6,"pix/pix",
"This value is multipled by the tile disparity and added to the maximal absolute difference");
gd.addNumericField("Maximal absolute tile tilt in DSI space", this.pf_max_atilt, 4,6,"pix/tile",
"Maximal disparity difference betweeing neighbor tiles for the tilted plane. Combined with the relative one (next), min of both limits applies");
gd.addNumericField("Maximal relative (per pixel of disparity) tile tilt in DSI space", this.pf_max_rtilt, 4,6,"1/tile",
"Maximal relative (to center disparity) tilt. Near tiles (larger disparity may have larger differnce.");
gd.addNumericField("Maximal absolute RMS of the remaining tiles in a sample", this.pf_smpl_arms, 4,6,"pix",
"After removing outliers RMS of the remaining tiles must be less than this value");
gd.addNumericField("Maximal relative (to center disparity) RMS of the remaining tiles in a sample", this.pf_smpl_rrms, 4,6,"pix/pix",
"Relative RMS times disparity is added to the absolute one");
gd.addNumericField("Tilt cost for damping insufficient plane data", this.pf_damp_tilt, 4,6,"",
"Regularisation to handle co-linear and even single-point planes, forcing fronto-parallel for single point, and minimal tilt for co-linear set");
gd.addNumericField("Influence of far neighbors is reduced as a Gaussian with this sigma", this.pf_rwsigma, 4,6,"",
"Sigma is relative to selection radius (square half-side)");
gd.addNumericField("Weight function Gaussian sigma (relative to radius) for initial plane fitting", this.pf_rwsigma_narrow, 4,6,"",
"Weight function Gaussian sigma (relative to selection radius) for initial plane fitting. May be ~=1/radius");
gd.addCheckbox ("Trim hanging FG", this.pf_en_trim_fg,
"Try trimming hanging FG (need improvement)");
gd.addNumericField("Absolute tolerane to determine that a tile is a background one for the selected plane",this.pf_atolerance, 4,6,"pix",
"When a tile has disparity smaller than a plane by more than this value it is considered to be farther (in backgeround)");
gd.addNumericField("Relative (to center tile disaprity) disaprity tolerance to distinguish between FG and BG", this.pf_rtolerance, 4,6,"pix/pix",
"Product of this value by the center disparity is added to the absolute tolerance (above)?");
gd.addNumericField("How many directions to look into (evenly of all 360) when trimming weak FG", this.pf_num_dirs, 0,3,"",
"Weak FG trimming (after more permissive bridging over gaps) assumes that the FG adge should be strong, it looks in specified number of directions");
gd.addNumericField("FG trimming blind disatance", this.pf_blind_dist, 4,6,"tiles",
"Do not count offenders closer than this to the center tile");
gd.addCheckbox ("Only strong trusted far tiles make this FG \"hanging\"", this.pf_strong_only_far,
"When false, any BG tile without this plane strong tiles will trigger trimming, true - only strong trusted tiles");
gd.addNumericField("Number strong trusted far tiles make this FG \"hanging\"", this.pf_num_strong_far, 0,3,"",
"Number of strong trusted far tiles to make this plane hanging");
gd.addNumericField("Number weak trusted far tiles make this FG \"hanging\"", this.pf_num_weak_far, 0,3,"",
"Number of weak trusted far tiles to make this plane hanging");
gd.addCheckbox ("Suggest new disparity over any but confirmed trusted tiles, false - only over empty", this.pf_discard_cond,
"When checked - disregard any conditionally trusted tiles that were not confirmed trusted by neighbors, false - only suggest for yet empty tiles");
gd.addCheckbox ("Suggest new disparity over any but strong trusted tiles", this.pf_discard_weak,
"When checked - disregard any weak trusted tiles, even confirmed.Only keep strong ones");
gd.addCheckbox ("Suggest new disparity over any tile, even strong trusted", this.pf_discard_strong,
"When checked - try new disparity even for strong tiles");
gd.addNumericField("Minimal diasparity difference between the new suggested and existing one", this.pf_new_diff, 4,6,"pix",
"Minimal diasparity (in master camera pixels) difference between the new suggested and the already tried (set for measurement) or measured (refined) one");
gd.addNumericField("Minimal refined tiles during plane filter", this.pf_min_new, 0,3,"",
"Repeat refine antill less tiles are updated");
gd.addTab("Rig Far","Parameters related to the ML files generation for the dual-quad camera rig");
gd.addCheckbox ("Enable recovering far objects over infinity area", this.ltfar_en,
"Try to use tiles that were treated as infinity by a single quad camera");
......@@ -310,6 +431,10 @@ public class BiQuadParameters {
"Add strong tiles over infinity areas that have both strenth and disparity above respective thersholds (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)");
gd.addTab("Rig selection","Rig tile selection filter");
gd.addCheckbox ("Combine with master camera selection over infinity", this.rf_master_infinity,
"'OR' selection with previos tile selection for master camera over infinity areas");
gd.addCheckbox ("Combine with master camera selection over non-infinity", this.rf_master_near,
......@@ -428,6 +553,44 @@ public class BiQuadParameters {
this.lt_stray_dist= (int) gd.getNextNumber();
this.lt_stray_over= gd.getNextNumber();
this.pf_last_priority= gd.getNextBoolean();
this.pf_trusted_strength= gd.getNextNumber();
this.pf_strength_rfloor= gd.getNextNumber();
this.pf_cond_rtrusted= gd.getNextNumber();
this.pf_strength_pow= gd.getNextNumber();
this.pf_disp_afloor= gd.getNextNumber();
this.pf_disp_rfloor= gd.getNextNumber();
this.pf_smpl_radius= (int) gd.getNextNumber();
this.pf_smpl_num= (int) gd.getNextNumber();
this.pf_smpl_num_narrow= (int) gd.getNextNumber();
this.pf_smpl_fract= gd.getNextNumber();
this.pf_max_adiff= gd.getNextNumber();
this.pf_max_rdiff= gd.getNextNumber();
this.pf_max_atilt= gd.getNextNumber();
this.pf_max_rtilt= gd.getNextNumber();
this.pf_smpl_arms= gd.getNextNumber();
this.pf_smpl_rrms= gd.getNextNumber();
this.pf_damp_tilt= gd.getNextNumber();
this.pf_rwsigma= gd.getNextNumber();
this.pf_rwsigma_narrow= gd.getNextNumber();
this.pf_en_trim_fg= gd.getNextBoolean();
this.pf_atolerance= gd.getNextNumber();
this.pf_rtolerance= gd.getNextNumber();
this.pf_num_dirs= (int) gd.getNextNumber();
this.pf_blind_dist= gd.getNextNumber();
this.pf_strong_only_far= gd.getNextBoolean();
this.pf_num_strong_far= (int) gd.getNextNumber();
this.pf_num_weak_far= (int) gd.getNextNumber();
this.pf_discard_cond= gd.getNextBoolean();
this.pf_discard_weak= gd.getNextBoolean();
this.pf_discard_strong= gd.getNextBoolean();
this.pf_new_diff= gd.getNextNumber();
this.pf_min_new= (int) gd.getNextNumber();
this.ltfar_en= gd.getNextBoolean();
this.ltfar_auto_floor= gd.getNextBoolean();
this.ltfar_min_disparity= gd.getNextNumber();
......@@ -536,6 +699,41 @@ public class BiQuadParameters {
properties.setProperty(prefix+"lt_stray_dist", this.lt_stray_dist+"");
properties.setProperty(prefix+"lt_stray_over", this.lt_stray_over+"");
properties.setProperty(prefix+"pf_last_priority", this.pf_last_priority+"");
properties.setProperty(prefix+"pf_trusted_strength", this.pf_trusted_strength+"");
properties.setProperty(prefix+"pf_strength_rfloor", this.pf_strength_rfloor+"");
properties.setProperty(prefix+"pf_cond_rtrusted", this.pf_cond_rtrusted+"");
properties.setProperty(prefix+"pf_strength_pow", this.pf_strength_pow+"");
properties.setProperty(prefix+"pf_disp_afloor", this.pf_disp_afloor+"");
properties.setProperty(prefix+"pf_disp_rfloor", this.pf_disp_rfloor+"");
properties.setProperty(prefix+"pf_smpl_radius", this.pf_smpl_radius+"");
properties.setProperty(prefix+"pf_smpl_num", this.pf_smpl_num+"");
properties.setProperty(prefix+"pf_smpl_num_narrow", this.pf_smpl_num_narrow+"");
properties.setProperty(prefix+"pf_smpl_fract", this.pf_smpl_fract+"");
properties.setProperty(prefix+"pf_max_adiff", this.pf_max_adiff+"");
properties.setProperty(prefix+"pf_max_rdiff", this.pf_max_rdiff+"");
properties.setProperty(prefix+"pf_max_atilt", this.pf_max_atilt+"");
properties.setProperty(prefix+"pf_max_rtilt", this.pf_max_rtilt+"");
properties.setProperty(prefix+"pf_smpl_arms", this.pf_smpl_arms+"");
properties.setProperty(prefix+"pf_smpl_rrms", this.pf_smpl_rrms+"");
properties.setProperty(prefix+"pf_damp_tilt", this.pf_damp_tilt+"");
properties.setProperty(prefix+"pf_rwsigma", this.pf_rwsigma+"");
properties.setProperty(prefix+"pf_rwsigma_narrow", this.pf_rwsigma_narrow+"");
properties.setProperty(prefix+"pf_en_trim_fg", this.pf_en_trim_fg+"");
properties.setProperty(prefix+"pf_atolerance", this.pf_atolerance+"");
properties.setProperty(prefix+"pf_rtolerance", this.pf_rtolerance+"");
properties.setProperty(prefix+"pf_num_dirs", this.pf_num_dirs+"");
properties.setProperty(prefix+"pf_blind_dist", this.pf_blind_dist+"");
properties.setProperty(prefix+"pf_strong_only_far", this.pf_strong_only_far+"");
properties.setProperty(prefix+"pf_num_strong_far", this.pf_num_strong_far+"");
properties.setProperty(prefix+"pf_num_weak_far", this.pf_num_weak_far+"");
properties.setProperty(prefix+"pf_discard_cond", this.pf_discard_cond+"");
properties.setProperty(prefix+"pf_discard_weak", this.pf_discard_weak+"");
properties.setProperty(prefix+"pf_discard_strong", this.pf_discard_strong+"");
properties.setProperty(prefix+"pf_new_diff", this.pf_new_diff+"");
properties.setProperty(prefix+"pf_min_new", this.pf_min_new+"");
properties.setProperty(prefix+"ltfar_en", this.ltfar_en+"");
properties.setProperty(prefix+"ltfar_auto_floor", this.ltfar_auto_floor+"");
properties.setProperty(prefix+"ltfar_min_disparity", this.ltfar_min_disparity+"");
......@@ -642,8 +840,45 @@ public class BiQuadParameters {
if (properties.getProperty(prefix+"lt_stray_dist")!=null) this.lt_stray_dist=Integer.parseInt(properties.getProperty(prefix+"lt_stray_dist"));
if (properties.getProperty(prefix+"lt_stray_over")!=null) this.lt_stray_over=Double.parseDouble(properties.getProperty(prefix+"lt_stray_over"));
if (properties.getProperty(prefix+"pf_last_priority")!=null) this.pf_last_priority=Boolean.parseBoolean(properties.getProperty(prefix+"pf_last_priority"));
if (properties.getProperty(prefix+"pf_trusted_strength")!=null) this.pf_trusted_strength=Double.parseDouble(properties.getProperty(prefix+"pf_trusted_strength"));
if (properties.getProperty(prefix+"pf_strength_rfloor")!=null) this.pf_strength_rfloor=Double.parseDouble(properties.getProperty(prefix+"pf_strength_rfloor"));
if (properties.getProperty(prefix+"pf_cond_rtrusted")!=null) this.pf_cond_rtrusted=Double.parseDouble(properties.getProperty(prefix+"pf_cond_rtrusted"));
if (properties.getProperty(prefix+"pf_strength_pow")!=null) this.pf_strength_pow=Double.parseDouble(properties.getProperty(prefix+"pf_strength_pow"));
if (properties.getProperty(prefix+"pf_disp_afloor")!=null) this.pf_strength_pow=Double.parseDouble(properties.getProperty(prefix+"pf_disp_afloor"));
if (properties.getProperty(prefix+"pf_disp_rfloor")!=null) this.pf_strength_pow=Double.parseDouble(properties.getProperty(prefix+"pf_disp_rfloor"));
if (properties.getProperty(prefix+"pf_smpl_radius")!=null) this.pf_smpl_radius=Integer.parseInt(properties.getProperty(prefix+"pf_smpl_radius"));
if (properties.getProperty(prefix+"pf_smpl_num")!=null) this.pf_smpl_num=Integer.parseInt(properties.getProperty(prefix+"pf_smpl_num"));
if (properties.getProperty(prefix+"pf_smpl_num_narrow")!=null) this.pf_smpl_num_narrow=Integer.parseInt(properties.getProperty(prefix+"pf_smpl_num_narrow"));
if (properties.getProperty(prefix+"pf_smpl_fract")!=null) this.pf_smpl_fract=Double.parseDouble(properties.getProperty(prefix+"pf_smpl_fract"));
if (properties.getProperty(prefix+"pf_max_adiff")!=null) this.pf_max_adiff=Double.parseDouble(properties.getProperty(prefix+"pf_max_adiff"));
if (properties.getProperty(prefix+"pf_max_rdiff")!=null) this.pf_max_rdiff=Double.parseDouble(properties.getProperty(prefix+"pf_max_rdiff"));
if (properties.getProperty(prefix+"pf_max_atilt")!=null) this.pf_max_atilt=Double.parseDouble(properties.getProperty(prefix+"pf_max_atilt"));
if (properties.getProperty(prefix+"pf_max_rtilt")!=null) this.pf_max_rtilt=Double.parseDouble(properties.getProperty(prefix+"pf_max_rtilt"));
if (properties.getProperty(prefix+"pf_smpl_arms")!=null) this.pf_smpl_arms=Double.parseDouble(properties.getProperty(prefix+"pf_smpl_arms"));
if (properties.getProperty(prefix+"pf_smpl_rrms")!=null) this.pf_smpl_rrms=Double.parseDouble(properties.getProperty(prefix+"pf_smpl_rrms"));
if (properties.getProperty(prefix+"pf_damp_tilt")!=null) this.pf_damp_tilt=Double.parseDouble(properties.getProperty(prefix+"pf_damp_tilt"));
if (properties.getProperty(prefix+"pf_rwsigma")!=null) this.pf_rwsigma=Double.parseDouble(properties.getProperty(prefix+"pf_rwsigma"));
if (properties.getProperty(prefix+"pf_rwsigma_narrow")!=null) this.pf_rwsigma_narrow=Double.parseDouble(properties.getProperty(prefix+"pf_rwsigma_narrow"));
if (properties.getProperty(prefix+"pf_en_trim_fg")!=null) this.pf_en_trim_fg=Boolean.parseBoolean(properties.getProperty(prefix+"pf_en_trim_fg"));
if (properties.getProperty(prefix+"pf_atolerance")!=null) this.pf_atolerance=Double.parseDouble(properties.getProperty(prefix+"pf_atolerance"));
if (properties.getProperty(prefix+"pf_rtolerance")!=null) this.pf_rtolerance=Double.parseDouble(properties.getProperty(prefix+"pf_rtolerance"));
if (properties.getProperty(prefix+"pf_num_dirs")!=null) this.pf_num_dirs=Integer.parseInt(properties.getProperty(prefix+"pf_num_dirs"));
if (properties.getProperty(prefix+"pf_blind_dist")!=null) this.pf_blind_dist=Double.parseDouble(properties.getProperty(prefix+"pf_blind_dist"));
if (properties.getProperty(prefix+"pf_strong_only_far")!=null) this.pf_strong_only_far=Boolean.parseBoolean(properties.getProperty(prefix+"pf_strong_only_far"));
if (properties.getProperty(prefix+"pf_num_strong_far")!=null) this.pf_num_strong_far=Integer.parseInt(properties.getProperty(prefix+"pf_num_strong_far"));
if (properties.getProperty(prefix+"pf_num_weak_far")!=null) this.pf_num_weak_far=Integer.parseInt(properties.getProperty(prefix+"pf_num_weak_far"));
if (properties.getProperty(prefix+"pf_discard_cond")!=null) this.pf_discard_cond=Boolean.parseBoolean(properties.getProperty(prefix+"pf_discard_cond"));
if (properties.getProperty(prefix+"pf_discard_weak")!=null) this.pf_discard_weak=Boolean.parseBoolean(properties.getProperty(prefix+"pf_discard_weak"));
if (properties.getProperty(prefix+"pf_discard_strong")!=null) this.pf_discard_strong=Boolean.parseBoolean(properties.getProperty(prefix+"pf_discard_strong"));
if (properties.getProperty(prefix+"pf_new_diff")!=null) this.pf_new_diff=Double.parseDouble(properties.getProperty(prefix+"pf_new_diff"));
if (properties.getProperty(prefix+"pf_min_new")!=null) this.pf_min_new=Integer.parseInt(properties.getProperty(prefix+"pf_min_new"));
if (properties.getProperty(prefix+"ltfar_en")!=null) this.ltfar_en=Boolean.parseBoolean(properties.getProperty(prefix+"ltfar_en"));
if (properties.getProperty(prefix+"ltfar_auto_floor")!=null) this.ltfar_auto_floor=Boolean.parseBoolean(properties.getProperty(prefix+"ltfar_auto_floor"));
if (properties.getProperty(prefix+"ltfar_min_disparity")!=null) this.ltfar_min_disparity=Double.parseDouble(properties.getProperty(prefix+"ltfar_min_disparity"));
......@@ -750,6 +985,42 @@ public class BiQuadParameters {
bqp.lt_stray_dist= this.lt_stray_dist;
bqp.lt_stray_over= this.lt_stray_over;
bqp.pf_last_priority= this.pf_last_priority;
bqp.pf_trusted_strength= this.pf_trusted_strength;
bqp.pf_strength_rfloor= this.pf_strength_rfloor;
bqp.pf_cond_rtrusted= this.pf_cond_rtrusted;
bqp.pf_strength_pow= this.pf_strength_pow;
bqp.pf_disp_afloor= this.pf_disp_afloor;
bqp.pf_disp_rfloor= this.pf_disp_rfloor;
bqp.pf_smpl_radius= this.pf_smpl_radius;
bqp.pf_smpl_num= this.pf_smpl_num;
bqp.pf_smpl_num_narrow= this.pf_smpl_num_narrow;
bqp.pf_smpl_fract= this.pf_smpl_fract;
bqp.pf_max_adiff= this.pf_max_adiff;
bqp.pf_max_rdiff= this.pf_max_rdiff;
bqp.pf_max_atilt= this.pf_max_atilt;
bqp.pf_max_rtilt= this.pf_max_rtilt;
bqp.pf_smpl_arms= this.pf_smpl_arms;
bqp.pf_smpl_rrms= this.pf_smpl_rrms;
bqp.pf_damp_tilt= this.pf_damp_tilt;
bqp.pf_rwsigma= this.pf_rwsigma;
bqp.pf_rwsigma_narrow= this.pf_rwsigma_narrow;
bqp.pf_en_trim_fg = this.pf_en_trim_fg;
bqp.pf_atolerance= this.pf_atolerance;
bqp.pf_rtolerance= this.pf_rtolerance;
bqp.pf_num_dirs= this.pf_num_dirs;
bqp.pf_blind_dist= this.pf_blind_dist;
bqp.pf_strong_only_far= this.pf_strong_only_far;
bqp.pf_num_strong_far= this.pf_num_strong_far;
bqp.pf_num_weak_far= this.pf_num_weak_far;
bqp.pf_discard_cond= this.pf_discard_cond;
bqp.pf_discard_weak= this.pf_discard_weak;
bqp.pf_discard_strong= this.pf_discard_strong;
bqp.pf_new_diff= this.pf_new_diff;
bqp.pf_min_new= this.pf_min_new;
bqp.ltfar_en= this.ltfar_en;
bqp.ltfar_auto_floor= this.ltfar_auto_floor;
bqp.ltfar_min_disparity= this.ltfar_min_disparity;
......
/**
** BiCamScan - calss to represent bultiple bi-quad camera measurements
**
** Copyright (C) 2018 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** BiCamScan.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.util.concurrent.atomic.AtomicInteger;
public class BiScan {
final static double THRESHOLD_LIN = 1.0E-20; // threshold ratio of matrix determinant to norm for linear approximation (det too low - fail)
final static double THRESHOLD_QUAD = 1.0E-30; // threshold ratio of matrix determinant to norm for quadratic approximation (det too low - fail)
double [] disparity_measured;
double [] target_disparity;
double [] strength_measured;
boolean [] strong_trusted; // sufficient strength without neighbors
boolean [] trusted;
boolean [] cond_trusted;
boolean [] disabled_measurement; // should disable source also
int [] src_index; // index of the source scan which measured data is used here (applies to disparity_measured, strength_measured, disabled_measurement
int list_index = -1;
BiCamDSI biCamDSI;
// public BiScan(BiCamDSI biCamDSI) {
// this.biCamDSI = biCamDSI;
// int num_tiles = biCamDSI.tnImage.getSizeX()*biCamDSI.tnImage.getSizeY();
// disparity= new double[num_tiles];
// strength= new double[num_tiles];
// trusted= new boolean[num_tiles];
// }
public BiScan(
BiCamDSI biCamDSI,
int indx,
double [] disparity,
double [] strength,
boolean [] trusted,
boolean [] disabled) {
this.biCamDSI = biCamDSI;
this.list_index = indx;
int num_tiles = biCamDSI.tnImage.getSizeX()*biCamDSI.tnImage.getSizeY();
if (disparity == null) {
disparity= new double[num_tiles];
} else {
this.disparity_measured = disparity.clone();
if (strength == null) {
strength= new double[num_tiles];
for (int nTile = 0; nTile < num_tiles; nTile++) strength[nTile] = Double.isNaN(disparity[nTile])?0.0:1.0;
} else {
this.strength_measured = strength.clone();
for (int nTile = 0; nTile < num_tiles; nTile++) {
if (Double.isNaN(disparity[nTile])) this.strength_measured [nTile] = 0.0;
if (strength[nTile] == 0.0) this.disparity_measured[nTile] = Double.NaN;
}
}
}
if (trusted == null) trusted= new boolean[num_tiles];
if (disabled == null) disabled= new boolean[num_tiles];
this.trusted = trusted;
this.disabled_measurement = disabled;
this.strong_trusted = new boolean[num_tiles];
this.cond_trusted = new boolean[num_tiles];
src_index = new int[num_tiles];
// set new measurement index to this, other to -1
for (int i = 0; i < num_tiles; i++) {
src_index[i] = (strength[i] > 0.0)? list_index:-1;
}
}
public double [] getDisparityMeasured() { return this.disparity_measured;} // FIXME!
public double [] getStrengthMeasured() { return this.strength_measured;} // FIXME
public boolean [] getTrusted() { return this.trusted;}
public boolean [] getDisabledMeasurement() { return this.disabled_measurement;}
public void disableTile (int nTile) {
trusted[nTile] = false;
strong_trusted[nTile] = false;
cond_trusted[nTile] = false;
// disabled[nTile] = true;
// if ((src_index[nTile] >= 0) && (src_index[nTile] != list_index)) {
if (src_index[nTile] >= 0) {
biCamDSI.getBiScan(src_index[nTile]).disabled_measurement[nTile] = false; // may be source tile or this tile
}
}
/**
* Get disparity and strength from the scan, mask by boolean attributes
* @param only_strong keep only trusted strong tiles
* @param only_trusted keep any trusted tiles
* @param only_enabled keep all but disabled tiles
* @return array of two arrays {disparity, strength}
*/
public double [][] getDisparityStrength( // FIXME
final boolean only_strong,
final boolean only_trusted,
final boolean only_enabled){
final int num_tiles = disparity_measured.length;
final double [][] ds = {disparity_measured.clone(), strength_measured.clone()}; // just to start with
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final BiScan this_scan = this;
// find definitely trusted and conditionally trusted tiles
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()) {
if ((only_strong && !strong_trusted[nTile]) ||
(only_trusted && !trusted[nTile])) {
ds[0][nTile] = Double.NaN;
ds[1][nTile] = 0.0;
} else { //if (src_index[nTile] != list_index){ // only one level of indirection?
int src = src_index[nTile]; // same tile or different
BiScan scan = this_scan;
if (src < 0) {
src = list_index;
} else {
scan = biCamDSI.biScans.get(src);
}
boolean dsbl = scan.disabled_measurement[nTile];
if (dsbl && only_enabled) { // src <0 only for the first scan where no data is available
ds[0][nTile] = Double.NaN;
ds[1][nTile] = 0.0;
} else {
ds[0][nTile] = scan.disparity_measured[nTile];
ds[1][nTile] = scan.strength_measured[nTile];
} // if (dsbl && only_enabled) -- else
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return ds;
}
public void showScan(String title) { // FIXME!
String [] titles= {
"all", // 0
"enabled", // 1
"cond_trusted", // 2
"weak trusted", // 3
"strong trusted", // 4
"measured", // 5
"suggested", // 6
"measured strength", // 7
"strength" }; // 8
double [][] ds_all = getDisparityStrength( // FIXME
false, // final boolean only_strong,
false, // final boolean only_trusted,
false) ; // final boolean only_enabled);
double [][] ds = getDisparityStrength( // FIXME
false, // final boolean only_strong,
false, // final boolean only_trusted,
true) ; // final boolean only_enabled);
double [][] dbg_data = new double[titles.length][];
dbg_data[5] = this.disparity_measured;
dbg_data[0] = ds_all[0];
dbg_data[7] = this.strength_measured;
dbg_data[8] = ds_all[1];
dbg_data[1] = ds[0];
if (this.cond_trusted != null) {
dbg_data[2] = ds[0].clone();
for (int i = 0; i < this.cond_trusted.length; i++) if (!cond_trusted[i]) dbg_data[2][i] = Double.NaN;
}
if (this.trusted != null) {
dbg_data[3] = ds[0].clone();
for (int i = 0; i < this.trusted.length; i++) if (!trusted[i]) dbg_data[3][i] = Double.NaN;
}
if (this.strong_trusted != null) {
dbg_data[4] = ds[0].clone();
for (int i = 0; i < this.strong_trusted.length; i++) if (!strong_trusted[i]) dbg_data[4][i] = Double.NaN;
}
if (this.target_disparity != null) {
dbg_data[6] = this.target_disparity.clone();
}
(new showDoubleFloatArrays()).showArrays(
dbg_data,
biCamDSI.tnImage.getSizeX(),
biCamDSI.tnImage.getSizeY(),
true,
title,
titles);
}
/**
* Reduce outliers on DSI when multiple "refined" disparity values exist for the same tile and the strongest does not seem to be the best
* Each disparity solution is compared to the weighted average of the neighbors and the strength is divided by the difference from that
* average value, so the closest to the neighbors gets strength boost.
* @param str_floor absolute strength to subtract from the measured
* @param pf_disp_afloor offset disparity to add to the disparity difference to avoid division by 0 or small numbers
* @param pf_disp_rfloor realtive to the disparity portion of the offset
* @return number of replaced tiles
*/
public int copyFittestEnabled(
final double str_floor, // absolute strength floor
final double pf_disp_afloor, // = 0.1; // When selecting the best fit from the alternative disparities, divide by difference increased by this
final double pf_disp_rfloor) // = 0.02; // Increase pf_disp_afloor for large disparities
{
final TileNeibs tnImage = biCamDSI.tnImage;
final int num_tiles = biCamDSI.tnImage.getSizeX()*biCamDSI.tnImage.getSizeY();
final double [][] ds = getDisparityStrength( // FIXME
false, // final boolean only_strong,
false, // final boolean only_trusted,
true) ; // final boolean only_enabled);
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final int [] new_src = new int[num_tiles];
final AtomicInteger num_changes = new AtomicInteger(0);
int dbg_x = 157;
int dbg_y = 212;
int debugLevel = -1;
final int dbg_tile = (debugLevel>-2)?(dbg_x + tnImage.sizeX*dbg_y):-1;
ai.set(0);
// find definitely trusted and conditionally trusted tiles
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()) {
if (nTile == dbg_tile) {
System.out.println("copyFittestEnabled(): nTile="+nTile);
}
if (ds[1][nTile] > 0.0 ) { // && (src_index[nTile] != list_index)){ // should be already found
int num_neib = 0;
double sw = 0.0, swd = 0.0;
double wdiag = 0.7;
for (int dir = 0; dir <8; dir++) {
int nTile1 = tnImage.getNeibIndex(nTile, dir);
if ((nTile1 >= 0) && (ds[1][nTile1] > str_floor)) {
double w = ds[1][nTile1] - str_floor;
if ((dir & 1) != 0) w *= wdiag;
sw += w;
swd += ds[0][nTile1] * w;
num_neib++;
}
}
if (num_neib > 0) {
double disp_mean = swd/sw;
double disp_floor = pf_disp_afloor + disp_mean * pf_disp_rfloor;
double disp_floor2 = disp_floor*disp_floor;
int best_indx=-1;
double best_strength =0.0;
for (int indx = list_index; indx >= 0; indx--) { // include the latest measurement
BiScan scan = biCamDSI.getBiScan(indx);
if (scan.disabled_measurement[nTile]) { // || (scan.src_index[nTile] != indx)){ // skip all but enabled
continue;
}
// calculate effective strength
double strength = scan.strength_measured[nTile] - str_floor;
if (strength <= 0) {
continue;
}
double diff = scan.disparity_measured[nTile] - disp_mean;
double eff_strength = strength/Math.sqrt(diff*diff + disp_floor2);
if (eff_strength > best_strength) {
best_strength = eff_strength;
best_indx = indx;
}
}
if ((best_indx >= 0) && (best_indx != src_index[nTile])) { // not the same as already set
new_src[nTile] = best_indx+1; // +1 so initial 0 will be "not set"
num_changes.getAndIncrement();
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (num_changes.get() > 0) {
ai.set(0);
// find definitely trusted and conditionally trusted tiles
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()) {
if (nTile == dbg_tile) {
System.out.println("copyFittestEnabled() 2 : nTile="+nTile);
}
if (new_src[nTile] > 0){
int best_indx = new_src[nTile]-1;
src_index[nTile] = best_indx;
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
// will need trusted* recalculated
return num_changes.get();
}
/**
* Copy data (if the current was not measured) from one of the previous scans - strongest that is not disabled. If last_priority is true
* the latest not disabled scan will be used, even if it is not the strongest
* @param last_priority
*/
public void copyLastStrongestEnabled(
final boolean last_priority) // use last if exists and is not disabled
{
final int num_tiles = biCamDSI.tnImage.getSizeX()*biCamDSI.tnImage.getSizeY();
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
// final boolean [] cond_trusted = new boolean [num_tiles];
strong_trusted = new boolean [num_tiles];
trusted = new boolean [num_tiles];
cond_trusted = new boolean [num_tiles];
ai.set(0);
// find definitely trusted and conditionally trusted tiles
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()) if (strength_measured[nTile] <= 0.0 ){ // keep last measurement for a while, even if it is not the best
int best_indx=-1;
boolean latest = true;
double best_strength =0.0;
for (int indx = list_index-1; indx >= 0; indx--) { // no need to try the latest - it is empty (strength_measured[nTile] <= 0.0 )
BiScan scan = biCamDSI.getBiScan(indx);
if (scan.disabled_measurement[nTile] || (scan.src_index[nTile] != indx)){ // skip all but enabled sources
continue;
}
if (scan.strength_measured[nTile] > best_strength) {
best_strength = scan.strength_measured[nTile];
best_indx = indx;
}
if (last_priority && latest) {
break; // best_indx should be set correctly, as strength > 0.0
}
latest = false; // first not disabled with strength>0 gets here
}
if (best_indx >= 0) {
src_index[nTile] = best_indx;
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
public void showScans(String title) {
}
/**
* Suggest disparities to try for the tiles in poorly textured areas by fitting planes in DSI
* calcTrusted should be called before to set up trusted/cond_trusted tiles
* suggested tiles will be compared against and made sure they differ by more than a specified margin
* 1) current measured (refined) disparity value
* 2) target disaprity that lead to the current measurement after refinement
* 3) any other disable measurement
* 4) any target disparity that lead to the disabled measurement
* @param trusted_strength strength to trust unconditionally
* @param strength_rfloor strength floor to subrtact as a fraction of the trusted strength
* @param discard_cond if true may suggest new disparities for conditionally trusted tiles
* @param discard_weak if true may suggest new disparities over trusted weak tiles
* @param discard_stron if true may suggest new disparities over any tile
* @param strength_pow raise strength to thyis power (normally just 1.0)
* @param smpl_radius sample "radius", square side is 2 * smpl_radius + 1
* @param smpl_num minimal absolute number of samples required to try fit a plane and validate a tile
* @param smpl_fract minimal fraction number of the neighbor samples that fit the rms filter required to try fit a plane and validate a tile
* @param smpl_num_narrow minimal absolute number of samples for preliminary fitting plane to trhe center area
* @param max_adiff maximal absolute difference from the center tile for initial neighbors selection
* @param max_rdiff maximal (additional) relative (to tile disparity) difference from the center tile for initial neighbors selection
* @param max_atilt maximal absolute tilt (pix/tile) for the tilted planes to fit
* @param max_rtilt maximal relative tilt (pix/tile per disparity pixel). min(max_rtilt*disparity, max_atilt) will be used
* @param smpl_arms maximal absolute rms of the weighted remaining samples for the successful plane fitting
* @param smpl_rrms maximal relative (additional)rms of the weighted remaining samples for the successful plane fitting
* @param damp_tilt regularization value to handle planes if the remaining samples are co-linear (or just a single tile)
* @param rwsigma weight Gaussian sigma to reduce influence of far tiles relative to smpl_radius
* @param rwsigma_narrow Gaussian sigma for the preliminary plain fitting using the closesttiles ~= 1/smpl_radius
* @param new_diff minimal difference between the new suggested and the already tried/measured one
* @param remove_all_tried remove from suggested - not only disabled, but all tried
* @param dbg_x tileX to debug
* @param dbg_y tileY to debug
* @param debugLevel debug level
* @return number of new tiles to measure in the array of suggested disparities - Double.NaN - nothing suggested
* for the tile. May need additional filtering to avoid suggested already tried disparities
*/
int suggestNewScan(
final double trusted_strength, // trusted correlation strength
final double strength_rfloor, // strength floor - relative to trusted
final boolean discard_cond, // consider conditionally trusted tiles (not promoted to trusted) as empty
final boolean discard_weak, // consider weak trusted tiles (not promoted to trusted) as empty
final boolean discard_strong, // suggest new disparitieas even for strong tiles
final double strength_pow, // raise strength-floor to this power
final int smpl_radius,
final int smpl_num, // = 3; // Number after removing worst (should be >1)
final double smpl_fract, // Number of friends among all neighbors
final int smpl_num_narrow, // = 3; // Number after removing worst (should be >1)
final double max_adiff, // Maximal absolute difference betweenthe center tile and friends
final double max_rdiff, // Maximal relative difference between the center tile and friends
final double max_atilt, // = 2.0; // pix per tile
final double max_rtilt, // = 0.2; // (pix / disparity) per tile
final double smpl_arms, // = 0.1; // Maximal RMS of the remaining tiles in a sample
final double smpl_rrms, // = 0.005; // Maximal RMS/disparity in addition to smplRms
final double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
final double rwsigma, // = 0.7; // influence of far neighbors diminish as a Gaussian with this sigma
final double rwsigma_narrow, // = used to determine initial tilt
final double new_diff, // minimal difference between the new suggested and the already tried/measured one
final boolean remove_all_tried, // remove from suggested - not only disabled, but all tried
final int dbg_x,
final int dbg_y,
final int debugLevel
) {
final TileNeibs tnImage = biCamDSI.tnImage;
final double wsigma = rwsigma*smpl_radius;
final double wsigma_narrow = rwsigma_narrow*smpl_radius;
// prepare window
final double [][] weights = new double [smpl_radius + 1][smpl_radius + 1];
final double [][] weights_narrow = new double [smpl_radius + 1][smpl_radius + 1];
for (int i = 0; i <weights.length; i++) {
for (int j = i; j <weights[i].length; j++) {
weights[i][j] = (wsigma >0.0) ?Math.exp(-(i*i+j*j)/(2*wsigma*wsigma)):1.0;
weights[j][i] = weights[i][j];
weights_narrow[i][j] = (wsigma_narrow >0.0) ?Math.exp(-(i*i+j*j)/(2*wsigma_narrow*wsigma_narrow)):1.0;
weights_narrow[j][i] = weights_narrow[i][j];
}
}
final double [][] ds = getDisparityStrength( // FIXME
false, // final boolean only_strong,
false, // final boolean only_trusted,
true) ; // final boolean only_enabled);
final int num_tiles = tnImage.getSizeX()*tnImage.getSizeY();
final double strength_floor = trusted_strength * strength_rfloor;
final int smpl_side = 2 * smpl_radius + 1; // Sample size (side of a square)
final int smpl_len = smpl_side*smpl_side;
final boolean [] trusted_sw = discard_weak ? (this.strong_trusted) : (discard_cond ? this.trusted: this.cond_trusted);
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
// final double [] suggested_disparity = new double [num_tiles];
target_disparity = new double [num_tiles];
for (int i = 0; i < num_tiles; i++) target_disparity[i] = Double.NaN;
// cond_trusted and trusted should be set;
ai.set(0);
// final BiScan this_scan = this;
final AtomicInteger num_new = new AtomicInteger(0);
// find definitely trusted and conditionally trusted tiles
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
int smpl_center = (smpl_side + 1) * smpl_radius;
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()) if (discard_strong || !trusted_sw[nTile]){
// Select all neighbors, then filter
double [] smpl_d = new double [smpl_len];
double [] smpl_w = new double [smpl_len];
double [] smpl_w_narrow = new double [smpl_len];
double [] smpl_p = new double [smpl_len]; // plane disparity,
int nall = 0;
double sw = 0, swd = 0;
for (int dy = -smpl_radius; dy <= smpl_radius; dy++) {
int ady = (dy > 0)? dy:(-dy);
for (int dx = -smpl_radius; dx <= smpl_radius; dx++) if ((dx != 0) || (dy != 0)){
int nTile1 = tnImage.getNeibIndex(nTile, dx, dy);
if ((nTile1 >= 0) && trusted[nTile1]) { // weak trusted OK
nall++;
int adx = (dx > 0)? dx:(-dx);
int smpl_indx = smpl_center + dy*smpl_side + dx;
double w = ds[1][nTile1]-strength_floor;
smpl_d[smpl_indx] = ds[0][nTile1];
smpl_w[smpl_indx] = w * weights[ady][adx];
smpl_w_narrow[smpl_indx] = w * weights_narrow[ady][adx];
if (strength_pow != 1.0) {
smpl_w[smpl_indx] = Math.pow(smpl_w[smpl_indx], strength_pow);
smpl_w_narrow[smpl_indx] = Math.pow(smpl_w_narrow[smpl_indx], strength_pow);
}
sw += smpl_w_narrow[smpl_indx];
swd += smpl_w_narrow[smpl_indx]* smpl_d[smpl_indx];
}
}
}
if (sw == 0.0) {
continue; //
}
double disp_mean = swd/sw; // preliminary reference disparity
double max_tilt = max_rtilt * disp_mean;
if (max_tilt > max_atilt) {
max_tilt = max_atilt;
}
int fin_samples= (int) ( nall * smpl_fract);
if (fin_samples < smpl_num) fin_samples = smpl_num;
// int fin_samples_narrow= (int) ( nall * smpl_fract_narrow);
// if (fin_samples_narrow < smpl_num) fin_samples_narrow = smpl_num_narrow;
// fit plane to mostly centertiles
int nsmpls = nall;
if (nsmpls < smpl_num_narrow) { // no tiles even to start
continue; //
}
double [] fit_rslt = fitPlaneRemoveOutliers(
smpl_radius, // int smpl_radius,
max_tilt, // double max_tilt,
damp_tilt, // double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
true, // boolean full_plane,
smpl_d, // double [] smpl_d,
smpl_w_narrow, // double [] smpl_w, // will be modified,
smpl_p, // double [] smpl_p, // will be set if provided
smpl_num_narrow, // int fin_samples, // remove until this number remain
debugLevel); // int debugLevel)
if ( (fit_rslt == null) || (fit_rslt[0] > (smpl_arms + smpl_rrms * fit_rslt[1]))){
continue; // narrow selection - too high rms
}
disp_mean = fit_rslt[1]; // smpl_p[smpl_center]; // center of the fitted plane
// re-select tiles to fit the plane and use wide weights
double max_diff = max_adiff + max_rdiff * disp_mean; // no provisions for tilt (or add a fraction)?
nsmpls = 0;
for (int indxs = 0; indxs < smpl_len; indxs++) if (smpl_w[indxs]>0){
if (Math.abs(smpl_d[indxs] - smpl_p[indxs]) < max_diff) {
nsmpls++;
} else {
smpl_w[indxs] = 0.0;
}
}
if (nsmpls < fin_samples) { // no tiles even to satrt
continue; //
}
fit_rslt = fitPlaneRemoveOutliers(
smpl_radius, // int smpl_radius,
max_tilt, // double max_tilt,
damp_tilt, // double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
true, // boolean full_plane,
smpl_d, // double [] smpl_d,
smpl_w, // double [] smpl_w, // will be modified,
smpl_p, // double [] smpl_p, // will be set if provided
fin_samples, // int fin_samples, // remove until this number remain
debugLevel); // int debugLevel)
if ( (fit_rslt == null) || (fit_rslt[0] > (smpl_arms + smpl_rrms * fit_rslt[1]))){
continue; // narrow selection - too high rms
}
if (Math.abs(fit_rslt[1] - ds[0][nTile]) < new_diff) { // suggested is too close to already measured
continue; // already measured for this tile
}
// compare to the previous suggestion
int previous_indx = ((src_index[nTile] < 0)? list_index:src_index[nTile]) -1;
double previous_target = (previous_indx >= 0)? biCamDSI.getBiScan(previous_indx).target_disparity[nTile]:Double.NaN; // Nothing is known about the target of the 0-scan
if (Math.abs(fit_rslt[1] - previous_target) < new_diff) { // suggested is too close to already suggested and result - disabled
continue; // already measured for this tile
}
// see if close one was already disabled
// do not compare with the scans that were not disabled - re-try them?remove_all_tried
boolean valid_suggestion = true;
for (BiScan other_scan:biCamDSI.biScans) if (other_scan.disabled_measurement[nTile] || remove_all_tried) {
// int other_indx = (other_scan.src_index[nTile] < 0)? other_scan.list_index:other_scan.src_index[nTile];
// double other_disparity = biCamDSI.getBiScan(other_indx).disparity_measured[nTile];
double other_disparity = other_scan.disparity_measured[nTile];
if (Math.abs(fit_rslt[1] - other_disparity) < new_diff) { // suggested is too close to already measured and disabled
valid_suggestion = false;
break; // already measured for this tile
}
int other_indx = other_scan.list_index;
double other_target = (other_indx > 0)? biCamDSI.getBiScan(other_indx - 1).target_disparity[nTile]:Double.NaN; // Nothing is known about the target of the 0-scan
if (Math.abs(fit_rslt[1] - other_target) < new_diff) { // suggested is too close to already suggested and result - disabled
valid_suggestion = false;
break; // already measured for this tile
}
}
if (valid_suggestion) {
target_disparity[nTile] = fit_rslt[1];
num_new.getAndIncrement();
}
}
}
};
}
ImageDtt.startAndJoin(threads);
// remove duplicates from what was suggested or measured before
return num_new.get();
}
// Simple version for non-flat strong areas - try duplicating neighbor
int suggestNewScan(
final int [] dxy, //up,down,right,left
final boolean discard_cond, // consider conditionally trusted tiles (not promoted to trusted) as empty
final boolean discard_weak, // consider weak trusted tiles (not promoted to trusted) as empty
final boolean discard_strong, // suggest new disparitieas even for strong tiles
final double new_diff, // minimal difference between the new suggested and the already tried/measured one
final boolean remove_all_tried, // remove from suggested - not only disabled, but all tried
final int dbg_x,
final int dbg_y,
final int debugLevel
) {
final TileNeibs tnImage = biCamDSI.tnImage;
final double [][] ds = getDisparityStrength( // FIXME
false, // final boolean only_strong,
false, // final boolean only_trusted,
true) ; // final boolean only_enabled);
final int num_tiles = tnImage.getSizeX()*tnImage.getSizeY();
final boolean [] trusted_sw = discard_weak ? (this.strong_trusted) : (discard_cond ? this.trusted: this.cond_trusted);
final boolean [] trusted_weak = this.cond_trusted; // or even any?
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
target_disparity = new double [num_tiles];
for (int i = 0; i < num_tiles; i++) target_disparity[i] = Double.NaN;
ai.set(0);
final AtomicInteger num_new = new AtomicInteger(0);
// find definitely trusted and conditionally trusted tiles
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()) if (discard_strong || !trusted_sw[nTile]){
int nTile1 = tnImage.getNeibIndex(nTile, dxy[0], dxy[1]);
if ((nTile1 >= 0) && trusted_weak[nTile1]) { // weak trusted OK, maybe even any measured
double new_disp = ds[0][nTile1];
if (Math.abs(new_disp - ds[0][nTile]) < new_diff) { // suggested is too close to already measured
continue; // already measured for this tile
}
// compare to the previous suggestion
int previous_indx = ((src_index[nTile] < 0)? list_index:src_index[nTile]) -1;
double previous_target = (previous_indx >= 0)? biCamDSI.getBiScan(previous_indx).target_disparity[nTile]:Double.NaN; // Nothing is known about the target of the 0-scan
if (Math.abs(new_disp - previous_target) < new_diff) { // suggested is too close to already suggested and result - disabled
continue; // already measured for this tile
}
// see if close one was already disabled
boolean valid_suggestion = true;
for (BiScan other_scan:biCamDSI.biScans) if (other_scan.disabled_measurement[nTile] || remove_all_tried) {
// int other_indx = (other_scan.src_index[nTile] < 0)? other_scan.list_index:other_scan.src_index[nTile];
// double other_disparity = biCamDSI.getBiScan(other_indx).disparity_measured[nTile];
double other_disparity = other_scan.disparity_measured[nTile];
if (Math.abs(new_disp - other_disparity) < new_diff) { // suggested is too close to already measured and disabled
valid_suggestion = false;
break; // already measured for this tile
}
int other_indx = other_scan.list_index;
double other_target = (other_indx > 0)? biCamDSI.getBiScan(other_indx - 1).target_disparity[nTile]:Double.NaN; // Nothing is known about the target of the 0-scan
if (Math.abs(new_disp - other_target) < new_diff) { // suggested is too close to already suggested and result - disabled
valid_suggestion = false;
break; // already measured for this tile
}
}
if (valid_suggestion) {
target_disparity[nTile] = new_disp;
num_new.getAndIncrement();
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return num_new.get();
}
/**
* Calculate trusted tiles from the strength and disparity. Trusted are tiles that are really strong
* (then they are trusted regardless of neighbors) or are somewhat strong and have sufficient neighbors
* that (together with this tile) make a good (tilted) plane
* @param trusted_strength strength to trust unconditionally
* @param strength_rfloor strength floor to subrtact as a fraction of the trusted strength
* @param cond_rtrusted fraction of the trusted strength (after subtracting str4ength_floor) that is sufficient
* to participate in plane fitting, if successful - make a tile trusted
* @param strength_pow raise strength to thyis power (normally just 1.0)
* @param smpl_radius sample "radius", square side is 2 * smpl_radius + 1
* @param smpl_num minimal absolute number of samples required to try fit a plane and validate a tile
* @param smpl_fract minimal fraction number of the neighbor samples that fit the rms filter required to try fit a plane and validate a tile
* @param max_adiff maximal absolute difference from the center tile for initial neighbors selection
* @param max_rdiff maximal (additional) relative (to tile disparity) difference from the center tile for initial neighbors selection
* @param max_atilt maximal absolute tilt (pix/tile) for the tilted planes to fit
* @param max_rtilt maximal relative tilt (pix/tile per disparity pixel). min(max_rtilt*disparity, max_atilt) will be used
* @param smpl_arms maximal absolute rms of the weighted remaining samples for the successful plane fitting
* @param smpl_rrms maximal relative (additional)rms of the weighted remaining samples for the successful plane fitting
* @param damp_tilt regularization value to handle planes if the remaining samples are co-linear (or just a single tile)
* @param rwsigma weight Gaussina sigma to reduce influence of far tiles relative to smpl_radius
* @param dbg_x tileX to debug
* @param dbg_y tileY to debug
* @param debugLevel debug level
* @return array of 3 numers: number of trusted strong tiles, number of additional trusted by plane fitting, and number of all
* somewhat strong tiles
*/
int [] calcTrusted(
final double trusted_strength, // trusted correlation strength
final double strength_rfloor, // strength floor - relative to trusted
final double cond_rtrusted, // minimal strength to consider - fraction of trusted
final double strength_pow, // raise strength-floor to this power
final int smpl_radius,
final int smpl_num, // = 3; // Number after removing worst (should be >1)
final double smpl_fract, // Number of friends among all neighbors
final double max_adiff, // Maximal absolute difference between the center tile and friends
final double max_rdiff, // Maximal relative difference between the center tile and friends
final double max_atilt, // = 2.0; // pix per tile
final double max_rtilt, // = 0.2; // (pix / disparity) per tile
final double smpl_arms, // = 0.1; // Maximal RMS of the remaining tiles in a sample
final double smpl_rrms, // = 0.005; // Maximal RMS/disparity in addition to smplRms
final double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
final double rwsigma, // = 0.7; // influence of far neighbors diminish as a Gaussian with this sigma
final int dbg_x,
final int dbg_y,
final int debugLevel
) {
final TileNeibs tnImage = biCamDSI.tnImage;
final double wsigma = rwsigma*smpl_radius;
final double [][] ds = getDisparityStrength( // already has disabled zeroed
false, // final boolean only_strong,
false, // final boolean only_trusted,
true) ; // final boolean only_enabled);
final int num_tiles = tnImage.getSizeX()*tnImage.getSizeY();
final double strength_floor = trusted_strength * strength_rfloor;
final double min_strength = strength_floor + (trusted_strength - strength_floor) * cond_rtrusted;
final int smpl_side = 2 * smpl_radius + 1; // Sample size (side of a square)
final int smpl_len = smpl_side*smpl_side;
// prepare window
final double [][] weights = new double [smpl_radius + 1][smpl_radius + 1];
for (int i = 0; i <weights.length; i++) {
for (int j = i; j <weights[i].length; j++) {
weights[i][j] = (wsigma >0.0) ?Math.exp(-(i*i+j*j)/(2*wsigma*wsigma)):1.0;
weights[j][i] = weights[i][j];
}
}
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final AtomicInteger num_non_weak = new AtomicInteger(0);
final AtomicInteger num_trusted_strong = new AtomicInteger(0);
final AtomicInteger num_trusted_plane = new AtomicInteger(0);
// final boolean [] cond_trusted = new boolean [num_tiles];
strong_trusted = new boolean [num_tiles];
trusted = new boolean [num_tiles];
cond_trusted = new boolean [num_tiles];
ai.set(0);
// find definitely trusted and conditionally trusted tiles
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()){
if (!Double.isNaN(ds[0][nTile]) && (ds[1][nTile] >= min_strength) || (ds[1][nTile] > 0)) {
num_non_weak.getAndIncrement();
cond_trusted[nTile] = true;
if (ds[1][nTile] > trusted_strength) {
strong_trusted[nTile] = true;
trusted[nTile] = true;
num_trusted_strong.getAndIncrement();
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
ai.set(0);
// find definitely trusted and conditionally trusted tiles
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
int smpl_center = (smpl_side + 1) * smpl_radius;
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()) if (cond_trusted[nTile] && !trusted[nTile]){
double [] smpl_d = new double [smpl_len];
double [] smpl_w = new double [smpl_len];
double [] smpl_p = new double [smpl_len]; // plane disparity,
// copy neighbor tiles
double disp_center = ds[0][nTile];
double max_diff = max_adiff + max_rdiff * disp_center;
double max_tilt = max_rtilt * disp_center;
if (max_tilt > max_atilt) {
max_tilt = max_atilt;
}
int nsmpls = 0;
int nall = 0;
for (int dy = -smpl_radius; dy <= smpl_radius; dy++) {
int ady = (dy > 0)? dy:(-dy);
for (int dx = -smpl_radius; dx <= smpl_radius; dx++) {
int nTile1 = tnImage.getNeibIndex(nTile, dx, dy);
if ((nTile1 >= 0) && cond_trusted[nTile1]) {
nall++;
int adx = (dx > 0)? dx:(-dx);
double max_fdiff = max_diff + (ady+adx) * max_tilt;
int smpl_indx = smpl_center + dy*smpl_side + dx;
if (Math.abs(ds[0][nTile1] - disp_center) <= max_fdiff) {
// smpl_sel[smpl_indx] = true;
smpl_d[smpl_indx] = ds[0][nTile1];
smpl_w[smpl_indx] = (ds[1][nTile1]-strength_floor) * weights[ady][adx];
if (strength_pow != 1.0) {
smpl_w[smpl_indx] = Math.pow(smpl_w[smpl_indx], strength_pow);
}
nsmpls ++;
}
}
}
}
int fin_samples= (int) ( nall * smpl_fract);
if (fin_samples < smpl_num) fin_samples = smpl_num;
if (nsmpls >= fin_samples) {
double [] fit_rslt = fitPlaneRemoveOutliers(
smpl_radius, // int smpl_radius,
max_tilt, // double max_tilt,
damp_tilt, // double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
false, // boolean full_plane,
smpl_d, // double [] smpl_d,
smpl_w, // double [] smpl_w, // will be modified,
smpl_p, // double [] smpl_p, // will be set if provided
fin_samples, // int fin_samples, // remove until this number remain
debugLevel); // int debugLevel)
if ( (fit_rslt != null) && (fit_rslt[0] < (smpl_arms + smpl_rrms * fit_rslt[1]))){
// Trusted tile, save it
trusted[nTile] = true;
num_trusted_plane.getAndIncrement();
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
int [] numTrustedAll = {num_trusted_strong.get(), num_trusted_plane.get(), num_non_weak.get()};
return numTrustedAll;
}
// FG edge should be strong
// Trimming(disabling) weak (trusted but not strong_trusted) tiles if on any one side:
// a) there are no same plane or closer tiles
// b) there are no in-plane or closer strong tiles, but there are some (strong or any?) farther tiles
// repeat while more are trimmed
// maybe, if there are both strong in-plane and far - see which are closer
/**
* Disable low-textured tiles are not between strong tiles, but on one side of it.
* This method relies on the assumption that FG edge should bave strong correlation, so it tries multiple directions
* from the weak (not trusted strong) tiles and trims tiles that eithre do not have anything in that direction or have
* farther tiles.
* Trimming(disabling) weak (trusted but not strong_trusted) tiles if on any one side:
* a) there are no same plane or closer tiles
* b) there are no in-plane or closer strong tiles, but there are some (strong or any?) farther tiles
* repeat while more are trimmed
* maybe, if there are both strong in-plane and far - see which are closer
* @param trusted_strength strength to trust unconditionally
* @param strength_rfloor strength floor to subrtact as a fraction of the trusted strength
* @param cond_rtrusted fraction of the trusted strength (after subtracting str4ength_floor) that is sufficient
* to participate in plane fitting, if successful - make a tile trusted
* @param strength_pow raise strength to thyis power (normally just 1.0)
* @param smpl_radius sample "radius", square side is 2 * smpl_radius + 1
* @param smpl_num minimal absolute number of samples required to try fit a plane and validate a tile
* @param smpl_fract minimal fraction number of the neighbor samples that fit the rms filter required to try fit a plane and validate a tile
* @param max_adiff maximal absolute difference from the center tile for initial neighbors selection
* @param max_rdiff maximal (additional) relative (to tile disparity) difference from the center tile for initial neighbors selection
* @param max_atilt maximal absolute tilt (pix/tile) for the tilted planes to fit
* @param max_rtilt maximal relative tilt (pix/tile per disparity pixel). min(max_rtilt*disparity, max_atilt) will be used
* @param smpl_arms maximal absolute rms of the weighted remaining samples for the successful plane fitting
* @param smpl_rrms maximal relative (additional)rms of the weighted remaining samples for the successful plane fitting
* @param damp_tilt regularization value to handle planes if the remaining samples are co-linear (or just a single tile)
* @param rwsigma weight Gaussina sigma to reduce influence of far tiles relative to smpl_radius
* @param atolerance absolute disparity tolerance to what to consider "far"
* @param rtolerance relative to disparity tolerance to what to consider "far"
* @param num_dirs number of directions per 2*PI to try
* @param blind_dist when trying directions require distance in that direction to exceed this value to count
* @param strong_only_far true: require far tiles to be trusted_strong, false - just trusted is OK
* @param num_strong_far number of strong trusted far tiles to make this FG tile hanging
* @param num_weak_far number of strong trusted far tiles to make this FG tile hanging
* @param dbg_x tileX to debug
* @param dbg_y tileY to debug
* @param debugLevel debug level
* @return
*/
int trimWeakFG(
final double trusted_strength, // trusted correlation strength
final double strength_rfloor, // strength floor - relative to trusted
final double cond_rtrusted, // minimal strength to consider - fraction of trusted
final double strength_pow, // raise strength-floor to this power
final int smpl_radius,
final int smpl_num, // = 3; // Number after removing worst (should be >1)
final double smpl_fract, // Number of friends among all neighbors
final double max_adiff, // Maximal absolute difference betweenthe center tile and friends
final double max_rdiff, // Maximal relative difference between the center tile and friends
final double max_atilt, // = 2.0; // pix per tile
final double max_rtilt, // = 0.2; // (pix / disparity) per tile
final double smpl_arms, // = 0.1; // Maximal RMS of the remaining tiles in a sample
final double smpl_rrms, // = 0.005; // Maximal RMS/disparity in addition to smplRms
final double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
final double rwsigma, // = 0.7; // influence of far neighbors diminish as a Gaussian with this sigma
final double atolerance, // When deciding closer/farther
final double rtolerance, // same, scaled with disparity
final int num_dirs, // number of directions to try
final double blind_dist, // analyze only tiles farther than this in the selected direction
final boolean strong_only_far, // in variant b) only compare with strong far
final int num_strong_far, // number of directions to try
final int num_weak_far, // number of directions to try
final int dbg_x,
final int dbg_y,
final int debugLevel
) {
final TileNeibs tnImage = biCamDSI.tnImage;
final int dbg_tile = (debugLevel>-2)?(dbg_x + tnImage.sizeX*dbg_y):-1;
final double wsigma = rwsigma*smpl_radius;
final double [][] ds = getDisparityStrength( // already has disabled zeroed
false, // final boolean only_strong,
false, // final boolean only_trusted,
true) ; // final boolean only_enabled);
final int num_tiles = tnImage.getSizeX()*tnImage.getSizeY();
final double strength_floor = trusted_strength * strength_rfloor;
// final double min_strength = strength_floor + (trusted_strength - strength_floor) * cond_rtrusted;
final int smpl_side = 2 * smpl_radius + 1; // Sample size (side of a square)
final int smpl_len = smpl_side*smpl_side;
// prepare window
final double [][] weights = new double [smpl_radius + 1][smpl_radius + 1];
for (int i = 0; i <weights.length; i++) {
for (int j = i; j <weights[i].length; j++) {
weights[i][j] = (wsigma >0.0) ?Math.exp(-(i*i+j*j)/(2*wsigma*wsigma)):1.0;
weights[j][i] = weights[i][j];
}
}
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final AtomicInteger num_disabled = new AtomicInteger(0);
int total_disabled = 0;
int npass=0;
while (true) {
num_disabled.set(0);
final boolean [] new_disabled = new boolean[num_tiles]; // this.disabled.clone();
ai.set(0);
// find definitely trusted and conditionally trusted tiles
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
int smpl_center = (smpl_side + 1) * smpl_radius;
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()) if (trusted[nTile] && !strong_trusted[nTile]){
boolean dbg_this = (dbg_tile == nTile);
if (dbg_this) {
System.out.println("trimWeakFG(): debugging tile"+nTile);
}
double [] smpl_d = new double [smpl_len];
double [] smpl_w = new double [smpl_len];
double [] smpl_w_all = new double [smpl_len];
double [] smpl_p = new double [smpl_len]; // plane disparity,
boolean [] smpl_strong = new boolean[smpl_len];
// copy neighbor tiles
double disp_center = ds[0][nTile];
double max_diff = max_adiff + max_rdiff * disp_center;
double max_tilt = max_rtilt * disp_center;
if (max_tilt > max_atilt) {
max_tilt = max_atilt;
}
int nsmpls = 0;
int nall = 0;
for (int dy = -smpl_radius; dy <= smpl_radius; dy++) {
int ady = (dy > 0)? dy:(-dy);
for (int dx = -smpl_radius; dx <= smpl_radius; dx++) {
int nTile1 = tnImage.getNeibIndex(nTile, dx, dy);
// if ((nTile1 >= 0) && cond_trusted[nTile1]) {
if ((nTile1 >= 0) && trusted[nTile1]) {
nall++;
int adx = (dx > 0)? dx:(-dx);
double max_fdiff = max_diff + (ady+adx) * max_tilt;
int smpl_indx = smpl_center + dy*smpl_side + dx;
smpl_d[smpl_indx] = ds[0][nTile1];
double w = (ds[1][nTile1]-strength_floor) * weights[ady][adx];
if (smpl_d[smpl_indx] < 0.0) { // discard stray negative disparity
w = 0.0;
}
if (strength_pow != 1.0) {
w = Math.pow(w, strength_pow);
}
smpl_w_all[smpl_indx] = w;
if (Math.abs(ds[0][nTile1] - disp_center) <= max_fdiff) {
smpl_w[smpl_indx] = w;
nsmpls ++;
}
smpl_strong[smpl_indx]= strong_trusted[nTile1];
}
}
}
int fin_samples= (int) ( nall * smpl_fract);
if (fin_samples < smpl_num) fin_samples = smpl_num;
if (nsmpls >= fin_samples) {
double [] fit_rslt = fitPlaneRemoveOutliers(
smpl_radius, // int smpl_radius,
max_tilt, // double max_tilt,
damp_tilt, // double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
true, // boolean full_plane,
smpl_d, // double [] smpl_d,
smpl_w, // double [] smpl_w, // will be modified,
smpl_p, // double [] smpl_p, // will be set if provided
fin_samples, // int fin_samples, // remove until this number remain
debugLevel); // int debugLevel)
if ( (fit_rslt != null) && (fit_rslt[0] < (smpl_arms + smpl_rrms * fit_rslt[1]))){
// check directions here, use smpl_w_all, smpl_d and smpl_p
// int [] num_this_closer = new int [num_dirs];
// int [] num_this_closer_strong = new int [num_dirs];
// int [] num_farther = new int [num_dirs];
double thershold_disp = -(atolerance + rtolerance*fit_rslt[1]);
double [][] dbg_data = dbg_this?(new double [5+num_dirs][smpl_len]):null;
String [] dbg_titles = dbg_this?(new String [5+num_dirs]):null;
if (dbg_this) {
for (int indxs = 0; indxs < smpl_len; indxs++) {
dbg_data[0][indxs] = smpl_d[indxs];
dbg_data[1][indxs] = smpl_strong[indxs]? smpl_d[indxs]: Double.NaN;
dbg_data[2][indxs] = smpl_p[indxs];
dbg_data[3][indxs] = smpl_w_all[indxs];
dbg_data[4][indxs] = smpl_d[indxs]-smpl_p[indxs];
}
dbg_titles[0]= "smpl_d";
dbg_titles[1]= "smpl_d-strong";
dbg_titles[2]= "smpl_p";
dbg_titles[3]= "smpl_w_all";
dbg_titles[4]= "smpl_d-smpl_p";
for (int idir = 0; idir<num_dirs; idir++) {
dbg_titles[5 + idir]="dir-"+idir;
for (int indxs = 0; indxs < smpl_len; indxs++) {
dbg_data[5+idir][indxs] = Double.NaN;
}
}
}
for (int idir = 0; idir<num_dirs; idir++) {
double a = 2*Math.PI*idir/num_dirs;
double ca = Math.cos(a);
double sa = Math.sin(a);
int num_this_closer = 0;
int num_this_closer_strong = 0;
int num_farther = 0;
int num_farther_strong = 0;
for (int indxs = 0; indxs < smpl_len; indxs++) if (smpl_w_all[indxs] > 0.0) {
int dy = indxs/smpl_side - smpl_radius;
int dx = indxs%smpl_side - smpl_radius;
double d = dx*ca + dy*sa;
if (dbg_this) {
dbg_data[5+idir][indxs] = d - blind_dist;
}
if (d >= blind_dist) {
boolean farther = (smpl_d[indxs]-smpl_p[indxs]) < thershold_disp;
if (farther) {
num_farther ++;
// if (!strong_only_far || smpl_strong[indxs]) num_farther++;
if (smpl_strong[indxs]) num_farther_strong++;
} else {
num_this_closer++;
if (smpl_strong[indxs]) num_this_closer_strong++;
}
}
}
if (dbg_this) {
System.out.println("trimWeakFG(): idir="+idir+" num_this_closer="+num_this_closer+
", num_this_closer_strong="+num_this_closer_strong+", num_farther="+num_farther);
}
boolean far_exist = (num_farther_strong > num_strong_far) || (!strong_only_far && (num_farther > num_weak_far));
if ((num_this_closer ==0) || far_exist) {
new_disabled[nTile] = true;
num_disabled.getAndIncrement();
if (dbg_this) {
System.out.println("trimWeakFG(): DISABLED idir="+idir+" num_this_closer="+num_this_closer+
", num_this_closer_strong="+num_this_closer_strong+", num_farther="+num_farther+", num_farther_strong="+num_farther_strong);
}
if (!dbg_this) {
break; // already disabled
}
}
}
if (dbg_this) {
(new showDoubleFloatArrays()).showArrays(
dbg_data,
smpl_side,
smpl_side,
true,
"trimWeakFG_T"+nTile,
dbg_titles);
}
} else { // may get even after initial filtering (by calcTrusted()) here because some neighbors became disabled? loosen flatness? Keep non-flat
if (dbg_this) {
System.out.println("trimWeakFG(): Too high RMS");
}
}
} else { // may get even after initial filtering (by calcTrusted()) here because some neighbors became disabled?
if (dbg_this) {
System.out.println("trimWeakFG(): Insufficient points");
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
npass++;
if (debugLevel > -2) {
System.out.println("trimWeakFG(): npass="+npass+" removed="+num_disabled.get());
}
if (num_disabled.get() == 0) {
break;
}
ai.set(0);
// find definitely trusted and conditionally trusted tiles
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()) if (new_disabled[nTile]) {
disableTile(nTile); // disabled source and this trusted*
}
}
};
}
ImageDtt.startAndJoin(threads);
if (debugLevel > -2) {
biCamDSI.getLastBiScan().showScan(
"trimWeakFG_"+npass);
}
total_disabled += num_disabled.get();
}
return total_disabled; // numTrustedAll;
}
// smpl_p[indxs] = approx2d[0][0] * (sx - smpl_radius) + approx2d[0][1] * (sy - smpl_radius) + approx2d[0][2];
/**
* Remove worst outliers when fitting planes until the specified number of samples are left, re-fitting
* plane after each iteration
* @param smpl_radius sample "radius", square side is 2 * smpl_radius + 1
* @param max_tilt maximal DSI plane tilt (pixels/tile)
* @param damp_tilt tilt cost for damping insufficient plane data
* @param full_plane generate full tilted plane, not only for non-zero tiles
* @param smpl_d array of disparity values to approximate
* @param smpl_w weights - only >0.0 are processed
* @param smpl_p approximated disparity values, amy be null. When provided (not null), will have calculated disparity approximation
* @param fin_samples
* @param debugLevel debug level
* @return array of 4 values: rmas of the remaining samples, average (center) disparity value, tiltX, tiltY
*/
public double [] fitPlaneRemoveOutliers(
int smpl_radius,
double max_tilt,
double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
boolean full_plane,
double [] smpl_d,
double [] smpl_w, // will be modified,
double [] smpl_p, // will be set if provided
int fin_samples, // remove until this number remain
int debugLevel)
{
double [] disp_tilts = null;
final int smpl_side = 2 * smpl_radius + 1; // Sample size (side of a square)
int num_in_sample = 0;
for (int i = 0; i < smpl_w.length; i++) if (smpl_w[i]> 0.0) num_in_sample++;
int smpl_len = smpl_w.length;
if (num_in_sample <fin_samples) {
return null;
}
double rms = Double.NaN;
if (smpl_p == null) smpl_p = new double [smpl_len];
while (num_in_sample >= fin_samples) {
// fit plane to the selected and remove outlayers after each iteration
disp_tilts = fitPlane(
smpl_radius, //int smpl_radius,
max_tilt, //double max_tilt,
damp_tilt, //double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
full_plane, // boolean full_plane,
smpl_d, // double [] smpl_d,
smpl_w, // double [] smpl_w,
smpl_p, //double [] smpl_p, // will be set if provided
debugLevel); // int debugLevel)
// calculate fitting quality
if (disp_tilts == null) {
return null;
}
// double d_center = disp_tilts[0];
double sw = 0.0, sd2 = 0.0;
for (int indxs = 0; indxs < smpl_len;indxs++) if (smpl_w[indxs] > 0) {
double d = smpl_d[indxs] - smpl_p[indxs];
double dw = d * smpl_w[indxs];
sd2 += dw * smpl_d[indxs];
sw += smpl_w[indxs];
}
rms = (sw > 0.0)? Math.sqrt(sd2/sw): Double.NaN;
// remove worst - it should not make remaining set
if (num_in_sample > fin_samples) { // remove worst if it is not the last run where only calculations are needed
int iworst = -1;
double dworst2 = 0.0;
for (int indxs = 0; indxs < smpl_len; indxs++) if (smpl_w[indxs] > 0.0) {
double d2 = smpl_d[indxs] - smpl_p[indxs];
d2 *=d2;
if (d2 > dworst2) {
if ((damp_tilt !=0.0) || notColinearWithout (
indxs, // int indx,
smpl_w, // boolean [] sel,
smpl_side)) { // int side))
iworst = indxs;
dworst2 = d2;
}
}
}
if (iworst < 0){
if (debugLevel > 0) {
System.out.println("**** this may be BUG in fitPlaneRemoveOutliers() can not find the worst sample - all tiles fit perfectly ****");
}
// this can happen if some samples are the same and all the pixels fit exactly - use all of them
break;
}
// remove worst sample
smpl_w[iworst] = 0.0;
num_in_sample --;
} else {
break;
}
} // while (nsmpls >= min_sample) {
double [] rslt = {rms, disp_tilts[0], disp_tilts[1], disp_tilts[1]};
return rslt;
}
/**
* Verify that selected points are not all on the same line, even if the specified one is removed
* @param indx index of the point to be removed
* @param smpl_w 2-d sample weights in linescan order (used zero/non-zero only)
* @param side square samples side
* @return true if there are enough samples for plane extraction, false otherwise
*/
public boolean notColinearWithout (
int indx,
double [] smpl_w,
int side)
{
if (smpl_w[indx] == 0.0){
throw new IllegalArgumentException ("notCoplanarWithout(): specified is the non existing index");
}
double w = smpl_w[indx];
smpl_w[indx] = 0.0;
boolean rslt = notColinear ( smpl_w, side);
smpl_w[indx] = w; // restore value
return rslt;
}
/**
* Verify that selected points are not all on the same line
* @param smpl_w 2-d sample weights in linescan order (used zero/non-zero only)
* @param side square samples side
* @return true if there are enough samples for plane extraction, false otherwise
*/
public boolean notColinear (
double [] smpl_w,
int side)
{
int indx0, indx1;
for (indx0 = 0; indx0 < smpl_w.length; indx0++){
if (smpl_w[indx0] > 0.0) break;
}
for (indx1 = indx0+1; indx1 < smpl_w.length; indx1++){
if (smpl_w[indx0] > 0.0) break;
}
if (indx1 >= smpl_w.length) return false; // too few points;
int sx0 = indx0 % side;
int sy0 = indx0 / side;
int sx1 = indx1 % side;
int sy1 = indx1 / side;
for (int indx = indx1 +1; indx < smpl_w.length; indx++){
int sx = indx % side;
int sy = indx / side;
if ((sx - sx0) * (sy - sy1) != (sx - sx1) * (sy - sy0)){
return true;
}
}
return false;
}
/**
* Approximate tile disparity by a tilted DSI plane
* @param smpl_radius sample "radius", square side is 2 * smpl_radius + 1
* @param max_tilt maximal DSI plane tilt (pixels/tile)
* @param damp_tilt tilt cost for damping insufficient plane data
* @param full_plane generate full tilted plane, not only for non-zero tiles
* @param smpl_d array of disparity values to approximate
* @param smpl_w weights - only >0.0 are processed
* @param smpl_p approximated disparity values, amy be null. When provided (not null), will have calculated disparity approximation
* @param debugLevel debug level
* @return array of 3 values: average (center) disparity value, tiltX, tiltY
*/
public double [] fitPlane(
int smpl_radius,
double max_tilt,
double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
boolean full_plane,
double [] smpl_d,
double [] smpl_w,
double [] smpl_p, // will be set if provided
int debugLevel)
{
PolynomialApproximation pa = new PolynomialApproximation();
final double [] damping = {damp_tilt, damp_tilt, 0.0}; // 0.0 will be applied to average value, tilt_cost - to both tilts
final int smpl_side = 2 * smpl_radius + 1; // Sample size (side of a square)
final int smpl_len = smpl_side*smpl_side;
if (smpl_p == null) smpl_p = new double [smpl_len];
int num_in_sample = 0;
for (int i = 0; i < smpl_w.length; i++) if (smpl_w[i] > 0.0) num_in_sample++;
double [][][] mdata = new double [num_in_sample][3][];
int mindx = 0;
for (int sy = 0; sy < smpl_side; sy++){
for (int sx = 0; sx < smpl_side; sx++){
int indxs = sy * smpl_side + sx;
if (smpl_w[indxs] > 0.0) {
mdata[mindx][0] = new double [2];
mdata[mindx][0][0] = sx - smpl_radius;
mdata[mindx][0][1] = sy - smpl_radius;
mdata[mindx][1] = new double [1];
mdata[mindx][1][0] = smpl_d[indxs];
mdata[mindx][2] = new double [1];
mdata[mindx][2][0] = smpl_w[indxs];
mindx ++;
}
}
}
double[][] approx2d = pa.quadraticApproximation(
mdata,
true, // boolean forceLinear, // use linear approximation
damping, // double [] damping,
THRESHOLD_LIN, // threshold ratio of matrix determinant to norm for linear approximation (det too low - fail)
THRESHOLD_QUAD, // threshold ratio of matrix determinant to norm for quadratic approximation (det too low - fail)
debugLevel);
if (approx2d == null){
if (debugLevel > -1){
System.out.println("getDisparityStrengthML(): can not find linear approximation");
}
return null;
}
// limit tilt to be within range
// double max_abs_tilt, // = 2.0; // pix per tile
// double max_rel_tilt, // = 0.2; // (pix / disparity) per tile
// double max_tilt = Math.min(mlfp.max_abs_tilt, mlfp.max_rel_tilt * approx2d[0][2]);
boolean overlimit = (Math.abs(approx2d[0][0]) > max_tilt) || (Math.abs(approx2d[0][1]) > max_tilt);
if (overlimit) {
approx2d[0][0] = Math.min(approx2d[0][0], max_tilt);
approx2d[0][1] = Math.min(approx2d[0][1], max_tilt);
approx2d[0][0] = Math.max(approx2d[0][0], -max_tilt);
approx2d[0][1] = Math.max(approx2d[0][1], -max_tilt);
}
// subtract tilt from disparity
for (int sy = 0; sy < smpl_side; sy++){
for (int sx = 0; sx < smpl_side; sx++){
int indxs = sy * smpl_side + sx;
if ((smpl_w[indxs] > 0.0) || full_plane) {
smpl_p[indxs] = approx2d[0][0] * (sx - smpl_radius) + approx2d[0][1] * (sy - smpl_radius) + approx2d[0][2];
}
}
}
if (overlimit){ // re-calculate disparity average (in the center)
double sw = 0.0;
double sd=0.0;
for (int indxs = 0; indxs < smpl_len;indxs++) if (smpl_w[indxs] > 0.0) {
double d = smpl_d[indxs] - smpl_p[indxs];
double dw = d * smpl_w[indxs];
sd += dw;
sw += smpl_w[indxs];
}
sd /= sw;
for (int indxs = 0; indxs < smpl_len;indxs++) if ((smpl_w[indxs] > 0.0) || full_plane) {
smpl_p[indxs] += sd;
}
approx2d[0][2] += sd;
}
double [] rslt = {approx2d[0][2], approx2d[0][0],approx2d[0][1]}; // {center, tiltX, tiltY
return rslt;
}
}
......@@ -588,6 +588,9 @@ private Panel panel1,
addButton("AUX Extrinsics", panelClt4, color_process);
addButton("AUX show fine", panelClt4, color_configure);
// addButton("Rig enhance", panelClt4, color_conf_process);
// /"Reset GT"
addButton("Reset GT", panelClt4, color_stop);
addButton("Ground truth 0", panelClt4, color_configure);
addButton("Ground truth", panelClt4, color_conf_process);
addButton("ML export", panelClt4, color_conf_process);
addButton("Rig planes", panelClt4, color_conf_process);
......@@ -4593,14 +4596,28 @@ private Panel panel1,
QuadCLT dbg_QUAD_CLT_AUX = QUAD_CLT_AUX;
return;
/* ======================================================================== */
} else if (label.equals("Reset GT")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
resetGroundTruth();
return;
/* ======================================================================== */
} else if (label.equals("Ground truth 0")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
enhanceByRig(false);
return;
/* ======================================================================== */
} else if (label.equals("Ground truth")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
enhanceByRig();
enhanceByRig(true);
return;
/* ======================================================================== */
/* ======================================================================== */
} else if (label.equals("CLT planes")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
......@@ -5052,10 +5069,14 @@ private Panel panel1,
return true;
}
public boolean enhanceByRig() {
//resetGroundTruthByRig()
public boolean resetGroundTruth() {
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null)) return false;
QUAD_CLT.resetGroundTruthByRig();
return true;
}
public boolean enhanceByRig( boolean use_planes) {
long startTime=System.nanoTime();
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null)) {
String msg = "DSI data is not available. Please run \"CLT 3D\" first";
IJ.showMessage("Error",msg);
......@@ -5066,22 +5087,17 @@ private Panel panel1,
String configPath=getSaveCongigPath();
if (configPath.equals("ABORT")) return false;
if (DEBUG_LEVEL > -2){
System.out.println("++++++++++++++ Enhancing single-camera DSI by the dual-camera rig++++++++++++++");
}
try {
if (DEBUG_LEVEL > -2){
System.out.println("++++++++++++++ Enhancing single-camera DSI by the dual-camera rig using planes ++++++++++++++");
}
TWO_QUAD_CLT.enhanceByRig( // actually there is no sense to process multiple image sets. Combine with other processing?
QUAD_CLT, // QuadCLT quadCLT_main,
QUAD_CLT_AUX, // QuadCLT quadCLT_aux,
CLT_PARAMETERS, // EyesisCorrectionParameters.DCTParameters dct_parameters,
use_planes, // final boolean use_planes,
THREADS_MAX, //final int threadsMax, // maximal number of threads to launch
UPDATE_STATUS, //final boolean updateStatus,
DEBUG_LEVEL);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //final int debugLevel);
if (configPath!=null) {
saveTimestampedProperties( // save config again
configPath, // full path or null
......
......@@ -2711,7 +2711,7 @@ public class ImageDtt {
for (int chn = 0; chn < numcol; chn++){
tiles_debayered[i][chn] = tile_debayer_shot_corr(
(chn != 2), // red or blue (flase - green)
(chn != 2), // red or blue (false - green)
iclt_tile[i][chn],
2 * transform_size,
lt_window2, // squared lapping window
......@@ -7098,12 +7098,12 @@ public class ImageDtt {
for (int i =0; i<quad; i++){
for (int chn = 0; chn < numcol; chn++){
// tiles_debayered[i][chn] = tile_debayer(
// (chn != 2), // red or blue (flase - green)
// (chn != 2), // red or blue (false - green)
// iclt_tile[i][chn],
// 2 * transform_size);
tiles_debayered[i][chn] = tile_debayer_shot_corr(
(chn != 2), // red or blue (flase - green)
(chn != 2), // red or blue (false - green)
iclt_tile[i][chn],
2 * transform_size,
lt_window2, // squared lapping window
......@@ -7642,7 +7642,7 @@ public class ImageDtt {
for (int chn = 0; chn < numcol; chn++){
tiles_debayered[i][chn] = tile_debayer_shot_corr(
(chn != 2), // red or blue (flase - green)
(chn != 2), // red or blue (false - green)
iclt_tile[i][chn],
2 * clt_parameters.transform_size,
lt_window2, // squared lapping window
......
......@@ -73,6 +73,9 @@ public class QuadCLT {
// magic scale should be set before using TileProcessor (calculated disparities depend on it)
public void resetGroundTruthByRig() {
tp.rig_disparity_strength = null;
}
public double [][] getGroundTruthByRig(){
if (tp == null) return null;
return tp.rig_disparity_strength;
......@@ -118,6 +121,57 @@ public class QuadCLT {
}
}
// used for aux camera
public boolean setupImageData(
String image_name,
String [] sourceFiles,
EyesisCorrectionParameters.CLTParameters clt_parameters,
int threadsMax,
int debugLevel) {
QuadCLT.SetChannels [] set_channels_aux = setChannels(image_name, debugLevel);
if ((set_channels_aux == null) || (set_channels_aux.length==0)) {
System.out.println("No files for the auxiliary camera match series "+image_name);
return false;
}
double [] referenceExposures_aux = eyesisCorrections.calcReferenceExposures(debugLevel); // multiply each image by this and divide by individual (if not NaN)
int [] channelFiles_aux = set_channels_aux[0].fileNumber();
// make single
boolean [][] saturation_aux = (clt_parameters.sat_level > 0.0)? new boolean[channelFiles_aux.length][] : null;
double [] scaleExposures_aux = new double[channelFiles_aux.length];
ImagePlus [] imp_srcs_aux = conditionImageSet(
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
sourceFiles, // String [] sourceFiles,
image_name, // set_channels_aux[0].name(), // String set_name,
referenceExposures_aux, // double [] referenceExposures,
channelFiles_aux, // int [] channelFiles,
scaleExposures_aux, //output // double [] scaleExposures
saturation_aux, //output // boolean [][] saturation_imp,
debugLevel); // int debugLevel);
double [][][] double_stacks_aux = new double [imp_srcs_aux.length][][];
for (int i = 0; i < double_stacks_aux.length; i++){
double_stacks_aux[i] = eyesisCorrections.bayerToDoubleStack(
imp_srcs_aux[i], // source Bayer image, linearized, 32-bit (float))
null); // no margins, no oversample
}
for (int i = 0; i < double_stacks_aux.length; i++){
for (int j =0 ; j < double_stacks_aux[i][0].length; j++){
double_stacks_aux[i][2][j]*=0.5; // Scale green 0.5 to compensate more pixels than R,B
}
}
setTiles (imp_srcs_aux[0], // set global tp.tilesX, tp.tilesY
clt_parameters,
threadsMax);
this.image_name = image_name;
image_data = double_stacks_aux;
saturation_imp = saturation_aux;
tp.setTrustedCorrelation(clt_parameters.grow_disp_trust);
tp.resetCLTPasses();
return true;
}
public QuadCLT(
String prefix,
......
......@@ -59,6 +59,12 @@ public class TileNeibs{
int [] xy = {indx % sizeX ,indx / sizeX};
return xy;
}
int getSizeX() {
return sizeX;
}
int getSizeY() {
return sizeY;
}
/**
* Get element index from x and y
......
......@@ -861,7 +861,7 @@ public class TwoQuadCLT {
quadCLT_aux, // QuadCLT quadCLT_aux,
null, // double [][] src_bimap, // current state of measurements (or null for new measurement)
0.0, // double disparity,
null, // ArrayList<Integer> tile_list, // or null. If non-null - do not remeasure members of teh list
null, // ArrayList<Integer> tile_list, // or null. If non-null - do not remeasure members of the list
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
......@@ -1116,7 +1116,7 @@ if (debugLevel > -100) return true; // temporarily !
} // for (int disp_step = 0; disp_step < clt_parameters.rig.rig_num_disp_steps; disp_step++)
// short cycle (remeasure only for teh list). May also break from it if RMS is not improving
// short cycle (remeasure only for the list). May also break from it if RMS is not improving
for (int num_short_cycle = 0; num_short_cycle < clt_parameters.rig.rig_adjust_short_cycles;num_short_cycle++) {
// refine for the existing list - all listed tiles, no thersholds
disparity_bimap = refineRig(
......@@ -1189,27 +1189,39 @@ if (debugLevel > -100) return true; // temporarily !
QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux,
EyesisCorrectionParameters.CLTParameters clt_parameters,
final boolean use_planes,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int debugLevel) throws Exception
final int debugLevel)// throws Exception
{
// boolean combine_oldsel_far = clt_parameters.rig.rf_master_infinity; // = true;
// boolean combine_oldsel_near = clt_parameters.rig.rf_master_near; // = false; //
if ((quadCLT_main.tp == null) || (quadCLT_main.tp.clt_3d_passes == null)) {
String msg = "DSI data not available. Please run\"CLT 3D\" first";
IJ.showMessage(msg);
IJ.showMessage("ERROR",msg);
System.out.println(msg);
return;
}
double [][] rig_disparity_strength = quadCLT_main.getGroundTruthByRig();
if (rig_disparity_strength == null) {
rig_disparity_strength = groundTruthByRig(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
if (use_planes) {
rig_disparity_strength = groundTruthByRigPlanes(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
} else {
rig_disparity_strength = groundTruthByRig(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
}
if (rig_disparity_strength != null) {
quadCLT_main.tp.rig_disparity_strength = rig_disparity_strength;
}
......@@ -1225,7 +1237,7 @@ if (debugLevel > -100) return true; // temporarily !
boolean[] selection = null;
final int tilesX = quadCLT_main.tp.getTilesX();
final int tilesY = quadCLT_main.tp.getTilesY();
BiCamDSI biCamDSI = new BiCamDSI( tilesX, tilesY);
BiCamDSI biCamDSI = new BiCamDSI( tilesX, tilesY, threadsMax);
boolean [][] dbg_sel = (debugLevel > -2)? new boolean [8][]:null;// was 4
if (dbg_sel!=null) dbg_sel[0] = infinity_select;
if (dbg_sel!=null) dbg_sel[1] = was_select;
......@@ -1546,6 +1558,678 @@ if (debugLevel > -100) return true; // temporarily !
}
}
public double [][] prepareRefineExistingDSI(
QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux,
EyesisCorrectionParameters.CLTParameters clt_parameters,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int debugLevel) // throws Exception
{
final int refine_inter = 2; // 3; // 3 - dx, 2 - disparity
final int tilesX = quadCLT_main.tp.getTilesX();
// final int tilesY = quadCLT_main.tp.getTilesY();
if ((quadCLT_main == null) || (quadCLT_aux == null)) {
System.out.println("QuadCLT instances are not initilaized");
return null;
}
// verify main camera has measured data
// Measure with target disparity == 0
if ((quadCLT_main.tp == null) || (quadCLT_main.tp.clt_3d_passes == null) || (quadCLT_main.tp.clt_3d_passes.size() ==0)){
System.out.println("No DSI data for the main camera is available. Please run \"CLT 3D\" command");
return null;
}
// See if auxiliary camera has images configured, if not - do it now.
if (quadCLT_aux.image_name ==null) {
boolean aux_OK = quadCLT_aux.setupImageData(
quadCLT_main.image_name, // String image_name,
quadCLT_main.correctionsParameters.getSourcePaths(), // String [] sourceFiles,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // int threadsMax,
debugLevel); // int debugLevel);
if (!aux_OK) {
return null;
}
}
// Re-measure background
double [][] disparity_bimap_infinity = measureNewRigDisparity(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
null, // double [][] src_bimap, // current state of measurements (or null for new measurement)
0, // double disparity,
null, // ArrayList<Integer> tile_list, // or null. If non-null - do not remeasure members of the list
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
int [] num_new = new int[1];
boolean [] trusted_infinity = getTrustedDisparity(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters.rig.min_trusted_strength, // double min_combo_strength, // check correlation strength combined for all 3 correlations
clt_parameters.grow_disp_trust, // double max_trusted_disparity, // 4.0 -> change to rig_trust
clt_parameters.rig.trusted_tolerance, // double trusted_tolerance,
null, // boolean [] was_trusted,
disparity_bimap_infinity ); // double [][] bimap // current state of measurements
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
(new showDoubleFloatArrays()).showArrays(
disparity_bimap_infinity,
tilesX,
disparity_bimap_infinity[0].length/tilesX,
true,
quadCLT_main.image_name+"DISP_MAP-INFINITY",
ImageDtt.BIDISPARITY_TITLES);
}
double [][] prev_bimap = null;
double [] scale_bad = new double [trusted_infinity.length];
for (int i = 0; i < scale_bad.length; i++) scale_bad[i] = 1.0;
for (int nref = 0; nref < clt_parameters.rig.num_inf_refine; nref++) {
// refine infinity using inter correlation
double [][] disparity_bimap_new = refineRigSel(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
disparity_bimap_infinity, // double [][] src_bimap, // current state of measurements (or null for new measurement)
prev_bimap, // double [][] prev_bimap, // previous state of measurements or null
scale_bad, // double [] scale_bad,
refine_inter, // int refine_mode, // 0 - by main, 1 - by aux, 2 - by inter
false, // boolean keep_inf, // keep expected disparity 0.0 if it was so
0.0, // clt_parameters.rig.refine_min_strength , // double refine_min_strength, // do not refine weaker tiles
clt_parameters.rig.refine_tolerance , // double refine_tolerance, // do not refine if absolute disparity below
trusted_infinity, // tile_list, // ArrayList<Integer> tile_list, // or null
num_new, // int [] num_new,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
prev_bimap = disparity_bimap_infinity;
disparity_bimap_infinity = disparity_bimap_new;
trusted_infinity = getTrustedDisparity(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters.rig.min_trusted_strength, // double min_combo_strength, // check correlation strength combined for all 3 correlations
clt_parameters.grow_disp_trust, // double max_trusted_disparity, // 4.0 -> change to rig_trust
clt_parameters.rig.trusted_tolerance, // double trusted_tolerance,
trusted_infinity, // null, // boolean [] was_trusted,
disparity_bimap_infinity ); // double [][] bimap // current state of measurements
if (debugLevel > -2) {
System.out.println("enhanceByRig(): refined (infinity) "+num_new[0]+" tiles");
}
if (num_new[0] < clt_parameters.rig.min_new) break;
}
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
for (int layer = 0; layer < disparity_bimap_infinity.length; layer ++) if (disparity_bimap_infinity[layer] != null){
for (int nTile = 0; nTile < disparity_bimap_infinity[layer].length; nTile++) {
if (!trusted_infinity[nTile]) disparity_bimap_infinity[layer][nTile] = Double.NaN;
}
}
if (scale_bad!= null) {
int num_bad = 0, num_trusted = 0;
for (int nTile = 0; nTile < scale_bad.length; nTile++) {
if (!trusted_infinity[nTile]) scale_bad[nTile] = Double.NaN;
else {
if (scale_bad[nTile] < 1.0) num_bad++;
scale_bad[nTile] = -scale_bad[nTile];
num_trusted ++;
}
}
System.out.println("num_trusted = "+num_trusted+", num_bad = "+num_bad);
(new showDoubleFloatArrays()).showArrays(
scale_bad,
tilesX,
disparity_bimap_infinity[0].length/tilesX,
quadCLT_main.image_name+"-INFINITY-SCALE_BAD"+clt_parameters.disparity);
}
(new showDoubleFloatArrays()).showArrays(
disparity_bimap_infinity,
tilesX,
disparity_bimap_infinity[0].length/tilesX,
true,
quadCLT_main.image_name+"-INFINITY-REFINED-TRUSTED"+clt_parameters.disparity,
ImageDtt.BIDISPARITY_TITLES);
}
// Get DSI from the main camera
quadCLT_main.tp.trimCLTPasses(false); // remove rig composite scan if any
// last but not including any rid data
CLTPass3d scan_last = quadCLT_main.tp.clt_3d_passes.get( quadCLT_main.tp.clt_3d_passes_size -1); // get last one
double [][] disparity_bimap = setBimapFromCLTPass3d(
scan_last, // CLTPass3d scan,
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
// int [] num_new = new int[1];
boolean [] trusted_near = getTrustedDisparity(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
0.5*clt_parameters.rig.min_trusted_strength, // double min_combo_strength, // check correlation strength combined for all 3 correlations
clt_parameters.grow_disp_trust, // double max_trusted_disparity, // 4.0 -> change to rig_trust
clt_parameters.rig.trusted_tolerance, // double trusted_tolerance,
null, // boolean [] was_trusted,
disparity_bimap); // double [][] bimap // current state of measurements
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
(new showDoubleFloatArrays()).showArrays(
disparity_bimap,
tilesX,
disparity_bimap[0].length/tilesX,
true,
quadCLT_main.image_name+"DISP_MAP-NONINFINITY",
ImageDtt.BIDISPARITY_TITLES);
}
for (int i = 0; i < scale_bad.length; i++) scale_bad[i] = 1.0;
prev_bimap = null;
for (int nref = 0; nref < clt_parameters.rig.num_near_refine; nref++) {
// refine infinity using inter correlation
double [][] disparity_bimap_new = refineRigSel(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
disparity_bimap, // double [][] src_bimap, // current state of measurements (or null for new measurement)
prev_bimap, // double [][] prev_bimap, // previous state of measurements or null
scale_bad, // double [] scale_bad,
refine_inter, // int refine_mode, // 0 - by main, 1 - by aux, 2 - by inter
false, // boolean keep_inf, // keep expected disparity 0.0 if it was so
0.0, // clt_parameters.rig.refine_min_strength , // double refine_min_strength, // do not refine weaker tiles
clt_parameters.rig.refine_tolerance , // double refine_tolerance, // do not refine if absolute disparity below
trusted_near, // tile_list, // ArrayList<Integer> tile_list, // or null
num_new, // int [] num_new,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
prev_bimap = disparity_bimap;
disparity_bimap = disparity_bimap_new;
trusted_near = getTrustedDisparity(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters.rig.min_trusted_strength, // double min_combo_strength, // check correlation strength combined for all 3 correlations
clt_parameters.grow_disp_trust, // double max_trusted_disparity, // 4.0 -> change to rig_trust
clt_parameters.rig.trusted_tolerance, // double trusted_tolerance,
trusted_near, // null, // boolean [] was_trusted,
disparity_bimap ); // double [][] bimap // current state of measurements
if (debugLevel > -2) {
System.out.println("enhanceByRig(): refined (near) "+num_new[0]+" tiles");
}
if (num_new[0] < clt_parameters.rig.min_new) break;
}
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
for (int layer = 0; layer < disparity_bimap.length; layer ++) if (disparity_bimap[layer] != null){
for (int nTile = 0; nTile < disparity_bimap[layer].length; nTile++) {
if (!trusted_near[nTile]) disparity_bimap[layer][nTile] = Double.NaN;
}
}
if (scale_bad!= null) {
int num_bad = 0, num_trusted = 0;
for (int nTile = 0; nTile < scale_bad.length; nTile++) {
if (!trusted_near[nTile]) scale_bad[nTile] = Double.NaN;
else {
if (scale_bad[nTile] < 1.0) num_bad++;
scale_bad[nTile] = -scale_bad[nTile];
num_trusted ++;
}
}
System.out.println("num_trusted = "+num_trusted+", num_bad = "+num_bad);
(new showDoubleFloatArrays()).showArrays(
scale_bad,
tilesX,
disparity_bimap[0].length/tilesX,
quadCLT_main.image_name+"-NEAR-SCALE_BAD"+clt_parameters.disparity);
}
(new showDoubleFloatArrays()).showArrays(
disparity_bimap,
tilesX,
disparity_bimap[0].length/tilesX,
true,
quadCLT_main.image_name+"-NEAR-REFINED-TRUSTED"+clt_parameters.disparity,
ImageDtt.BIDISPARITY_TITLES);
}
// Combine infinity and non-infinity
for (int nTile = 0; nTile < disparity_bimap[0].length; nTile++) {
if (trusted_infinity[nTile] &&
(!trusted_near[nTile] ||
(disparity_bimap_infinity[ImageDtt.BI_STR_ALL_INDEX][nTile] > disparity_bimap[ImageDtt.BI_STR_ALL_INDEX][nTile]))) {
for (int i = 0; i < disparity_bimap.length; i++) if (disparity_bimap_infinity[i]!=null) {
disparity_bimap[i][nTile] = disparity_bimap_infinity[i][nTile];
}
trusted_near[nTile] = true;
}
}
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
(new showDoubleFloatArrays()).showArrays(
disparity_bimap,
tilesX,
disparity_bimap[0].length/tilesX,
true,
quadCLT_main.image_name+"DSI_ALL",
ImageDtt.BIDISPARITY_TITLES);
for (int layer = 0; layer < disparity_bimap.length; layer ++) if (disparity_bimap[layer] != null){
for (int nTile = 0; nTile < disparity_bimap[layer].length; nTile++) {
if (!trusted_near[nTile]) disparity_bimap[layer][nTile] = Double.NaN;
}
}
for (int layer:ImageDtt.BIDISPARITY_STRENGTHS) if (disparity_bimap[layer] != null){
for (int nTile = 0; nTile < disparity_bimap[layer].length; nTile++) {
if (!trusted_near[nTile]) disparity_bimap[layer][nTile] = 0.0;
}
}
(new showDoubleFloatArrays()).showArrays(
disparity_bimap,
tilesX,
disparity_bimap[0].length/tilesX,
true,
quadCLT_main.image_name+"-DSI-ALL-TRUSTED"+clt_parameters.disparity,
ImageDtt.BIDISPARITY_TITLES);
}
return disparity_bimap;
}
public double [][] groundTruthByRigPlanes(
QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux,
EyesisCorrectionParameters.CLTParameters clt_parameters,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int debugLevel) // throws Exception
{
final int num_full_cycles = 3; // Number of full low-texture cycles that include growing flat LT and trimmin weak FG over BG
final int num_cross_gaps_cycles = 20; // maximalnumger of adding new tiles cycles while "crossing the gaps)
final int min_cross_gaps_new = 20; // minimal number of the new added tiles
final int refine_inter = 2; // 3; // 3 - dx, 2 - disparity
final int tilesX = quadCLT_main.tp.getTilesX();
final int tilesY = quadCLT_main.tp.getTilesY();
BiCamDSI biCamDSI = new BiCamDSI( tilesX, tilesY,threadsMax);
System.out.println("groundTruthByRigPlanes()");
double [][] disparity_bimap = prepareRefineExistingDSI(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
if (disparity_bimap == null) {
String msg = "Failed to get (and refine) initial rig DSI from the existing data";
System.out.println(msg);
IJ.showMessage("ERROR",msg);
return null;
}
biCamDSI.addBiScan(disparity_bimap);
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
biCamDSI.getLastBiScan().showScan(
quadCLT_main.image_name+"-BISCAN_initial");
}
int [][] dxy = {{0, -1},{0,1},{-1,0},{1,0}};
for (int num_fcycle = 0; num_fcycle < num_full_cycles; num_fcycle++) {
// Grow tiles, cross gaps (do not trim yet
//
for (int num_cycle = 0; num_cycle < num_cross_gaps_cycles; num_cycle++) {
BiScan last_scan = biCamDSI.getLastBiScan();
int [] trusted_stats = last_scan.calcTrusted( // finds strong trusted and validates week ones if they fit planes
clt_parameters.rig.pf_trusted_strength, // final double trusted_strength, // trusted correlation strength
clt_parameters.rig.pf_strength_rfloor, // final double strength_rfloor, // strength floor - relative to trusted
clt_parameters.rig.pf_cond_rtrusted, // final double cond_rtrusted, // minimal strength to consider - fraction of trusted
clt_parameters.rig.pf_strength_pow, // final double strength_pow, // raise strength-floor to this power
clt_parameters.rig.pf_smpl_radius, // final int smpl_radius,
clt_parameters.rig.pf_smpl_num, // final int smpl_num, // = 3; // Number after removing worst (should be >1)
clt_parameters.rig.pf_smpl_fract, // final double smpl_fract, // Number of friends among all neighbors
clt_parameters.rig.pf_max_adiff, // final double max_adiff, // Maximal absolute difference betweenthe center tile and friends
clt_parameters.rig.pf_max_rdiff, // final double max_rdiff, // Maximal relative difference between the center tile and friends
clt_parameters.rig.pf_max_atilt, // final double max_atilt, // = 2.0; // pix per tile
clt_parameters.rig.pf_max_rtilt, // final double max_rtilt, // = 0.2; // (pix / disparity) per tile
clt_parameters.rig.pf_smpl_arms, // final double smpl_arms, // = 0.1; // Maximal RMS of the remaining tiles in a sample
clt_parameters.rig.pf_smpl_rrms, // final double smpl_rrms, // = 0.005; // Maximal RMS/disparity in addition to smplRms
clt_parameters.rig.pf_damp_tilt, // final double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
clt_parameters.rig.pf_rwsigma, // final double rwsigma, // = 0.7; // influence of far neighbors diminish as a Gaussian with this sigma
clt_parameters.tileX, // final int dbg_x,
clt_parameters.tileY, // final int dbg_y,
debugLevel); // final int debugLevel);
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
biCamDSI.getLastBiScan().showScan(
quadCLT_main.image_name+"-BISCAN_TRUSTED"+num_fcycle+"-"+num_cycle);
}
/*
* @return array of 3 numbers: number of trusted strong tiles, number of additional trusted by plane fitting, and number of all
* somewhat strong tiles
*/
if (debugLevel > -2) {
System.out.println("groundTruthByRigPlanes() grow pass "+num_cycle+" of "+ num_cross_gaps_cycles+
" strong trusted: "+trusted_stats[0]+ " neib trusted: "+trusted_stats[1]+" weak trusted: " + trusted_stats[2]);
}
int num_added_tiles =0;
if (num_cycle < 2*dxy.length) {
// simple duplicating one step in 4 directions
num_added_tiles = last_scan.suggestNewScan(
dxy[num_cycle % dxy.length], // final int [] dxy, //up,down,right,left
clt_parameters.rig.pf_discard_cond, // final boolean discard_cond, // consider conditionally trusted tiles (not promoted to trusted) as empty
clt_parameters.rig.pf_discard_weak, // final boolean discard_weak, // consider conditionally trusted tiles (not promoted to trusted) as empty
clt_parameters.rig.pf_discard_strong, // final boolean discard_strong, // consider conditionally trusted tiles (not promoted to trusted) as empty
clt_parameters.rig.pf_new_diff, // final double new_diff, // minimal difference between the new suggested and the already tried/measured one
true, // final boolean remove_all_tried, // remove from suggested - not only disabled, but all tried
clt_parameters.tileX, // final int dbg_x,
clt_parameters.tileY, // final int dbg_y,
debugLevel); // final int debugLevel);
} else {
// suggest new disparities, using plane surfaces (extending around that may cause false surfaces)
/*
* Suggest disparities to try for the tiles in poorly textured areas by fitting planes in DSI
* calcTrusted should be called before to set up trusted/cond_trusted tiles
* suggested tiles will be compared against and made sure they differ by more than a specified margin
* 1) current measured (refined) disparity value
* 2) target disaprity that lead to the current measurement after refinement
* 3) any other disable measurement
* 4) any target disparity that lead to the disabled measurement
* @return number of new tiles to measure in the array of suggested disparities - Double.NaN - nothing suggested
* for the tile. May need additional filtering to avoid suggested already tried disparities
*/
num_added_tiles = last_scan.suggestNewScan(
clt_parameters.rig.pf_trusted_strength, // final double trusted_strength, // trusted correlation strength
clt_parameters.rig.pf_strength_rfloor, // final double strength_rfloor, // strength floor - relative to trusted
clt_parameters.rig.pf_discard_cond, // final boolean discard_cond, // consider conditionally trusted tiles (not promoted to trusted) as empty
clt_parameters.rig.pf_discard_weak, // final boolean discard_weak, // consider conditionally trusted tiles (not promoted to trusted) as empty
clt_parameters.rig.pf_discard_strong, // final boolean discard_strong, // consider conditionally trusted tiles (not promoted to trusted) as empty
clt_parameters.rig.pf_strength_pow, // final double strength_pow, // raise strength-floor to this power
clt_parameters.rig.pf_smpl_radius, // final int smpl_radius,
clt_parameters.rig.pf_smpl_num, // final int smpl_num, // = 3; // Number after removing worst (should be >1)
clt_parameters.rig.pf_smpl_fract, // final double smpl_fract, // Number of friends among all neighbors
clt_parameters.rig.pf_smpl_num_narrow, // final int smpl_num_narrow, // = 3; // Number after removing worst (should be >1)
clt_parameters.rig.pf_max_adiff, // final double max_adiff, // Maximal absolute difference betweenthe center tile and friends
clt_parameters.rig.pf_max_rdiff, // final double max_rdiff, // Maximal relative difference between the center tile and friends
clt_parameters.rig.pf_max_atilt, // final double max_atilt, // = 2.0; // pix per tile
clt_parameters.rig.pf_max_rtilt, // final double max_rtilt, // = 0.2; // (pix / disparity) per tile
clt_parameters.rig.pf_smpl_arms, // final double smpl_arms, // = 0.1; // Maximal RMS of the remaining tiles in a sample
clt_parameters.rig.pf_smpl_rrms, // final double smpl_rrms, // = 0.005; // Maximal RMS/disparity in addition to smplRms
clt_parameters.rig.pf_damp_tilt, // final double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
clt_parameters.rig.pf_rwsigma, // final double rwsigma, // = 0.7; // influence of far neighbors diminish as a Gaussian with this sigma
clt_parameters.rig.pf_rwsigma_narrow, // final double rwsigma_narrow, // = used to determine initial tilt
clt_parameters.rig.pf_new_diff, // final double new_diff, // minimal difference between the new suggested and the already tried/measured one
true, // final boolean remove_all_tried, // remove from suggested - not only disabled, but all tried
clt_parameters.tileX, // final int dbg_x,
clt_parameters.tileY, // final int dbg_y,
debugLevel); // final int debugLevel);
}
if (debugLevel > -2) {
System.out.println("groundTruthByRigPlanes() full cycle = "+num_fcycle+", grow pass "+num_cycle+" of "+ num_cross_gaps_cycles+
" suggestNewScan() -> "+num_added_tiles);
}
//num_cycle < num_cross_gaps_cycles;
boolean last_cycle = (num_added_tiles < min_cross_gaps_new) || (num_cycle >= (num_cross_gaps_cycles-1));
if (clt_parameters.show_map && (debugLevel > -2) && clt_parameters.rig.rig_mode_debug){
if (last_cycle || (num_cycle < 2 * dxy.length))
biCamDSI.getLastBiScan().showScan(
quadCLT_main.image_name+"-BISCAN_SUGGESTED"+num_fcycle+"-"+num_cycle);
}
if (last_cycle && clt_parameters.rig.pf_en_trim_fg) { // last cycle and trimming enabled
if (debugLevel > -2) {
// System.out.println("groundTruthByRigPlanes(): num_added_tiles= "+num_added_tiles+" > "+min_cross_gaps_new+", done growing over gaps");
System.out.println("groundTruthByRigPlanes(): that was the last growing over gaps cycle, performing trimming hanging weak FG over BG");
}
/*
* Disable low-textured tiles are not between strong tiles, but on one side of it.
* This method relies on the assumption that FG edge should bave strong correlation, so it tries multiple directions
* from the weak (not trusted strong) tiles and trims tiles that eithre do not have anything in that direction or have
* farther tiles.
* Trimming(disabling) weak (trusted but not strong_trusted) tiles if on any one side:
* a) there are no same plane or closer tiles
* b) there are no in-plane or closer strong tiles, but there are some (strong or any?) farther tiles
* repeat while more are trimmed
* maybe, if there are both strong in-plane and far - see which are closer
*/
int num_trimmed = last_scan.trimWeakFG(
clt_parameters.rig.pf_trusted_strength, // final double trusted_strength, // trusted correlation strength
clt_parameters.rig.pf_strength_rfloor, // final double strength_rfloor, // strength floor - relative to trusted
clt_parameters.rig.pf_cond_rtrusted, // final double cond_rtrusted, // minimal strength to consider - fraction of trusted
clt_parameters.rig.pf_strength_pow, // final double strength_pow, // raise strength-floor to this power
clt_parameters.rig.pf_smpl_radius, // final int smpl_radius,
clt_parameters.rig.pf_smpl_num, // final int smpl_num, // = 3; // Number after removing worst (should be >1)
clt_parameters.rig.pf_smpl_fract, // final double smpl_fract, // Number of friends among all neighbors
clt_parameters.rig.pf_max_adiff, // final double max_adiff, // Maximal absolute difference betweenthe center tile and friends
clt_parameters.rig.pf_max_rdiff, // final double max_rdiff, // Maximal relative difference between the center tile and friends
clt_parameters.rig.pf_max_atilt, // final double max_atilt, // = 2.0; // pix per tile
clt_parameters.rig.pf_max_rtilt, // final double max_rtilt, // = 0.2; // (pix / disparity) per tile
clt_parameters.rig.pf_smpl_arms, // final double smpl_arms, // = 0.1; // Maximal RMS of the remaining tiles in a sample
clt_parameters.rig.pf_smpl_rrms, // final double smpl_rrms, // = 0.005; // Maximal RMS/disparity in addition to smplRms
clt_parameters.rig.pf_damp_tilt, // final double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
clt_parameters.rig.pf_rwsigma, // final double rwsigma, // = 0.7; // influence of far neighbors diminish as a Gaussian with this sigma
clt_parameters.rig.pf_atolerance, // final double atolerance, // When deciding closer/farther
clt_parameters.rig.pf_rtolerance, // final double rtolerance, // same, scaled with disparity
clt_parameters.rig.pf_num_dirs, // final int num_dirs, // number of directions to try
clt_parameters.rig.pf_blind_dist, // final double blind_dist, // analyze only tiles farther than this in the selected direction
clt_parameters.rig.pf_strong_only_far, // final boolean strong_only_far, // in variant b) only compare with strong far
clt_parameters.rig.pf_num_strong_far, // final int num_strong_far, // number of directions to try
clt_parameters.rig.pf_num_weak_far, // final int num_weak_far, // number of directions to try
clt_parameters.tileX, // final int dbg_x,
clt_parameters.tileY, // final int dbg_y,
debugLevel); // final int debugLevel);
if (debugLevel > -2) {
System.out.println("groundTruthByRigPlanes(): full cycle="+num_fcycle+" num_trimmed= "+num_trimmed+" tiles");
}
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
biCamDSI.getLastBiScan().showScan(
quadCLT_main.image_name+"-BISCAN_TRIMMED"+num_fcycle+"-"+num_cycle);
}
// suggest again, after trimming
int num_added_tiles_trimmed = last_scan.suggestNewScan(
clt_parameters.rig.pf_trusted_strength, // final double trusted_strength, // trusted correlation strength
clt_parameters.rig.pf_strength_rfloor, // final double strength_rfloor, // strength floor - relative to trusted
clt_parameters.rig.pf_discard_cond, // final boolean discard_cond, // consider conditionally trusted tiles (not promoted to trusted) as empty
clt_parameters.rig.pf_discard_weak, // final boolean discard_weak, // consider conditionally trusted tiles (not promoted to trusted) as empty
clt_parameters.rig.pf_discard_strong, // final boolean discard_strong, // consider conditionally trusted tiles (not promoted to trusted) as empty
clt_parameters.rig.pf_strength_pow, // final double strength_pow, // raise strength-floor to this power
clt_parameters.rig.pf_smpl_radius, // final int smpl_radius,
clt_parameters.rig.pf_smpl_num, // final int smpl_num, // = 3; // Number after removing worst (should be >1)
clt_parameters.rig.pf_smpl_fract, // final double smpl_fract, // Number of friends among all neighbors
clt_parameters.rig.pf_smpl_num_narrow, // final int smpl_num_narrow, // = 3; // Number after removing worst (should be >1)
clt_parameters.rig.pf_max_adiff, // final double max_adiff, // Maximal absolute difference betweenthe center tile and friends
clt_parameters.rig.pf_max_rdiff, // final double max_rdiff, // Maximal relative difference between the center tile and friends
clt_parameters.rig.pf_max_atilt, // final double max_atilt, // = 2.0; // pix per tile
clt_parameters.rig.pf_max_rtilt, // final double max_rtilt, // = 0.2; // (pix / disparity) per tile
clt_parameters.rig.pf_smpl_arms, // final double smpl_arms, // = 0.1; // Maximal RMS of the remaining tiles in a sample
clt_parameters.rig.pf_smpl_rrms, // final double smpl_rrms, // = 0.005; // Maximal RMS/disparity in addition to smplRms
clt_parameters.rig.pf_damp_tilt, // final double damp_tilt, // = 0.001; // Tilt cost for damping insufficient plane data
clt_parameters.rig.pf_rwsigma, // final double rwsigma, // = 0.7; // influence of far neighbors diminish as a Gaussian with this sigma
clt_parameters.rig.pf_rwsigma_narrow, // final double rwsigma_narrow, // = used to determine initial tilt
clt_parameters.rig.pf_new_diff, // final double new_diff, // minimal difference between the new suggested and the already tried/measured one
true, // final boolean remove_all_tried, // remove from suggested - not only disabled, but all tried
clt_parameters.tileX, // final int dbg_x,
clt_parameters.tileY, // final int dbg_y,
debugLevel); // final int debugLevel);
if (debugLevel > -2) {
System.out.println("groundTruthByRigPlanes() full cycle = "+num_fcycle+", grow pass "+num_cycle+" of "+ num_cross_gaps_cycles+
" suggestNewScan() -> "+num_added_tiles_trimmed+"( after trimming)");
}
if (clt_parameters.show_map && (debugLevel > -2) && clt_parameters.rig.rig_mode_debug){
biCamDSI.getLastBiScan().showScan(
quadCLT_main.image_name+"-BISCAN_TRIMMED_SUGGESTED"+num_fcycle+"-"+num_cycle);
}
// break; // too few added before trimmimng or number of steps exceeded limit
} // if (last_cycle && clt_parameters.rig.pf_en_trim_fg) { // last cycle and trimming enabled
// measure and refine
double [] target_disparity = biCamDSI.getTargetDisparity(-1); // get last
// Measure provided tiles (brdeak after, if it was the last cycle)
disparity_bimap = measureNewRigDisparity(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
target_disparity, // double [] disparity, // Double.NaN - skip, ohers - measure
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
// refine measurements
int [] num_new = new int[1];
boolean [] trusted_measurements = getTrustedDisparity(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
clt_parameters.rig.min_trusted_strength, // double min_combo_strength, // check correlation strength combined for all 3 correlations
clt_parameters.grow_disp_trust, // double max_trusted_disparity, // 4.0 -> change to rig_trust
clt_parameters.rig.trusted_tolerance, // double trusted_tolerance,
null, // boolean [] was_trusted,
disparity_bimap); // double [][] bimap // current state of measurements
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
(new showDoubleFloatArrays()).showArrays(
disparity_bimap,
tilesX,
tilesY,
true,
quadCLT_main.image_name+"-gaps_cycle"+num_cycle,
ImageDtt.BIDISPARITY_TITLES);
}
double [][] prev_bimap = null;
double [] scale_bad = new double [trusted_measurements.length];
for (int i = 0; i < scale_bad.length; i++) scale_bad[i] = 1.0;
for (int nref = 0; nref < clt_parameters.rig.num_inf_refine; nref++) {
// refine infinity using inter correlation
double [][] disparity_bimap_new = refineRigSel(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
disparity_bimap, // double [][] src_bimap, // current state of measurements (or null for new measurement)
prev_bimap, // double [][] prev_bimap, // previous state of measurements or null
scale_bad, // double [] scale_bad,
refine_inter, // int refine_mode, // 0 - by main, 1 - by aux, 2 - by inter
false, // boolean keep_inf, // keep expected disparity 0.0 if it was so
0.0, // clt_parameters.rig.refine_min_strength , // double refine_min_strength, // do not refine weaker tiles
clt_parameters.rig.refine_tolerance , // double refine_tolerance, // do not refine if absolute disparity below
trusted_measurements, // tile_list, // ArrayList<Integer> tile_list, // or null
num_new, // int [] num_new,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
prev_bimap = disparity_bimap;
disparity_bimap = disparity_bimap_new;
trusted_measurements = getTrustedDisparityInter(
0.0, // clt_parameters.rig.lt_trusted_strength*clt_parameters.rig.lt_need_friends, // double min_inter_strength, // check correlation strength combined for all 3 correlations
clt_parameters.grow_disp_trust, // double max_trusted_disparity,
trusted_measurements, // boolean [] was_trusted,
disparity_bimap ); // double [][] bimap // current state of measurements
if (debugLevel > -2) {
System.out.println("groundTruthByRigPlanes(): cycle="+num_cycle+", refinement step="+nref+" num_new= "+num_new[0]+" tiles");
}
if (num_new[0] < clt_parameters.rig.pf_min_new) break;
}
//FIXME: show only for last_cycle
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
double [][] dbg_img = new double[disparity_bimap.length][];
for (int layer = 0; layer < disparity_bimap.length; layer ++) if (disparity_bimap[layer] != null){
dbg_img [layer]= disparity_bimap[layer].clone();
for (int nTile = 0; nTile < disparity_bimap[layer].length; nTile++) {
if (!trusted_measurements[nTile]) dbg_img[layer][nTile] = Double.NaN;
}
}
if ((scale_bad!= null) && (debugLevel > 0)){
int num_bad = 0, num_trusted = 0;
for (int nTile = 0; nTile < scale_bad.length; nTile++) {
if (!trusted_measurements[nTile]) scale_bad[nTile] = Double.NaN;
else {
if (scale_bad[nTile] < 1.0) num_bad++;
scale_bad[nTile] = -scale_bad[nTile];
num_trusted ++;
}
}
System.out.println("num_trusted = "+num_trusted+", num_bad = "+num_bad);
(new showDoubleFloatArrays()).showArrays(
scale_bad,
tilesX,
tilesY,
quadCLT_main.image_name+"-gaps_cycle"+num_cycle+"-scale_bad");
}
(new showDoubleFloatArrays()).showArrays(
dbg_img,
tilesX,
tilesY,
true,
quadCLT_main.image_name+"-gaps_cycle"+num_cycle+"-REFINED_TRUSTED",
ImageDtt.BIDISPARITY_TITLES);
}
// add refined data
biCamDSI.addBiScan(disparity_bimap);
// find strongest
biCamDSI.getLastBiScan().copyLastStrongestEnabled(
clt_parameters.rig.pf_last_priority); // final boolean last_priority)
double afloor = clt_parameters.rig.pf_trusted_strength * clt_parameters.rig.pf_strength_rfloor;
// replace strongest by fittest
for (int nfit = 0; nfit < 5; nfit++) {
int num_replaced = biCamDSI.getLastBiScan().copyFittestEnabled(
afloor, // final double str_floor, // absolute strength floor
clt_parameters.rig.pf_disp_afloor, // final double pf_disp_afloor, // = 0.1; // When selecting the best fit from the alternative disparities, divide by difference increased by this
clt_parameters.rig.pf_disp_rfloor); // final double pf_disp_rfloor) // = 0.02; // Increase pf_disp_afloor for large disparities
if ((debugLevel > -2) && clt_parameters.rig.rig_mode_debug){
System.out.println("groundTruthByRigPlanes(): Replacing strongest by fittest: ntry = "+nfit+", replaced "+num_replaced+" tiles");
}
if (num_replaced == 0) {
break;
}
}
if (clt_parameters.show_map && (debugLevel > 0) && clt_parameters.rig.rig_mode_debug){
biCamDSI.getLastBiScan().showScan(
quadCLT_main.image_name+"-BISCAN_"+num_fcycle+"-"+num_cycle);
}
if (last_cycle) { // last cycle
if ((debugLevel > -2) && clt_parameters.rig.rig_mode_debug){
System.out.println("groundTruthByRigPlanes(): that was refinement measurements after the trimming of hanging weak FG over BG");
}
break;
}
// public void showScan(String title) {
} // for (int num_cycle = 0; num_cycle < num_cross_gaps_cycles; num_cycle++) {
}// for (int num_fcycle = 0; num_fcycle < num_full_cycles; num_fcycle++) {
double [][] rig_disparity_strength = biCamDSI.getLastBiScan().getDisparityStrength(
false, // boolean only_strong,
false, // boolean only_trusted,
true); // boolean only_enabled,
return rig_disparity_strength;
}
public double [][] groundTruthByRig(
QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux,
......@@ -1619,7 +2303,7 @@ if (debugLevel > -100) return true; // temporarily !
quadCLT_aux, // QuadCLT quadCLT_aux,
null, // double [][] src_bimap, // current state of measurements (or null for new measurement)
0, // double disparity,
null, // ArrayList<Integer> tile_list, // or null. If non-null - do not remeasure members of teh list
null, // ArrayList<Integer> tile_list, // or null. If non-null - do not remeasure members of the list
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
......@@ -1868,7 +2552,7 @@ if (debugLevel > -100) return true; // temporarily !
// final int tilesX = quadCLT_main.tp.getTilesX();
// final int tilesY = quadCLT_main.tp.getTilesY();
// grow around using all camera and inter-camera correlations (try to get low-textured,like our street pavement)
BiCamDSI biCamDSI = new BiCamDSI( tilesX, tilesY);
BiCamDSI biCamDSI = new BiCamDSI( tilesX, tilesY,threadsMax);
int min_added_tiles = clt_parameters.rig.lt_min_new;
for (int num_fill = 0; num_fill < clt_parameters.rig.lt_repeat; num_fill++) {
int num_new_trusted = biCamDSI.removeLTUntrusted(
......@@ -2003,6 +2687,9 @@ if (debugLevel > -100) return true; // temporarily !
return rig_disparity_strength;
}
public double [][] fillPoorTextureByInter(
QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux,
......@@ -2717,7 +3404,7 @@ if (debugLevel > -100) return true; // temporarily !
QuadCLT quadCLT_aux,
double [][] src_bimap, // current state of measurements (or null for new measurement)
double disparity,
ArrayList<Integer> tile_list, // or null. If non-null - do not remeasure members of teh list
ArrayList<Integer> tile_list, // or null. If non-null - do not remeasure members of the list
EyesisCorrectionParameters.CLTParameters clt_parameters,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
......@@ -2790,6 +3477,57 @@ if (debugLevel > -100) return true; // temporarily !
return disparity_bimap;
}
/**
* Measure with specified disparity array, skip Double.NaN tiles
* @param quadCLT_main main camera QuadCLT instance (should have tp initialized)
* @param quadCLT_aux auxiliary camera QuadCLT instance (should have tp initialized)
* @param disparity expected per-tile disparities. NaN - do not measure
* @param clt_parameters various configuration parameters
* @param threadsMax maximal number of threads to use
* @param updateStatus update IJ status bar
* @param debugLevel debug level
* @return results of the new measurements combined with the old results (if available)
*/
public double [][] measureNewRigDisparity(
QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux,
double [] disparity, // Double.NaN - skip, ohers - measure
EyesisCorrectionParameters.CLTParameters clt_parameters,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int debugLevel){
int tile_op_all = clt_parameters.tile_task_op; //FIXME Use some constant?
int tilesX =quadCLT_main.tp.getTilesX();
int tilesY =quadCLT_main.tp.getTilesY();
int [][] tile_op = new int [tilesY][tilesX];
double [][] disparity_array = new double [tilesY][tilesX];
for (int tileY = 0; tileY<tilesY;tileY++) {
for (int tileX = 0; tileX<tilesX;tileX++) {
int nTile = tileY * tilesX + tileX;
disparity_array[tileY][tileX] = disparity[nTile];
if (!Double.isNaN(disparity[nTile])) {
tile_op[tileY][tileX] = tile_op_all;
//disparity_array[tileY][tileX] = disparity[nTile];
}
}
}
double [][] disparity_bimap = measureRig(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
tile_op, // int [][] tile_op, // common for both amin and aux
disparity_array, // double [][] disparity_array,
null, // double [][] ml_data, // data for ML - 10 layers - 4 center areas (3x3, 5x5,..) per camera-per direction, 1 - composite, and 1 with just 1 data (target disparity)
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
clt_parameters.fat_zero, // double fatzero,
threadsMax, //final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel)
return disparity_bimap;
}
private boolean prepRefineTile(
EyesisCorrectionParameters.CLTParameters clt_parameters,
int tile_op_all,
......
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