Commit 41b89aee authored by Andrey Filippov's avatar Andrey Filippov

Working on pole detection

parent 3967e7b5
...@@ -151,6 +151,9 @@ public class BiQuadParameters { ...@@ -151,6 +151,9 @@ public class BiQuadParameters {
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 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 public int pf_min_new = 5; // Minimal number of he new tiles during rig refine for plane filter
public double lonefg_rstrength = 0.4; // Minimal relative strength of the lone FG tiles
public double lonefg_disp_incr = 1.0; // Maximal disparity of the lone FG tile over maximum of its neighbors
public boolean ltavg_en = true; // apply low texture correlation averaging public boolean ltavg_en = true; // apply low texture correlation averaging
public int ltavg_radius = 1; // low texture averaging radius public int ltavg_radius = 1; // low texture averaging radius
public boolean ltavg_dens_strong = true; // density calculation - consider only strong tiles public boolean ltavg_dens_strong = true; // density calculation - consider only strong tiles
...@@ -470,7 +473,14 @@ public class BiQuadParameters { ...@@ -470,7 +473,14 @@ public class BiQuadParameters {
gd.addNumericField("Minimal refined tiles during plane filter", this.pf_min_new, 0,3,"", gd.addNumericField("Minimal refined tiles during plane filter", this.pf_min_new, 0,3,"",
"Repeat refine antill less tiles are updated"); "Repeat refine antill less tiles are updated");
gd.addTab("LT Avg","Low texture correlatinaveraging");
gd.addMessage("Remove lone FG tiles, that have disparity exceeding maximal neighbor by a margin");
gd.addNumericField("Minimal relative strength of the lone FG tiles", this.lonefg_rstrength, 4,6,"",
"Tile will be removed if it is closer than closest neighbor and is weaker than that neighbor or this value");
gd.addNumericField("Maximal disparity of the lone FG tile over maximum of its neighbors", this.lonefg_disp_incr, 4,6,"pix",
"Tile will be removed if it has disparity higher by this margin that highest neighbor and is weak enough");
gd.addTab("LT Avg","Low texture correlation averaging");
gd.addCheckbox ("Apply low texture correlation averaging", this.ltavg_en, gd.addCheckbox ("Apply low texture correlation averaging", this.ltavg_en,
"Improve low textures by averaging 2-d correlation results"); "Improve low textures by averaging 2-d correlation results");
...@@ -731,6 +741,9 @@ public class BiQuadParameters { ...@@ -731,6 +741,9 @@ public class BiQuadParameters {
this.pf_new_diff= gd.getNextNumber(); this.pf_new_diff= gd.getNextNumber();
this.pf_min_new= (int) gd.getNextNumber(); this.pf_min_new= (int) gd.getNextNumber();
this.lonefg_rstrength= gd.getNextNumber();
this.lonefg_disp_incr= gd.getNextNumber();
this.ltavg_en= gd.getNextBoolean(); this.ltavg_en= gd.getNextBoolean();
this.ltavg_radius= (int) gd.getNextNumber(); this.ltavg_radius= (int) gd.getNextNumber();
this.ltavg_dens_strong= gd.getNextBoolean(); this.ltavg_dens_strong= gd.getNextBoolean();
...@@ -918,6 +931,8 @@ public class BiQuadParameters { ...@@ -918,6 +931,8 @@ public class BiQuadParameters {
properties.setProperty(prefix+"pf_new_diff", this.pf_new_diff+""); properties.setProperty(prefix+"pf_new_diff", this.pf_new_diff+"");
properties.setProperty(prefix+"pf_min_new", this.pf_min_new+""); properties.setProperty(prefix+"pf_min_new", this.pf_min_new+"");
properties.setProperty(prefix+"lonefg_rstrength", this.lonefg_rstrength+"");
properties.setProperty(prefix+"lonefg_disp_incr", this.lonefg_disp_incr+"");
properties.setProperty(prefix+"ltavg_en", this.ltavg_en+""); properties.setProperty(prefix+"ltavg_en", this.ltavg_en+"");
properties.setProperty(prefix+"ltavg_radius", this.ltavg_radius+""); properties.setProperty(prefix+"ltavg_radius", this.ltavg_radius+"");
...@@ -1107,7 +1122,8 @@ public class BiQuadParameters { ...@@ -1107,7 +1122,8 @@ public class BiQuadParameters {
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_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+"pf_min_new")!=null) this.pf_min_new=Integer.parseInt(properties.getProperty(prefix+"pf_min_new"));
if (properties.getProperty(prefix+"lonefg_rstrength")!=null) this.lonefg_rstrength=Double.parseDouble(properties.getProperty(prefix+"lonefg_rstrength"));
if (properties.getProperty(prefix+"lonefg_disp_incr")!=null) this.lonefg_disp_incr=Double.parseDouble(properties.getProperty(prefix+"lonefg_disp_incr"));
if (properties.getProperty(prefix+"ltavg_en")!=null) this.ltavg_en=Boolean.parseBoolean(properties.getProperty(prefix+"ltavg_en")); if (properties.getProperty(prefix+"ltavg_en")!=null) this.ltavg_en=Boolean.parseBoolean(properties.getProperty(prefix+"ltavg_en"));
if (properties.getProperty(prefix+"ltavg_radius")!=null) this.ltavg_radius=Integer.parseInt(properties.getProperty(prefix+"ltavg_radius")); if (properties.getProperty(prefix+"ltavg_radius")!=null) this.ltavg_radius=Integer.parseInt(properties.getProperty(prefix+"ltavg_radius"));
...@@ -1298,6 +1314,9 @@ public class BiQuadParameters { ...@@ -1298,6 +1314,9 @@ public class BiQuadParameters {
bqp.pf_new_diff= this.pf_new_diff; bqp.pf_new_diff= this.pf_new_diff;
bqp.pf_min_new= this.pf_min_new; bqp.pf_min_new= this.pf_min_new;
bqp.lonefg_rstrength= this.lonefg_rstrength;
bqp.lonefg_disp_incr= this.lonefg_disp_incr;
bqp.ltavg_en= this.ltavg_en; bqp.ltavg_en= this.ltavg_en;
bqp.ltavg_radius= this.ltavg_radius; bqp.ltavg_radius= this.ltavg_radius;
bqp.ltavg_dens_strong= this.ltavg_dens_strong; bqp.ltavg_dens_strong= this.ltavg_dens_strong;
......
/** /**
** BiCamScan - calss to represent bultiple bi-quad camera measurements ** BiCamScan - class to represent multiple bi-quad camera measurements
** **
** Copyright (C) 2018 Elphel, Inc. ** Copyright (C) 2018 Elphel, Inc.
** **
...@@ -36,7 +36,7 @@ public class BiScan { ...@@ -36,7 +36,7 @@ public class BiScan {
boolean [] strong_trusted; // sufficient strength without neighbors boolean [] strong_trusted; // sufficient strength without neighbors
boolean [] trusted; boolean [] trusted;
boolean [] cond_trusted; boolean [] cond_trusted;
boolean [] disabled_measurement; // should disable source also boolean [] disabled_measurement; // should disable source, not this!
int [] src_index; // index of the source scan which measured data is used here (applies to disparity_measured, strength_measured, disabled_measurement 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; int list_index = -1;
int scan_type = -1; int scan_type = -1;
...@@ -100,7 +100,7 @@ public class BiScan { ...@@ -100,7 +100,7 @@ public class BiScan {
// disabled[nTile] = true; // disabled[nTile] = true;
// if ((src_index[nTile] >= 0) && (src_index[nTile] != list_index)) { // if ((src_index[nTile] >= 0) && (src_index[nTile] != list_index)) {
if (src_index[nTile] >= 0) { if (src_index[nTile] >= 0) {
biCamDSI.getBiScan(src_index[nTile]).disabled_measurement[nTile] = false; // may be source tile or this tile biCamDSI.getBiScan(src_index[nTile]).disabled_measurement[nTile] = true; // false; // may be source tile or this tile
} }
} }
/** /**
...@@ -1267,6 +1267,71 @@ public class BiScan { ...@@ -1267,6 +1267,71 @@ public class BiScan {
return numTrustedAll; return numTrustedAll;
} }
/**
* Remove stray tiles that are closer than closest neighbor and weaker than it or
* trusted_strength * min_rstrength
* @param trusted_strength absolute raw strength to trust
* @param min_rstrength minimal strength to allow lone FG, relative to trusted_strength
* @param max_disp_inc maximal disparity difference between this tile and the nearest neighbor
* @param dbg_x
* @param dbg_y
* @param debugLevel
* @return number of disabled tiles
*/
int trimWeakLoneFG(
final double trusted_strength, // trusted correlation strength
final double min_rstrength, // strength floor - relative to trusted
final double max_disp_inc,
final int dbg_x,
final int dbg_y,
final int debugLevel
) {
final AtomicInteger ai_trimmed = new AtomicInteger(0);
final double min_strength = trusted_strength * min_rstrength;
final TileNeibs tnImage = biCamDSI.tnImage;
final int num_tiles = tnImage.sizeX * tnImage.sizeY;
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final double [][] ds = getDisparityStrength( // already has disabled zeroed
false, // final boolean only_strong,
false, // final boolean only_trusted,
true) ; // final boolean only_enabled);
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])){
double max_disp = 0;
double max_disp_w = 0;
double d_lim = ds[0][nTile] - max_disp_inc;
double w = ds[1][nTile];
for (int dir = 0; dir < 8; dir++) {
int nTile1 = tnImage.getNeibIndex(nTile, dir);
if ((nTile1 >=0) && (ds[0][nTile1] > max_disp)){
max_disp = ds[0][nTile1];
max_disp_w = ds[1][nTile1];
}
if (max_disp > d_lim) {
break;
}
}
if ((max_disp <= d_lim) && ((w < max_disp_w) || (w < min_strength))) {
disableTile(nTile);
ai_trimmed.getAndIncrement();
if (debugLevel > -4) {
System.out.println("trimWeakLoneFG: removing tile "+nTile+" ("+(nTile%tnImage.sizeX)+":"+(nTile/tnImage.sizeX));
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return ai_trimmed.get();
}
// FG edge should be strong // FG edge should be strong
// Trimming(disabling) weak (trusted but not strong_trusted) tiles if on any one side: // Trimming(disabling) weak (trusted but not strong_trusted) tiles if on any one side:
// a) there are no same plane or closer tiles // a) there are no same plane or closer tiles
......
...@@ -4254,10 +4254,14 @@ private Panel panel1, ...@@ -4254,10 +4254,14 @@ private Panel panel1,
/// ============================================ /// ============================================
} else if (label.equals("CLT 3D") || label.equals("CLT Extrinsics") || label.equals("CLT Poly corr")) { } else if (label.equals("CLT 3D") || label.equals("CLT Extrinsics") || label.equals("CLT Poly corr")) {
boolean adjust_extrinsics = label.equals("CLT Extrinsics") || label.equals("CLT Poly corr"); boolean adjust_extrinsics = label.equals("CLT Extrinsics") || label.equals("CLT Poly corr");
boolean adjust_poly = label.equals("CLT Poly corr"); boolean adjust_poly = label.equals("CLT Poly corr");
DEBUG_LEVEL=MASTER_DEBUG_LEVEL; DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL); EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
clt3d(adjust_extrinsics, adjust_poly);
/*
if (QUAD_CLT == null){ if (QUAD_CLT == null){
QUAD_CLT = new QuadCLT ( QUAD_CLT = new QuadCLT (
QuadCLT.PREFIX, QuadCLT.PREFIX,
...@@ -4327,6 +4331,7 @@ private Panel panel1, ...@@ -4327,6 +4331,7 @@ private Panel panel1,
true, true,
PROPERTIES); PROPERTIES);
} }
*/
return; return;
} else if (label.equals("AUX Extrinsics") || label.equals("AUX Poly corr")) { } else if (label.equals("AUX Extrinsics") || label.equals("AUX Poly corr")) {
boolean adjust_extrinsics = label.equals("AUX Extrinsics") || label.equals("AUX Poly corr"); boolean adjust_extrinsics = label.equals("AUX Extrinsics") || label.equals("AUX Poly corr");
...@@ -5125,11 +5130,11 @@ private Panel panel1, ...@@ -5125,11 +5130,11 @@ private Panel panel1,
if (configPath.equals("ABORT")) return false; if (configPath.equals("ABORT")) return false;
if (DEBUG_LEVEL > -2){ if (DEBUG_LEVEL > -2){
System.out.println("++++++++++++++ Enhancing single-camera DSI by the dual-camera rig using planes ++++++++++++++"); System.out.println("++++++++++++++ Generating GT data for street poles ++++++++++++++");
} }
TWO_QUAD_CLT.processPoles( // actually there is no sense to process multiple image sets. Combine with other processing? TWO_QUAD_CLT.processPoles( // actually there is no sense to process multiple image sets. Combine with other processing?
// QUAD_CLT, // QuadCLT quadCLT_main, QUAD_CLT, // QuadCLT quadCLT_main,
// QUAD_CLT_AUX, // QuadCLT quadCLT_aux, QUAD_CLT_AUX, // QuadCLT quadCLT_aux,
TWO_QUAD_CLT.biCamDSI_persistent, // BiCamDSI biCamDSI, TWO_QUAD_CLT.biCamDSI_persistent, // BiCamDSI biCamDSI,
CLT_PARAMETERS, // EyesisCorrectionParameters.DCTParameters dct_parameters, CLT_PARAMETERS, // EyesisCorrectionParameters.DCTParameters dct_parameters,
THREADS_MAX, //final int threadsMax, // maximal number of threads to launch THREADS_MAX, //final int threadsMax, // maximal number of threads to launch
...@@ -5157,14 +5162,98 @@ private Panel panel1, ...@@ -5157,14 +5162,98 @@ private Panel panel1,
QUAD_CLT.resetGroundTruthByRig(); QUAD_CLT.resetGroundTruthByRig();
return true; return true;
} }
// boolean adjust_extrinsics = label.equals("CLT Extrinsics") || label.equals("CLT Poly corr");
// boolean adjust_poly = label.equals("CLT Poly corr");
public boolean clt3d(
boolean adjust_extrinsics,
boolean adjust_poly
) {
if (QUAD_CLT == null){
QUAD_CLT = new QuadCLT (
QuadCLT.PREFIX,
PROPERTIES,
EYESIS_CORRECTIONS,
CORRECTION_PARAMETERS);
if (DEBUG_LEVEL > 0){
System.out.println("Created new QuadCLT instance, will need to read CLT kernels");
}
}
String configPath=getSaveCongigPath();
if (configPath.equals("ABORT")) return false;
EYESIS_CORRECTIONS.initSensorFiles(DEBUG_LEVEL);
int numChannels=EYESIS_CORRECTIONS.getNumChannels();
CHANNEL_GAINS_PARAMETERS.modifyNumChannels(numChannels);
if (!QUAD_CLT.CLTKernelsAvailable()){
if (DEBUG_LEVEL > 0){
System.out.println("Reading CLT kernels");
}
QUAD_CLT.readCLTKernels(
CLT_PARAMETERS,
THREADS_MAX,
UPDATE_STATUS, // update status info
DEBUG_LEVEL);
if (DEBUG_LEVEL > 1){
QUAD_CLT.showCLTKernels(
THREADS_MAX,
UPDATE_STATUS, // update status info
DEBUG_LEVEL);
}
}
if (!QUAD_CLT.geometryCorrectionAvailable()){
if (DEBUG_LEVEL > 0){
System.out.println("Calculating geometryCorrection");
}
if (!QUAD_CLT.initGeometryCorrection(DEBUG_LEVEL+2)){
return false;
}
}
QUAD_CLT.processCLTQuads3d(
adjust_extrinsics, // boolean adjust_extrinsics,
adjust_poly, // boolean adjust_poly,
CLT_PARAMETERS, // EyesisCorrectionParameters.DCTParameters dct_parameters,
DEBAYER_PARAMETERS, //EyesisCorrectionParameters.DebayerParameters debayerParameters,
// NONLIN_PARAMETERS, //EyesisCorrectionParameters.NonlinParameters nonlinParameters,
COLOR_PROC_PARAMETERS, //EyesisCorrectionParameters.ColorProcParameters colorProcParameters,
CHANNEL_GAINS_PARAMETERS, //CorrectionColorProc.ColorGainsParameters channelGainParameters,
RGB_PARAMETERS, //EyesisCorrectionParameters.RGBParameters rgbParameters,
EQUIRECTANGULAR_PARAMETERS, // EyesisCorrectionParameters.EquirectangularParameters equirectangularParameters,
// CONVOLVE_FFT_SIZE, //int convolveFFTSize, // 128 - fft size, kernel size should be size/2
THREADS_MAX, //final int threadsMax, // maximal number of threads to launch
UPDATE_STATUS, //final boolean updateStatus,
DEBUG_LEVEL); //final int debugLevel);
if (configPath!=null) {
saveTimestampedProperties( // save config again
configPath, // full path or null
null, // use as default directory if path==null
true,
PROPERTIES);
}
return true;
}
public boolean enhanceByRig( boolean use_planes) { public boolean enhanceByRig( boolean use_planes) {
long startTime=System.nanoTime(); long startTime=System.nanoTime();
if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null)) { if ((QUAD_CLT == null) || (QUAD_CLT.tp == null) || (QUAD_CLT.tp.clt_3d_passes == null)) {
String msg = "DSI data is not available. Please run \"CLT 3D\" first"; boolean OK = clt3d(
false, // boolean adjust_extrinsics,
false); // boolean adjust_poly);
if (! OK) {
String msg = "DSI data is not available and \"CLT 3D\" failed";
IJ.showMessage("Error",msg); IJ.showMessage("Error",msg);
System.out.println(msg); System.out.println(msg);
return false; return false;
} }
}
if (!prepareRigImages()) return false; if (!prepareRigImages()) return false;
String configPath=getSaveCongigPath(); String configPath=getSaveCongigPath();
if (configPath.equals("ABORT")) return false; if (configPath.equals("ABORT")) return false;
......
/**
** PoleProcessor - handling poles like street lights and other vertical objects
** common in artificial environments
**
** Copyright (C) 2018 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** PoleProcessor.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.atomic.AtomicInteger;
public class PoleProcessor {
BiCamDSI biCamDSI;
ArrayList<PoleCluster> pole_clusters = new ArrayList<PoleCluster>();
int tilesX;
int tilesY;
class PoleCluster{
double mean_disp = 0.0;
double mean_x = 0.0;
double mean_y = 0.0;
double strength = 0.0;
ArrayList <Integer> tiles = new ArrayList<Integer>();
Rectangle bBox = new Rectangle();
Rectangle eBox; // not calculated, assigned by caller
int layer = -1;
double getMeanDisp() {return mean_disp;}
double getStrength() {return strength;} // to get average strength - need to divide by getNumTiles()
double getMeanX() {return mean_x;}
double getMeanY() {return mean_y;}
int getNumTiles() {return tiles.size();}
ArrayList<Integer> getTiles() {return tiles;}
public Rectangle getBBox() {return bBox;}
public Rectangle getEBox() {return eBox;}
public void trimEBoxBottom(int height) {eBox.height = height;}
public void setEBox(
int ext_left,
int ext_right,
int ext_up,
int ext_down)
{
this.eBox = new Rectangle(
bBox.x - ext_left,
bBox.y - ext_up,
bBox.width + ext_right + ext_left,
bBox.height + ext_up + ext_down);
if (eBox.x < 0) {
eBox.width+=eBox.x;
eBox.x = 0;
}
if (eBox.y < 0) {
eBox.height +=eBox.y;
eBox.y = 0;
}
if ((eBox.x + eBox.width) >= tilesX) {
eBox.width = tilesX - eBox.x;
}
if ((eBox.y + eBox.height) >= tilesY) {
eBox.height = tilesY - eBox.y;
}
}
public boolean intersects(PoleCluster cluster) {
return this.eBox.intersects(cluster.eBox);
}
public void setLayer(int layer) {this.layer = layer;}
public int getLayer() {return layer;}
void addCluster(
double [][] norm_ds,
PoleCluster cluster)
{
for (int otherTile:cluster.getTiles()) {
addTile(norm_ds, otherTile);
}
// merge eBox-es if any
if ((eBox != null) && (cluster.eBox !=null)) {
eBox.add(cluster.eBox);
}
}
void addTile(
double [][] norm_ds,
int nTile)
{
if (tiles.indexOf(nTile) >=0) {
System.out.println("*** BUG in PoleCluster.addTile("+nTile+") - tile already exists here ***");
return; //
}
if (norm_ds[1][nTile] <= 0) {
System.out.println("*** BUG in PoleCluster.addTile("+nTile+") - strength= "+norm_ds[1][nTile]+" ***");
return; //
}
TileNeibs tnImage = biCamDSI.tnImage;
int tileX = nTile % tnImage.sizeX;
int tileY = nTile / tnImage.sizeX;
mean_disp = (mean_disp * strength + norm_ds[0][nTile] * norm_ds[1][nTile])/(strength + norm_ds[1][nTile]);
mean_x = (mean_x * strength + tileX * norm_ds[1][nTile])/(strength + norm_ds[1][nTile]);
mean_y = (mean_y * strength + tileY * norm_ds[1][nTile])/(strength + norm_ds[1][nTile]);
strength += norm_ds[1][nTile];
if (tiles.isEmpty() || ( tileX < bBox.x)) bBox.x = tileX;
if (tiles.isEmpty() || ((tileX - bBox.x) > (bBox.width -1))) bBox.width = tileX - bBox.x + 1;
if (tiles.isEmpty() || ( tileY < bBox.y)) bBox.y = tileY;
if (tiles.isEmpty() || ((tileY - bBox.y) > (bBox.height -1))) bBox.height = tileY - bBox.y + 1;
tiles.add(nTile);
}
// remove would be trikier - will need to recalculate bBox
void removeTile(
double [][] norm_ds,
int nTile)
{
int indx = tiles.indexOf(nTile);
if (indx < 0) {
System.out.println("*** BUG in PoleCluster.removeTile("+nTile+") - tile does not belong here ***");
return; //
}
TileNeibs tnImage = biCamDSI.tnImage;
int tileX = nTile % tnImage.sizeX;
int tileY = nTile / tnImage.sizeX;
mean_disp = (mean_disp * strength - norm_ds[0][nTile] * norm_ds[1][nTile])/(strength - norm_ds[1][nTile]);
mean_x = (mean_x * strength - tileX * norm_ds[1][nTile])/(strength - norm_ds[1][nTile]);
mean_y = (mean_y * strength - tileY * norm_ds[1][nTile])/(strength - norm_ds[1][nTile]);
strength -= norm_ds[1][nTile];
tiles.remove(indx);
// re-calculate bounding box
for (int i = 0; i < tiles.size(); i++ ) {
int nt = tiles.get(i);
tileX = nt % tnImage.sizeX;
tileY = nt / tnImage.sizeX;
if ((i==0) || ( tileX < bBox.x)) bBox.x = tileX;
if ((i==0) || ((tileX - bBox.x) > (bBox.width -1))) bBox.width = tileX - bBox.x + 1;
if ((i==0) || ( tileY < bBox.y)) bBox.y = tileX;
if ((i==0) || ((tileY - bBox.y) > (bBox.height -1))) bBox.height = tileY - bBox.y + 1;
}
}
}
public PoleProcessor (
BiCamDSI biCamDSI,
int tilesX,
int tilesY)
{
this.biCamDSI = biCamDSI;
this.tilesX = tilesX;
this.tilesY = tilesY;
}
public double [][] conditionDisparityStrength(
final BiScan biScan,
final double trusted_strength, // trusted correlation strength
final double strength_rfloor,
final double strength_pow
) {
final double strength_floor = trusted_strength * strength_rfloor;
final TileNeibs tnImage = biCamDSI.tnImage;
final int num_tiles = tnImage.sizeX * tnImage.sizeY;
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final double [][] cond_ds = new double [2] [num_tiles];
final double [][] disparity_strength = biScan.getDisparityStrength(
false, // only_strong,
false, // only_trusted,
true); // only_enabled);
// final AtomicInteger ai_num_seeds = new AtomicInteger(0);
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(disparity_strength[0][nTile]) &&(disparity_strength[1][nTile] > strength_floor)){
double w = disparity_strength[1][nTile] - strength_floor;
if (strength_pow != 1.0) {
w = Math.pow(w, strength_pow);
}
cond_ds[0][nTile] = disparity_strength[0][nTile];
cond_ds[1][nTile] = w;
} else {
cond_ds[0][nTile] = Double.NaN;
cond_ds[1][nTile] = 0.0;
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return cond_ds;
}
public boolean [] findSeeds(
final double [][] norm_ds,
final double min_strength, // after subtracting floor and possible applying pow
final int seed_down,
final double seed_aover,
final double seed_rover,
final double max_disparity
) {
final TileNeibs tnImage = biCamDSI.tnImage;
final int num_tiles = tnImage.sizeX * tnImage.sizeY;
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final boolean [] seeds = new boolean [num_tiles];
// final AtomicInteger ai_num_seeds = new AtomicInteger(0);
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 (norm_ds[1][nTile] > min_strength){
double d_head = norm_ds[0][nTile];
if ((d_head <= max_disparity) && (d_head > seed_aover)) {
double sw = 0.0;
double swd = 0.0;
int nTile1 = nTile; // tnImage.getNeibIndex(indx, TileNeibs.DIR_DOWN);
for (int i = 0; i < seed_down; i++) {
nTile1 = tnImage.getNeibIndex(nTile1, TileNeibs.DIR_DOWN);
if ((nTile1 >= 0) && (norm_ds[1][nTile1] > 0.0) && !Double.isNaN(norm_ds[0][nTile1])) {
double w = norm_ds[1][nTile1];
sw += w;
swd += w * norm_ds[0][nTile1];
}
}
if (sw > 0.0){
swd /= sw; // weighted average of the disparities right below
double threshold = swd + seed_aover + seed_rover * d_head;
if (d_head >= threshold) {
seeds[nTile] = true;
// ai_num_seeds.getAndIncrement();
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return seeds;
}
public ArrayList<PoleCluster> initPoleClusters(
final double max_dx,
final double max_dy,
final double max_dd,
boolean [] bseeds,
double [][] norm_ds,
final int debugLevel)
{
final TileNeibs tnImage = biCamDSI.tnImage;
ArrayList<PoleCluster> clusters = new ArrayList<PoleCluster>();
for (int nTile = 0; nTile < bseeds.length; nTile++) if (bseeds[nTile]){
double this_disp = norm_ds[0][nTile];
int tileX = nTile % tnImage.sizeX;
int tileY = nTile / tnImage.sizeX;
label_gotit: {
for (PoleCluster cluster: clusters) {
if (
!(Math.abs(cluster.getMeanDisp() - this_disp) > max_dd) && // to allow Double.NaN
!(Math.abs(cluster.getMeanX() - tileX) > max_dx) &&
!(Math.abs(cluster.getMeanY() - tileY) > max_dy)) {
cluster.addTile(norm_ds, nTile);
break label_gotit;
}
}
// did not find, need to create a new cluster
PoleCluster cluster = new PoleCluster();
cluster.addTile(norm_ds, nTile);
clusters.add(cluster);
}
}
sortClustersByDisparity(clusters);
return clusters;
}
public void extendClusters(
int ext_left,
int ext_right,
int ext_up,
int ext_down,
ArrayList<PoleCluster> clusters)
{
for (PoleCluster cluster: clusters) {
// Assign extended bounding box to each cluster
cluster.setEBox(
ext_left,
ext_right,
ext_up,
ext_down);
}
}
public void cutClusterBottoms(
final double [][] norm_ds,
final double pedestal_strength, // bottom tiles should be at least this strong (normalized strength)
final double pedestal_disp_over, // bottom tiles should have disparity at least by this above cluster
final ArrayList<PoleCluster> clusters)
{
// can be multithreaded
final TileNeibs tnImage = biCamDSI.tnImage;
// final int num_tiles = tnImage.sizeX * tnImage.sizeY;
final Thread[] threads = ImageDtt.newThreadArray(biCamDSI.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final int num_clust = clusters.size();
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nClust = ai.getAndIncrement(); nClust < num_clust; nClust = ai.getAndIncrement()) {
PoleCluster cluster = clusters.get(nClust);
Rectangle bBox = cluster.getBBox(); // never extends beyond ?
Rectangle eBox = cluster.getEBox();
int nTile = eBox.x + tilesX * eBox.y;
double disp_marg = cluster.getMeanDisp() + pedestal_disp_over;
for (int dy = bBox.y - eBox.y + bBox.height; dy < eBox.height; dy++) {
// label
label_still_some_far_weak:{
for ( int dx = 0; dx < eBox.width; dx++) {
int nTile1 = tnImage.getNeibIndex(nTile, dx, dy); // should always be inside image
if ( (norm_ds[1][nTile1] < pedestal_strength) ||
(norm_ds[0][nTile1] < disp_marg)) {
break label_still_some_far_weak;
}
}
// found pedestal - trim eBox
cluster.trimEBoxBottom(dy);
break;
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
public int assignClustersToLayers(
ArrayList<PoleCluster> clusters)
{
ArrayList<ArrayList<PoleCluster>> layer_lists = new ArrayList<ArrayList<PoleCluster>>();
for (PoleCluster cluster: clusters) {
// Assign extended bounding box to each cluster
// see if this cluster fits to any of the existing layers
label_layers:{
for (int nlayer = 0; nlayer < layer_lists.size(); nlayer++) {
ArrayList<PoleCluster> layer = layer_lists.get(nlayer);
// see if current cluster intersects with any on this layer
label_clusters: {
for (PoleCluster other_cluster: layer){
if (cluster.intersects(other_cluster)) {
break label_clusters; // this layer won't work
}
}
// Layer OK
cluster.setLayer(nlayer);
layer.add(cluster);
break label_layers;
}
}
// need new layer
cluster.setLayer(layer_lists.size());
ArrayList<PoleCluster> new_layer = new ArrayList<PoleCluster>();
new_layer.add(cluster);
layer_lists.add(new_layer);
}
}
return layer_lists.size();
}
public int mergeOverlappingClusters(
boolean extended,
double disp_tolerance,
double [][] norm_ds,
ArrayList<PoleCluster> clusters,
int debugLevel)
{
int num_merge = 0;
for (int nCluster = 0; nCluster < clusters.size(); nCluster++) {
PoleCluster cluster = clusters.get(nCluster);
double this_disp = cluster.getMeanDisp();
Rectangle this_box = extended?cluster.getEBox():cluster.getBBox();
for (int nOther = 0; nOther < nCluster; nOther++) {
PoleCluster other_cluster = clusters.get(nOther);
double other_disp = other_cluster.getMeanDisp();
Rectangle other_box = extended?other_cluster.getEBox():other_cluster.getBBox();
if (this_box.intersects(other_box) && (Math.abs(other_disp - this_disp) < disp_tolerance)) {
if (debugLevel > -2) {
System.out.println("Merging cluster " +nCluster+ " to cluster " +nOther);
System.out.println("Merging cluster ("+this_box.x+","+this_box.y+","+this_box.width+","+this_box.height+") disp="+this_disp+
" to cluster ("+other_box.x+","+other_box.y+","+other_box.width+","+other_box.height+") disp="+other_disp);
}
other_cluster.addCluster(norm_ds, cluster);
clusters.remove(nCluster);
nCluster--; // so when incremented by for() it will stay the same
num_merge++;
if (debugLevel > -2) {
other_disp = other_cluster.getMeanDisp();
other_box = extended ? other_cluster.getEBox(): other_cluster.getBBox();
System.out.println("Combined cluster: ("+other_box.x+","+other_box.y+","+other_box.width+","+other_box.height+") disp="+other_disp);
}
break;
}
}
}
return num_merge;
}
double [][] dbgClusterLayers( // layer and eBox should be set
boolean show_bbox,
boolean show_ebox,
ArrayList<PoleCluster> clusters)
{
final TileNeibs tnImage = biCamDSI.tnImage;
int tilesX = tnImage.sizeX;
int tilesY = tnImage.sizeY;
int num_tiles = tilesY*tilesX;
int num_layers = 0;
for (PoleCluster cluster: clusters){
int cl = cluster.getLayer();
if (cl > num_layers) num_layers = cl;
}
num_layers++;
double [][] dbg_layers = new double [num_layers][num_tiles];
for (int i = 0; i < num_layers; i++) {
for (int j=0; j < num_tiles; j++) {
dbg_layers[i][j] = Double.NaN;
}
}
for (PoleCluster cluster: clusters){
int layer = cluster.getLayer();
double disp = cluster.getMeanDisp();
Rectangle [] rectangles = {show_bbox?cluster.getBBox():null,show_ebox?cluster.getEBox():null};
for (int nbox = 0; nbox< rectangles.length; nbox++) {
Rectangle box = new Rectangle(rectangles[nbox]);
if (box.x < 0) {
box.width+=box.x;
box.x = 0;
}
if (box.y < 0) {
box.height +=box.y;
box.y = 0;
}
if ((box.x + box.width) >= tilesX) {
box.width = tilesX - box.x;
}
if ((box.y + box.height) >= tilesY) {
box.height = tilesY - box.y;
}
int nTile = box.y * tilesX + box.x;
for (int dx = 0; dx < box.width;dx++) {
if (tnImage.getNeibIndex(nTile, dx, 0) < 0 ) {
System.out.println("dbgClusterLayers() bug 1: box.x ="+box.x+", box.width="+box.width+"box.y ="+box.y+", box.height="+box.height+"dx="+dx);
continue;
}
dbg_layers[layer][tnImage.getNeibIndex(nTile, dx, 0)] = disp; // should never be out of bounds
if (tnImage.getNeibIndex(nTile, dx, box.height -1) < 0 ) {
System.out.println("dbgClusterLayers() bug 2: box.x ="+box.x+", box.width="+box.width+"box.y ="+box.y+", box.height="+box.height+"dx="+dx);
continue;
}
dbg_layers[layer][tnImage.getNeibIndex(nTile, dx, box.height -1)] = disp; // should never be out of bounds
}
for (int dy = 1; dy < box.height - 1; dy++) {
if (tnImage.getNeibIndex(nTile, 0, dy) < 0 ) {
System.out.println("dbgClusterLayers() bug 3: box.x ="+box.x+", box.width="+box.width+"box.y ="+box.y+", box.height="+box.height+"dy="+dy);
continue;
}
dbg_layers[layer][tnImage.getNeibIndex(nTile, 0, dy)] = disp; // should never be out of bounds
if (tnImage.getNeibIndex(nTile, box.width -1, dy) < 0 ) {
System.out.println("dbgClusterLayers() bug 4: box.x ="+box.x+", box.width="+box.width+"box.y ="+box.y+", box.height="+box.height+"dy="+dy);
continue;
}
dbg_layers[layer][tnImage.getNeibIndex(nTile, box.width -1, dy)] = disp; // should never be out of bounds
}
}
}
return dbg_layers;
}
double [][] getClusterLayers( // layer and eBox should be set
ArrayList<PoleCluster> clusters)
{
final TileNeibs tnImage = biCamDSI.tnImage;
int tilesX = tnImage.sizeX;
int tilesY = tnImage.sizeY;
int num_tiles = tilesY*tilesX;
int num_layers = 0;
for (PoleCluster cluster: clusters){
int cl = cluster.getLayer();
if (cl > num_layers) num_layers = cl;
}
num_layers++;
double [][] dbg_layers = new double [num_layers][num_tiles];
for (int i = 0; i < num_layers; i++) {
for (int j=0; j < num_tiles; j++) {
dbg_layers[i][j] = Double.NaN;
}
}
for (PoleCluster cluster: clusters){
int layer = cluster.getLayer();
double disp = cluster.getMeanDisp();
Rectangle box = new Rectangle(cluster.getEBox());
if (box.x < 0) {
box.width+=box.x;
box.x = 0;
}
if (box.y < 0) {
box.height +=box.y;
box.y = 0;
}
if ((box.x + box.width) >= tilesX) {
box.width = tilesX - box.x;
}
if ((box.y + box.height) >= tilesY) {
box.height = tilesY - box.y;
}
int nTile = box.y * tilesX + box.x;
for (int dy = 0; dy < box.height; dy++) {
for (int dx = 0; dx < box.width;dx++) {
dbg_layers[layer][tnImage.getNeibIndex(nTile, dx, dy)] = disp; // should never be out of bounds
}
}
}
return dbg_layers;
}
public void sortClustersByDisparity(
ArrayList<PoleCluster> clusters)
{
Collections.sort(clusters, new Comparator<PoleCluster>() {
@Override
public int compare(PoleCluster lhs, PoleCluster rhs) {
// -1 - less than, 1 - greater than, 0 - equal
return (rhs.mean_disp > lhs.mean_disp) ? -1 : (rhs.mean_disp < lhs.mean_disp ) ? 1 : 0;
}
});
}
}
...@@ -25,6 +25,20 @@ import java.util.Arrays; ...@@ -25,6 +25,20 @@ import java.util.Arrays;
*/ */
public class TileNeibs{ public class TileNeibs{
final static int DIR_N = 0; // UP
final static int DIR_NE = 1;
final static int DIR_E = 2; // Right
final static int DIR_SE = 3;
final static int DIR_S = 4; // Down
final static int DIR_SW = 5;
final static int DIR_W = 6; // Left
final static int DIR_NW = 7;
final static int DIR_CENTER = -1;
final static int DIR_UP = 0; // UP
final static int DIR_LEFT = 2; // Right
final static int DIR_DOWN = 4; // Down
final static int DIR_RIGHT = 6; // Left
int sizeX; int sizeX;
int sizeY; int sizeY;
public int dirs = 8; public int dirs = 8;
......
...@@ -33,6 +33,7 @@ public class TwoQuadCLT { ...@@ -33,6 +33,7 @@ public class TwoQuadCLT {
public long startSetTime; // start of set processing public long startSetTime; // start of set processing
public long startStepTime; // start of step processing public long startStepTime; // start of step processing
BiCamDSI biCamDSI_persistent; // may be removed later to save memory, now to be able to continue BiCamDSI biCamDSI_persistent; // may be removed later to save memory, now to be able to continue
PoleProcessor poleProcessor_persistent;
public void processCLTQuadCorrs( public void processCLTQuadCorrs(
QuadCLT quadCLT_main, QuadCLT quadCLT_main,
...@@ -1207,18 +1208,328 @@ if (debugLevel > -100) return true; // temporarily ! ...@@ -1207,18 +1208,328 @@ if (debugLevel > -100) return true; // temporarily !
return true; return true;
} }
public void processPoles( public boolean processPoles(
// QuadCLT quadCLT_main, // tiles should be set QuadCLT quadCLT_main, // tiles should be set
// QuadCLT quadCLT_aux, QuadCLT quadCLT_aux,
BiCamDSI biCamDSI, BiCamDSI biCamDSI,
EyesisCorrectionParameters.CLTParameters clt_parameters, EyesisCorrectionParameters.CLTParameters clt_parameters,
final int threadsMax, // maximal number of threads to launch final int threadsMax, // maximal number of threads to launch
final boolean updateStatus, final boolean updateStatus,
final int debugLevel)// throws Exception final int debugLevel)// throws Exception
{ {
System.out.println("**** Nothing here yet ****"); if ((quadCLT_main == null) ||
(quadCLT_main.tp == null) ||
(quadCLT_main.tp.clt_3d_passes == null) ||
(biCamDSI_persistent== null) ||
(biCamDSI_persistent.biScans== null)) {
String msg = "Data is not available. Please run \"Ground truth\" first";
IJ.showMessage("Error",msg);
System.out.println(msg);
return false;
}
int scan_index = biCamDSI_persistent.biScans.size()-1;
BiScan biScan = biCamDSI_persistent.biScans.get(scan_index);
biScan.showScan(quadCLT_main.image_name+"LastBiScan-"+scan_index, null);
if (poleProcessor_persistent == null) {
poleProcessor_persistent = new PoleProcessor(
biCamDSI_persistent,
quadCLT_main.tp.getTilesX(),
quadCLT_main.tp.getTilesY());
}
PoleProcessor pp = poleProcessor_persistent;
final double seed_rsrength = 0.8;
final int seed_down = 5;
final double seed_aover = 0.2;
final double seed_rover = 0.05;
final double max_disparity = 5.0;
double [][] norm_ds = pp.conditionDisparityStrength(
biScan, // final BiScan biScan,
clt_parameters.rig.pf_trusted_strength, // final double trusted_strength, // trusted correlation strength
clt_parameters.rig.pf_strength_rfloor, // final double strength_rfloor,
clt_parameters.rig.pf_strength_pow); // final double strength_pow,
double seed_min_strength = clt_parameters.rig.pf_trusted_strength* (1.0 - clt_parameters.rig.pf_strength_rfloor) * seed_rsrength;
if (clt_parameters.rig.pf_strength_pow != 1.0) {
seed_min_strength = Math.pow(seed_min_strength, clt_parameters.rig.pf_strength_pow);
}
boolean [] seeds = pp.findSeeds(
norm_ds, // final double [][] norm_ds,
seed_min_strength, // final double min_strength, // after subtracting floor and possible applying pow
seed_down, // final int seed_down,
seed_aover, // final double seed_aover,
seed_rover, // final double seed_rover,
max_disparity); // final double max_disparity);
double max_dd = 0.1;
double max_dx = 5;
double max_dy = Double.NaN;
int ext_side = 2;
int ext_up = 2;
int ext_down = 30;
double pedestal_strength = 0.15;
double pedestal_disp_over = 0.3;
ArrayList<PoleProcessor.PoleCluster> pole_clusters= pp.initPoleClusters(
max_dx, // final double max_dx,
max_dy, // final double max_dy,
max_dd, // final double max_dd,
seeds, // boolean [] bseeds,
norm_ds, // double [][] norm_ds,
debugLevel); //final int debugLevel)
pp.extendClusters(
ext_side, // int ext_left,
ext_side, // int ext_right,
ext_up, // int ext_up,
ext_down, // int ext_down,
pole_clusters); // ArrayList<PoleCluster> clusters)
pp.cutClusterBottoms(
norm_ds, // final double [][] norm_ds,
pedestal_strength, // final double pedestal_strength, // bottom tiles should be at least this strong (normalized strength)
pedestal_disp_over, // final double pedestal_disp_over, // bottom tiles should have disparity at least by this above cluster
pole_clusters); // final ArrayList<PoleCluster> clusters)
boolean extended = false; // merge if only original clusters intersect
double disp_tolerance = 1.5; // max_dd;
int num_merged=pp.mergeOverlappingClusters(
extended, // boolean extended,
disp_tolerance, // double disp_tolerance,
norm_ds, // double [][] norm_ds,
pole_clusters, // ArrayList<PoleCluster> clusters,
debugLevel); // int debugLevel)
if (debugLevel > -2) {
System.out.println("Merged "+num_merged+" clusters");
}
int num_layers = pp.assignClustersToLayers(
pole_clusters); // ArrayList<PoleCluster> clusters)
double [][] layers_to_measure = pp.getClusterLayers(
pole_clusters); // ArrayList<PoleCluster> clusters)
if (debugLevel > -2) {
double [][] disparity_strength = biScan.getDisparityStrength(
false, // only_strong,
false, // only_trusted,
true); // only_enabled);
double [][] dbg_seeds = new double [2][seeds.length];
int num_seeds = 0;
for (int i = 0; i < dbg_seeds[0].length; i++ ) {
if (seeds[i]){
dbg_seeds[0][i] = disparity_strength[0][i];
dbg_seeds[1][i] = 1.0; // same contrast
num_seeds++;
} else {
dbg_seeds[0][i] = Double.NaN;
}
}
double [][] dbg_clust = new double [2][seeds.length];
for (int i = 0; i < dbg_seeds[0].length; i++ ) {
dbg_clust[0][i] = Double.NaN;
dbg_clust[1][i] = Double.NaN;
}
for (int nclust = 0; nclust < pole_clusters.size(); nclust++) {
PoleProcessor.PoleCluster cluster = pole_clusters.get(nclust);
double d = cluster.getMeanDisp();
ArrayList<Integer> tiles = cluster.getTiles();
for (int i: tiles) {
dbg_clust[0][i] = d;
dbg_clust[1][i] = 0.01*nclust;
}
}
biScan.showScan(quadCLT_main.image_name+"-Seeds-"+scan_index, dbg_seeds);
biScan.showScan(quadCLT_main.image_name+"-Clusters-"+scan_index, dbg_clust);
biScan.showScan(quadCLT_main.image_name+"-norm_ds-"+scan_index, norm_ds);
System.out.println("findSeeds() detected "+num_seeds+" tiles as poles seeds");
System.out.println("initPoleClusters() detected "+pole_clusters.size()+" clusters as poles seeds");
System.out.println("assignClustersToLayers() detected "+num_layers+" layers to probe poles seeds");
int tilesX = quadCLT_main.tp.getTilesX();
double [][] dbg_layers = pp.dbgClusterLayers( // layer and eBox should be set
true, // boolean show_bbox,
true, // boolean show_ebox,
pole_clusters); // ArrayList<PoleCluster> clusters)
double [][] dbg_layers1 = new double [dbg_layers.length+2][];
for (int i = 0; i <dbg_layers.length; i++) {
dbg_layers1[i] = dbg_layers[i];
}
dbg_layers1[dbg_layers.length + 0] = norm_ds[0];
dbg_layers1[dbg_layers.length + 1] = norm_ds[1];
(new showDoubleFloatArrays()).showArrays(
dbg_layers1,
tilesX,
dbg_layers[0].length/tilesX,
true,
"CLUSTER-BOXES");
(new showDoubleFloatArrays()).showArrays(
layers_to_measure,
tilesX,
layers_to_measure[0].length/tilesX,
true,
"LAYERS_TO_MEASURE");
}
// Just measuring poles with different averaging
double high_disp_tolerance = 0.3;
double low_disp_tolerance = 0.3;
double min_strength = 0.15;
double [][][] measured_poles = measurePoles(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
layers_to_measure, // double [][] poles_ds,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
false, // boolean notch_mode, // use pole-detection mode for inter-camera correlation
0, // int lt_rad, // low texture mode - inter-correlation is averaged between the neighbors before argmax-ing, using (2*notch_mode+1)^2 square
threadsMax, //final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
measured_poles = removeDisparityMismatch(
measured_poles, // double [][][] ds_src,
high_disp_tolerance, // double high_disp_tolerance,
low_disp_tolerance, //double low_disp_tolerance );
min_strength); //double min_strength);//
showMeasuredPoles(
"MEASURED_POLES-CENTER", // String title,
quadCLT_main.tp.getTilesX(), // tilesX, // int tilesX,
measured_poles); // double [][][] measured_poles);
double [][][] measured_poles_strongest = poleAddStrongest(
measured_poles, // double [][][] ds_src,
null); // double [][][] ds_other)
double [][][] measured_poles_fittest = poleAddFittest(
measured_poles, // double [][][] ds_src,
null); // double [][][] ds_other)
for (int num_avg = 0; num_avg < 5; num_avg++) {
measured_poles = measurePoles(
quadCLT_main, // QuadCLT quadCLT_main, // tiles should be set
quadCLT_aux, // QuadCLT quadCLT_aux,
layers_to_measure, // double [][] poles_ds,
clt_parameters, // EyesisCorrectionParameters.CLTParameters clt_parameters,
true, // boolean notch_mode, // use pole-detection mode for inter-camera correlation
num_avg, // int lt_rad, // low texture mode - inter-correlation is averaged between the neighbors before argmax-ing, using (2*notch_mode+1)^2 square
threadsMax, //final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
measured_poles = removeDisparityMismatch(
measured_poles, // double [][][] ds_src,
high_disp_tolerance, // double high_disp_tolerance,
low_disp_tolerance, //double low_disp_tolerance );
min_strength); //double min_strength);//
measured_poles_strongest = poleAddStrongest(
measured_poles_strongest, // double [][][] ds_src,
measured_poles); // double [][][] ds_other)
measured_poles_fittest = poleAddFittest(
measured_poles_fittest, // double [][][] ds_src,
measured_poles); // double [][][] ds_other)
showMeasuredPoles(
"MEASURED_POLES-AVG"+num_avg, // String title,
quadCLT_main.tp.getTilesX(), // tilesX, // int tilesX,
measured_poles); // double [][][] measured_poles);
}
showMeasuredPoles(
"MEASURED_POLES-STRONGEST", // String title,
quadCLT_main.tp.getTilesX(), // tilesX, // int tilesX,
measured_poles_strongest); // double [][][] measured_poles);
showMeasuredPoles(
"MEASURED_POLES-FITTEST", // String title,
quadCLT_main.tp.getTilesX(), // tilesX, // int tilesX,
measured_poles_fittest); // double [][][] measured_poles);
return true;
}
public double [][][] removeDisparityMismatch(
double [][][] ds_src,
double high_disp_tolerance,
double low_disp_tolerance,
double min_strength)
{
double [][][] ds = new double [ds_src.length][2][];
for (int i =0; i <ds.length; i++) {
ds[i][0] = ds_src[i][0].clone();
ds[i][1] = ds_src[i][1].clone();
for (int nTile = 0; nTile < ds[i][0].length; nTile++) {
if ( (ds_src[i][1][nTile] < min_strength) ||
(ds_src[i][0][nTile] > high_disp_tolerance) ||
(ds_src[i][0][nTile] < -low_disp_tolerance)) {
ds[i][0][nTile] = Double.NaN;
ds[i][1][nTile] = 0.0;
}
}
}
return ds;
}
public double [][][] poleAddStrongest(
double [][][] ds_src,
double [][][] ds_other)
{
int num_layers = (ds_src == null) ? ds_other.length : ds_src.length;
double [][][] ds = new double [num_layers][2][];
boolean just_clone = (ds_src == null) || (ds_other == null);
if (ds_src == null) {
ds_src = ds_other;
}
for (int i =0; i <ds.length; i++) {
ds[i][0] = ds_src[i][0].clone();
ds[i][1] = ds_src[i][1].clone();
if (!just_clone) {
for (int nTile = 0; nTile < ds[i][0].length; nTile++) {
if (ds_other[i][1][nTile] > ds[i][1][nTile]) {
ds[i][0][nTile] = ds_other[i][0][nTile];
ds[i][1][nTile] = ds_other[i][1][nTile];
}
}
}
}
return ds;
} }
public double [][][] poleAddFittest(
double [][][] ds_src,
double [][][] ds_other)
{
int num_layers = (ds_src == null) ? ds_other.length : ds_src.length;
double [][][] ds = new double [num_layers][2][];
boolean just_clone = (ds_src == null) || (ds_other == null);
if (ds_src == null) {
ds_src = ds_other;
}
for (int i =0; i <ds.length; i++) {
ds[i][0] = ds_src[i][0].clone();
ds[i][1] = ds_src[i][1].clone();
if (!just_clone) {
for (int nTile = 0; nTile < ds[i][0].length; nTile++) {
if (Double.isNaN(ds[i][0][nTile]) || (Math.abs(ds_other[i][0][nTile]) < Math.abs(ds[i][0][nTile]))) {
ds[i][0][nTile] = ds_other[i][0][nTile];
ds[i][1][nTile] = ds_other[i][1][nTile];
}
}
}
}
return ds;
}
// improve DSI acquired for a single camera by use of a pair // improve DSI acquired for a single camera by use of a pair
// Run this after "CLT 3D" // Run this after "CLT 3D"
...@@ -2038,6 +2349,16 @@ if (debugLevel > -100) return true; // temporarily ! ...@@ -2038,6 +2349,16 @@ if (debugLevel > -100) return true; // temporarily !
// //
for (int num_cycle = 0; num_cycle < num_cross_gaps_cycles; num_cycle++) { for (int num_cycle = 0; num_cycle < num_cross_gaps_cycles; num_cycle++) {
BiScan last_scan = biCamDSI.getLastBiScan(BiScan.BISCAN_SINGLECORR); BiScan last_scan = biCamDSI.getLastBiScan(BiScan.BISCAN_SINGLECORR);
if (clt_parameters.rig.lonefg_disp_incr > 0.0) {
int removed_lone = last_scan.trimWeakLoneFG(
clt_parameters.rig.pf_trusted_strength, // final double trusted_strength, // trusted correlation strength
clt_parameters.rig.lonefg_rstrength, // final double min_rstrength, // strength floor - relative to trusted
clt_parameters.rig.lonefg_disp_incr ,//final double max_disp_inc,
clt_parameters.tileX, // final int dbg_x,
clt_parameters.tileY, // final int dbg_y,
debugLevel+2); // final int debugLevel);
System.out.println("trimWeakLoneFG() -> "+removed_lone);
}
int [] trusted_stats = last_scan.calcTrusted( // finds strong trusted and validates week ones if they fit planes 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_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_strength_rfloor, // final double strength_rfloor, // strength floor - relative to trusted
...@@ -2450,7 +2771,7 @@ if (debugLevel > -100) return true; // temporarily ! ...@@ -2450,7 +2771,7 @@ if (debugLevel > -100) return true; // temporarily !
return false; return false;
} }
int scan_index = biCamDSI_persistent.biScans.size()-1; int scan_index = biCamDSI_persistent.biScans.size()-1;
boolean show_smooth = true; boolean show_smooth = false;
boolean keep_unreliable = false; boolean keep_unreliable = false;
boolean keep_weak = false; boolean keep_weak = false;
boolean keep_strong = false; boolean keep_strong = false;
...@@ -5056,6 +5377,79 @@ if (debugLevel > -100) return true; // temporarily ! ...@@ -5056,6 +5377,79 @@ if (debugLevel > -100) return true; // temporarily !
} }
private void showMeasuredPoles(
String title,
int tilesX,
double [][][] measured_poles) {
int num_layers = measured_poles.length;
String [] titles = new String[2 * num_layers];
double [][] dbg_img = new double[2 * num_layers][];
for (int i = 0; i < num_layers; i++) {
titles[i] = "disparity_"+i;
titles[i+num_layers] = "strength_"+i;
dbg_img[i] = measured_poles[i][0];
dbg_img[i+num_layers] = measured_poles[i][1];
}
(new showDoubleFloatArrays()).showArrays(
dbg_img,
tilesX,
dbg_img[0].length/tilesX,
true,
title,
titles);
}
private double [][][] measurePoles(
QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux,
double [][] poles_ds,
EyesisCorrectionParameters.CLTParameters clt_parameters,
boolean notch_mode, // use pole-detection mode for inter-camera correlation
int lt_rad, // low texture mode - inter-correlation is averaged between the neighbors before argmax-ing, using (2*notch_mode+1)^2 square
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int debugLevel)
{
int num_layers = poles_ds.length;
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();
double [][][] measuredDisparityStrength = new double [num_layers][2][]; // num_tiles];
for (int layer = 0; layer < num_layers; layer++) {
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] = poles_ds[layer][nTile];
if (!Double.isNaN(poles_ds[layer][nTile])) {
tile_op[tileY][tileX] = tile_op_all;
}
}
}
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,
notch_mode, // final boolean notch_mode, // use notch filter for inter-camera correlation to detect poles
lt_rad, // final int // low texture mode - inter-correlation is averaged between the neighbors before argmax-ing, using
true, // boolean no_int_x0, // do not offset window to integer maximum - used when averaging low textures to avoid "jumps" for very wide
threadsMax, //final int threadsMax, // maximal number of threads to launch
updateStatus, // final boolean updateStatus,
debugLevel); // final int debugLevel);
measuredDisparityStrength[layer][0] = disparity_bimap[ImageDtt.BI_DISP_CROSS_INDEX];
measuredDisparityStrength[layer][1] = disparity_bimap[ImageDtt.BI_STR_CROSS_INDEX];
}
return measuredDisparityStrength;
}
private double [][] measureRig( private double [][] measureRig(
QuadCLT quadCLT_main, // tiles should be set QuadCLT quadCLT_main, // tiles should be set
QuadCLT quadCLT_aux, QuadCLT quadCLT_aux,
......
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