Commit d129b782 authored by Andrey Filippov's avatar Andrey Filippov

assigning tiles to surfaces

parent 6ae8367c
...@@ -2213,7 +2213,19 @@ public class EyesisCorrectionParameters { ...@@ -2213,7 +2213,19 @@ public class EyesisCorrectionParameters {
public boolean msUseSel = true; // Use planes selection masks (generated when splitting to intersecting pairs public boolean msUseSel = true; // Use planes selection masks (generated when splitting to intersecting pairs
public boolean msDivideByArea = true; // Divide plane strengths by ellipsoid area public boolean msDivideByArea = true; // Divide plane strengths by ellipsoid area
public double msScaleProj = 1.5; // Scale projection of the plane ellipsoid public double msScaleProj = 1.5; // Scale projection of the plane ellipsoid
public double msFractUni = 0.3; // Spread this fraction of the ellipsoid weight among extended (double) supertile public double msFractUni = 0.3; // Spread this fraction of the ellipsoid weight among extended (double) supertile
public double tsMaxDiff = 0.3; // Maximal disparity difference when assigning tiles
public double tsMinDiffOther = 0.35; // Minimal disparity difference to be considered as a competitor surface
public double tsMinStrength = 0.05; // Minimal tile correlation strength to be assigned
public double tsMaxStrength = 10.0; // Maximal tile correlation strength to be assigned
public int tsMoveDirs = 3; // Allowed tile disparity correction: 1 increase, 2 - decrease, 3 - both directions
public boolean tsEnMulti = false; // Allow assignment when several surfaces fit
public double tsSurfStrPow = 0.0; // Raise surface strengths ratio to this power when comparing candidates
public double tsSigma = 2.0; // Radius of influence (in tiles) of the previously assigned tiles
public double tsNSigma = 2.0; // Maximal relative to radius distance to calculate influence
public double tsMinAdvantage = 3.0; // Minimal ratio of the best surface candidate to the next one to make selection
public boolean tsReset = false; // Reset tiles to surfaces assignment
public boolean replaceWeakOutlayers = true; // false; public boolean replaceWeakOutlayers = true; // false;
...@@ -2518,7 +2530,18 @@ public class EyesisCorrectionParameters { ...@@ -2518,7 +2530,18 @@ public class EyesisCorrectionParameters {
properties.setProperty(prefix+"msDivideByArea", this.msDivideByArea+""); properties.setProperty(prefix+"msDivideByArea", this.msDivideByArea+"");
properties.setProperty(prefix+"msScaleProj", this.msScaleProj +""); properties.setProperty(prefix+"msScaleProj", this.msScaleProj +"");
properties.setProperty(prefix+"msFractUni", this.msFractUni +""); properties.setProperty(prefix+"msFractUni", this.msFractUni +"");
properties.setProperty(prefix+"tsMaxDiff", this.tsMaxDiff +"");
properties.setProperty(prefix+"tsMinDiffOther", this.tsMinDiffOther +"");
properties.setProperty(prefix+"tsMinStrength", this.tsMinStrength +"");
properties.setProperty(prefix+"tsMaxStrength", this.tsMaxStrength +"");
properties.setProperty(prefix+"tsMoveDirs", this.tsMoveDirs+"");
properties.setProperty(prefix+"tsEnMulti", this.tsEnMulti+"");
properties.setProperty(prefix+"tsSurfStrPow", this.tsSurfStrPow +"");
properties.setProperty(prefix+"tsSigma", this.tsSigma +"");
properties.setProperty(prefix+"tsNSigma", this.tsNSigma +"");
properties.setProperty(prefix+"tsMinAdvantage", this.tsMinAdvantage +"");
properties.setProperty(prefix+"dbg_migrate", this.dbg_migrate+""); properties.setProperty(prefix+"dbg_migrate", this.dbg_migrate+"");
properties.setProperty(prefix+"show_ortho_combine", this.show_ortho_combine+""); properties.setProperty(prefix+"show_ortho_combine", this.show_ortho_combine+"");
...@@ -2816,6 +2839,18 @@ public class EyesisCorrectionParameters { ...@@ -2816,6 +2839,18 @@ public class EyesisCorrectionParameters {
if (properties.getProperty(prefix+"msScaleProj")!=null) this.msScaleProj=Double.parseDouble(properties.getProperty(prefix+"msScaleProj")); if (properties.getProperty(prefix+"msScaleProj")!=null) this.msScaleProj=Double.parseDouble(properties.getProperty(prefix+"msScaleProj"));
if (properties.getProperty(prefix+"msFractUni")!=null) this.msFractUni=Double.parseDouble(properties.getProperty(prefix+"msFractUni")); if (properties.getProperty(prefix+"msFractUni")!=null) this.msFractUni=Double.parseDouble(properties.getProperty(prefix+"msFractUni"));
if (properties.getProperty(prefix+"tsMaxDiff")!=null) this.tsMaxDiff=Double.parseDouble(properties.getProperty(prefix+"tsMaxDiff"));
if (properties.getProperty(prefix+"tsMinDiffOther")!=null) this.tsMinDiffOther=Double.parseDouble(properties.getProperty(prefix+"tsMinDiffOther"));
if (properties.getProperty(prefix+"tsMinStrength")!=null) this.tsMinStrength=Double.parseDouble(properties.getProperty(prefix+"tsMinStrength"));
if (properties.getProperty(prefix+"tsMaxStrength")!=null) this.tsMaxStrength=Double.parseDouble(properties.getProperty(prefix+"tsMaxStrength"));
if (properties.getProperty(prefix+"tsMoveDirs")!=null) this.tsMoveDirs=Integer.parseInt(properties.getProperty(prefix+"tsMoveDirs"));
if (properties.getProperty(prefix+"tsEnMulti")!=null) this.tsEnMulti=Boolean.parseBoolean(properties.getProperty(prefix+"tsEnMulti"));
if (properties.getProperty(prefix+"tsSurfStrPow")!=null) this.tsSurfStrPow=Double.parseDouble(properties.getProperty(prefix+"tsSurfStrPow"));
if (properties.getProperty(prefix+"tsSigma")!=null) this.tsSigma=Double.parseDouble(properties.getProperty(prefix+"tsSigma"));
if (properties.getProperty(prefix+"tsNSigma")!=null) this.tsNSigma=Double.parseDouble(properties.getProperty(prefix+"tsNSigma"));
if (properties.getProperty(prefix+"tsMinAdvantage")!=null) this.tsMinAdvantage=Double.parseDouble(properties.getProperty(prefix+"tsMinAdvantage"));
if (properties.getProperty(prefix+"dbg_migrate")!=null) this.dbg_migrate=Boolean.parseBoolean(properties.getProperty(prefix+"dbg_migrate")); if (properties.getProperty(prefix+"dbg_migrate")!=null) this.dbg_migrate=Boolean.parseBoolean(properties.getProperty(prefix+"dbg_migrate"));
...@@ -3139,6 +3174,17 @@ public class EyesisCorrectionParameters { ...@@ -3139,6 +3174,17 @@ public class EyesisCorrectionParameters {
gd.addNumericField("Scale projection of the plane ellipsoid", this.msScaleProj, 6); gd.addNumericField("Scale projection of the plane ellipsoid", this.msScaleProj, 6);
gd.addNumericField("Spread this fraction of the ellipsoid weight among extended (double) supertile",this.msFractUni, 6); gd.addNumericField("Spread this fraction of the ellipsoid weight among extended (double) supertile",this.msFractUni, 6);
gd.addNumericField("Maximal disparity difference when assigning tiles", this.tsMaxDiff, 6);
gd.addNumericField("Minimal disparity difference to be considered as a competitor surface", this.tsMinDiffOther, 6);
gd.addNumericField("Minimal tile correlation strength to be assigned", this.tsMinStrength, 6);
gd.addNumericField("Maximal tile correlation strength to be assigned", this.tsMaxStrength, 6);
gd.addNumericField("Allowed tile disparity correction: 1 increase, 2 - decrease, 3 - both directions",this.tsMoveDirs, 0);
gd.addCheckbox ("Allow assignment when several surfaces fit", this.tsEnMulti);
gd.addNumericField("Raise surface strengths ratio to this power when comparing candidates", this.tsSurfStrPow, 6);
gd.addNumericField("Radius of influence (in tiles) of the previously assigned tiles", this.tsSigma, 6);
gd.addNumericField("Maximal relative to radius distance to calculate influence", this.tsNSigma, 6);
gd.addNumericField("Minimal ratio of the best surface candidate to the next one to make selection", this.tsMinAdvantage, 6);
gd.addCheckbox ("Test new mode after migration", this.dbg_migrate); gd.addCheckbox ("Test new mode after migration", this.dbg_migrate);
gd.addMessage ("--- Other debug images ---"); gd.addMessage ("--- Other debug images ---");
...@@ -3442,6 +3488,18 @@ public class EyesisCorrectionParameters { ...@@ -3442,6 +3488,18 @@ public class EyesisCorrectionParameters {
this.msDivideByArea= gd.getNextBoolean(); this.msDivideByArea= gd.getNextBoolean();
this.msScaleProj= gd.getNextNumber(); this.msScaleProj= gd.getNextNumber();
this.msFractUni= gd.getNextNumber(); this.msFractUni= gd.getNextNumber();
this.tsMaxDiff= gd.getNextNumber();
this.tsMinDiffOther= gd.getNextNumber();
this.tsMinStrength= gd.getNextNumber();
this.tsMaxStrength= gd.getNextNumber();
this.tsMoveDirs= (int) gd.getNextNumber();
this.tsEnMulti= gd.getNextBoolean();
this.tsSurfStrPow= gd.getNextNumber();
this.tsSigma= gd.getNextNumber();
this.tsNSigma= gd.getNextNumber();
this.tsMinAdvantage= gd.getNextNumber();
this.tsReset = false; // Reset tiles to surfaces assignment
this.dbg_migrate= gd.getNextBoolean(); this.dbg_migrate= gd.getNextBoolean();
...@@ -3458,8 +3516,40 @@ public class EyesisCorrectionParameters { ...@@ -3458,8 +3516,40 @@ public class EyesisCorrectionParameters {
this.show_flaps_dirs= gd.getNextBoolean(); this.show_flaps_dirs= gd.getNextBoolean();
this.show_first_clusters= gd.getNextBoolean(); this.show_first_clusters= gd.getNextBoolean();
this.show_planes= gd.getNextBoolean(); this.show_planes= gd.getNextBoolean();
return true; return true;
} }
public boolean showTsDialog() {
GenericDialog gd = new GenericDialog("Set CLT parameters");
gd.addNumericField("Maximal disparity difference when assigning tiles", this.tsMaxDiff, 6);
gd.addNumericField("Minimal disparity difference to be considered as a competitor surface", this.tsMinDiffOther, 6);
gd.addNumericField("Minimal tile correlation strength to be assigned", this.tsMinStrength, 6);
gd.addNumericField("Maximal tile correlation strength to be assigned", this.tsMaxStrength, 6);
gd.addNumericField("Allowed tile disparity correction: 1 increase, 2 - decrease, 3 - both directions",this.tsMoveDirs, 0);
gd.addCheckbox ("Allow assignment when several surfaces fit", this.tsEnMulti);
gd.addNumericField("Raise surface strengths ratio to this power when comparing candidates", this.tsSurfStrPow, 6);
gd.addNumericField("Radius of influence (in tiles) of the previously assigned tiles", this.tsSigma, 6);
gd.addNumericField("Maximal relative to radius distance to calculate influence", this.tsNSigma, 6);
gd.addNumericField("Minimal ratio of the best surface candidate to the next one to make selection", this.tsMinAdvantage, 6);
gd.addCheckbox ("Reset tiles to surfaces assignment", false);
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
this.tsMaxDiff= gd.getNextNumber();
this.tsMinDiffOther= gd.getNextNumber();
this.tsMinStrength= gd.getNextNumber();
this.tsMaxStrength= gd.getNextNumber();
this.tsMoveDirs= (int) gd.getNextNumber();
this.tsEnMulti= gd.getNextBoolean();
this.tsSurfStrPow= gd.getNextNumber();
this.tsSigma= gd.getNextNumber();
this.tsNSigma= gd.getNextNumber();
this.tsMinAdvantage= gd.getNextNumber();
this.tsReset= gd.getNextBoolean();
return true;
}
} }
public static class DCTParameters { public static class DCTParameters {
......
...@@ -507,6 +507,7 @@ private Panel panel1, ...@@ -507,6 +507,7 @@ private Panel panel1,
addButton("CLT reset 3D", panelClt1, color_stop); addButton("CLT reset 3D", panelClt1, color_stop);
addButton("CLT 3D", panelClt1, color_conf_process); addButton("CLT 3D", panelClt1, color_conf_process);
addButton("CLT planes", panelClt1, color_conf_process); addButton("CLT planes", panelClt1, color_conf_process);
addButton("CLT ASSIGN", panelClt1, color_process);
addButton("CLT OUT 3D", panelClt1, color_process); addButton("CLT OUT 3D", panelClt1, color_process);
add(panelClt1); add(panelClt1);
...@@ -4782,6 +4783,26 @@ private Panel panel1, ...@@ -4782,6 +4783,26 @@ private Panel panel1,
UPDATE_STATUS, //final boolean updateStatus, UPDATE_STATUS, //final boolean updateStatus,
DEBUG_LEVEL); //final int debugLevel); DEBUG_LEVEL); //final int debugLevel);
return; return;
} else if (label.equals("CLT ASSIGN")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
if (QUAD_CLT == null){
System.out.println("QUAD_CLT is null, nothing to show");
return;
}
if (!CLT_PARAMETERS.showTsDialog()) return;
boolean OK = QUAD_CLT.assignCLTPlanes(
CLT_PARAMETERS, // EyesisCorrectionParameters.DCTParameters dct_parameters,
THREADS_MAX, //final int threadsMax, // maximal number of threads to launch
UPDATE_STATUS, //final boolean updateStatus,
DEBUG_LEVEL); //final int debugLevel);
if (!OK){
System.out.println("Could not assign tiles to surfaces, probably \"CLT planes\" command did not run");
return;
}
return;
} else if (label.equals("CLT OUT 3D")) { } else if (label.equals("CLT OUT 3D")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL; DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
...@@ -4790,7 +4811,6 @@ private Panel panel1, ...@@ -4790,7 +4811,6 @@ private Panel panel1,
System.out.println("QUAD_CLT is null, nothing to show (will add previous steps)"); System.out.println("QUAD_CLT is null, nothing to show (will add previous steps)");
return; return;
} }
String configPath=null; String configPath=null;
if (EYESIS_CORRECTIONS.correctionsParameters.saveSettings) { if (EYESIS_CORRECTIONS.correctionsParameters.saveSettings) {
......
...@@ -4460,7 +4460,6 @@ public class QuadCLT { ...@@ -4460,7 +4460,6 @@ public class QuadCLT {
} }
return rslt; return rslt;
} }
// public ImagePlus [] cltDisparityScan(
public void showCLTPlanes( public void showCLTPlanes(
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
...@@ -4481,9 +4480,33 @@ public class QuadCLT { ...@@ -4481,9 +4480,33 @@ public class QuadCLT {
threadsMax, threadsMax,
updateStatus, updateStatus,
debugLevel); debugLevel);
// CLTPass3d last_scan = tp.clt_3d_passes.get(tp.clt_3d_passes.size() -1); // get last one
} }
public boolean assignCLTPlanes(
EyesisCorrectionParameters.CLTParameters clt_parameters,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int debugLevel)
{
if (tp == null){
System.out.println("showCLTPlanes(): tp is null");
return false;
}
if (tp.clt_3d_passes == null){
System.out.println("showCLTPlanes(): tp.clt_3d_passes is null");
return false;
}
return tp.assignTilesToSurfaces(
clt_parameters,
geometryCorrection,
threadsMax,
updateStatus,
debugLevel);
}
public void out3d( public void out3d(
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
......
...@@ -72,6 +72,9 @@ public class SuperTiles{ ...@@ -72,6 +72,9 @@ public class SuperTiles{
int [][] shell_map = null; // per supertile, per disparity plane - shell index + 1 (0 - none) int [][] shell_map = null; // per supertile, per disparity plane - shell index + 1 (0 - none)
double [][] surfaces; // per shell, per tile (linescan order) disparity value or NaN in missing supertiles double [][] surfaces; // per shell, per tile (linescan order) disparity value or NaN in missing supertiles
TileSurface tileSurface = null;
/** /**
* currently lowest plane for each includes all tiles, so do not use it. May change in the future * currently lowest plane for each includes all tiles, so do not use it. May change in the future
...@@ -185,6 +188,15 @@ public class SuperTiles{ ...@@ -185,6 +188,15 @@ public class SuperTiles{
} }
} }
public void setTileSurface( TileSurface tileSurface)
{
this.tileSurface = tileSurface;
}
public TileSurface getTileSurface()
{
return tileSurface;
}
public void initFuseCoeff( public void initFuseCoeff(
double scale_diag, double scale_diag,
boolean debug) boolean debug)
......
...@@ -2942,6 +2942,53 @@ public class TileProcessor { ...@@ -2942,6 +2942,53 @@ public class TileProcessor {
} }
public boolean assignTilesToSurfaces(
EyesisCorrectionParameters.CLTParameters clt_parameters,
GeometryCorrection geometryCorrection,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int debugLevel)
{
CLTPass3d scan_prev = clt_3d_passes.get(clt_3d_passes.size() -1); // get last one
// boolean show_st = clt_parameters.stShow || (debugLevel > 1);
SuperTiles st = scan_prev.getSuperTiles();
TileSurface tileSurface = st.getTileSurface();
if (tileSurface == null){
return false;
}
double [][][] dispStrength = st.getDisparityStrengths(
clt_parameters.stMeasSel); // int stMeasSel) // = 1; // Select measurements for supertiles : +1 - combo, +2 - quad +4 - hor +8 - vert)
boolean [][] tileSel = st.getMeasurementSelections(
clt_parameters.stMeasSel); // int stMeasSel) // = 1; // Select measurements for supertiles : +1 - combo, +2 - quad +4 - hor +8 - vert)
tileSurface.InitTilesAssignment(
clt_parameters.tsReset,
dispStrength, // final double [][][] dispStrength,
tileSel, // final boolean [][] tileSel,
debugLevel); // final int debugLevel,
int [] stats= tileSurface.assignTilesToSurfaces(
clt_parameters.tsMaxDiff, //final double maxDiff,
clt_parameters.tsMinDiffOther, //final double minDiffOther, // should be >= maxDiff
clt_parameters.tsMinStrength, //final double minStrength,
clt_parameters.tsMaxStrength, //final double maxStrength,
clt_parameters.tsMoveDirs, //final int moveDirs, // 1 increase disparity, 2 - decrease disparity, 3 - both directions
clt_parameters.tsEnMulti, //final boolean enMulti,
clt_parameters.tsSurfStrPow, //final double surfStrPow, // surface strength power
clt_parameters.tsSigma, //final double sigma,
clt_parameters.tsNSigma, //final double nSigma,
clt_parameters.tsMinAdvantage, //final double minAdvantage,
clt_parameters.plDispNorm, // final double dispNorm, // disparity normalize (proportionally scale down disparity difference if above
dispStrength, // final double [][][] dispStrength,
0, // -1, // debugLevel, // final int debugLevel)
clt_parameters.tileX,
clt_parameters.tileY);
tileSurface.printStats(stats);
return true;
}
//====================== //======================
public void showPlanes( public void showPlanes(
EyesisCorrectionParameters.CLTParameters clt_parameters, EyesisCorrectionParameters.CLTParameters clt_parameters,
...@@ -3174,9 +3221,11 @@ public class TileProcessor { ...@@ -3174,9 +3221,11 @@ public class TileProcessor {
st.tileProcessor.getTilesY(), // int tilesY, st.tileProcessor.getTilesY(), // int tilesY,
geometryCorrection, // GeometryCorrection geometryCorrection, geometryCorrection, // GeometryCorrection geometryCorrection,
st.tileProcessor.threadsMax); // int threadsMax); st.tileProcessor.threadsMax); // int threadsMax);
st.setTileSurface(tileSurface);
TileSurface.TileData [][] tileData = tileSurface.createTileShells ( // TileSurface.TileData [][] tileData =
tileSurface.createTileShells (
clt_parameters.msUseSel, // final boolean use_sel, clt_parameters.msUseSel, // final boolean use_sel,
clt_parameters.msDivideByArea, // final boolean divide_by_area, clt_parameters.msDivideByArea, // final boolean divide_by_area,
clt_parameters.msScaleProj, // final double scale_projection, clt_parameters.msScaleProj, // final double scale_projection,
...@@ -3185,19 +3234,17 @@ public class TileProcessor { ...@@ -3185,19 +3234,17 @@ public class TileProcessor {
0, // -1, // debugLevel, // final int debugLevel) 0, // -1, // debugLevel, // final int debugLevel)
clt_parameters.tileX, clt_parameters.tileX,
clt_parameters.tileY); clt_parameters.tileY);
int [][] tiles_layers = tileSurface.sortTilesToSurfaces( tileSurface.InitTilesAssignment(
true,
dispStrength, // final double [][][] dispStrength, dispStrength, // final double [][][] dispStrength,
tileSel, // final boolean [][] tileSel, tileSel, // final boolean [][] tileSel,
tileData, // final TileData [][] tileData_src, debugLevel); // final int debugLevel,
// parameters if (debugLevel > -10){
clt_parameters, // final EyesisCorrectionParameters.CLTParameters clt_parameters, return; // just cut off the rest
debugLevel, // final int debugLevel, }
clt_parameters.tileX,
clt_parameters.tileY);
TilePlanes.PlaneData[][][] split_planes = // use original (measured planes. See if smoothed are needed here) TilePlanes.PlaneData[][][] split_planes = // use original (measured planes. See if smoothed are needed here)
...@@ -3571,6 +3618,10 @@ public class TileProcessor { ...@@ -3571,6 +3618,10 @@ public class TileProcessor {
} }
} }
public void secondPassSetup( // prepare tile tasks for the second pass based on the previous one(s) public void secondPassSetup( // prepare tile tasks for the second pass based on the previous one(s)
// final double [][][] image_data, // first index - number of image in a quad // final double [][][] image_data, // first index - number of image in a quad
......
import java.awt.Point;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
...@@ -40,6 +41,8 @@ public class TileSurface { ...@@ -40,6 +41,8 @@ public class TileSurface {
private int [] ss_dirs8; private int [] ss_dirs8;
private double [] window; private double [] window;
private int threadsMax = 100; private int threadsMax = 100;
private int [][] tileLayers = null;
private TileData [][] tileData = null;
static int STAT_UNASSIGNED = 0; // index of number of unassigned tiles static int STAT_UNASSIGNED = 0; // index of number of unassigned tiles
static int STAT_ASSIGNED = 1; // index of number of assigned tiles static int STAT_ASSIGNED = 1; // index of number of assigned tiles
...@@ -1649,7 +1652,7 @@ public class TileSurface { ...@@ -1649,7 +1652,7 @@ public class TileSurface {
dbg_Y); // final int dbg_Y); dbg_Y); // final int dbg_Y);
showSurfaceDS (tileData, "tileData"); showSurfaceDS (tileData, "tileData");
this.tileData = tileData;
return tileData; return tileData;
} }
...@@ -1712,7 +1715,8 @@ public class TileSurface { ...@@ -1712,7 +1715,8 @@ public class TileSurface {
} }
/** /**
* Convert from image tile index to surface tile index (surface tiles are all full superTileSize * Convert from image tile index to the surface tile index (surface tiles are all
* full superTileSize),
* TODO: update/remove if surface grid will be trimmed to fit image * TODO: update/remove if surface grid will be trimmed to fit image
* Currently there are 324 tiles horizontally in the image and 328 in the surfaces * Currently there are 324 tiles horizontally in the image and 328 in the surfaces
* @param nTile image tile index in scan order * @param nTile image tile index in scan order
...@@ -1722,9 +1726,31 @@ public class TileSurface { ...@@ -1722,9 +1726,31 @@ public class TileSurface {
int nTile) int nTile)
{ {
// calculate index in tileData (has different dimensions - TODO: trim? // calculate index in tileData (has different dimensions - TODO: trim?
return stilesX * superTileSize * (nTile / imageTilesX) + (nTile % imageTilesX); int surfaceTilesX = stilesX * superTileSize;
return surfaceTilesX * (nTile / imageTilesX) + (nTile % imageTilesX);
} }
/**
* Convert from surface tile index (surface tiles are all full superTileSize) to
* the image tile index
* TODO: update/remove if surface grid will be trimmed to fit image
* Currently there are 324 tiles horizontally in the image and 328 in the surfaces
* @param nSurfTile surface tile index in scan order
* @return image tile index in scan order or -1 if outside of the image tiles
*/
public int getImageTileIndex(
int nSurfTile)
{
// calculate index in tileData (has different dimensions - TODO: trim?
int surfaceTilesX = stilesX * superTileSize;
int tx = nSurfTile % surfaceTilesX;
int ty = nSurfTile / surfaceTilesX;
if ((tx > imageTilesX) || (ty > imageTilesY)){
return -1; // out of image
}
return imageTilesX * ty + tx;
}
/** /**
* Assign tiles to a certain disparity surface if there is only one surface candidate * Assign tiles to a certain disparity surface if there is only one surface candidate
...@@ -1743,15 +1769,15 @@ public class TileSurface { ...@@ -1743,15 +1769,15 @@ public class TileSurface {
* @param dbg_Y debug tile Y coordinate * @param dbg_Y debug tile Y coordinate
* @return * @return
*/ */
public int [] assignSingleCandidate( public int [] assignTilesToSingleCandidate(
final double maxDiff, final double maxDiff,
final double minDiffOther, final double minDiffOther,
final double minStrength, final double minStrength,
final double maxStrength, final double maxStrength,
final int moveDirs, // 1 increase disparity, 2 - decrease disparity, 3 - both directions final int moveDirs, // 1 increase disparity, 2 - decrease disparity, 3 - both directions
final double dispNorm, // disparity normalize (proportionally scale down disparity difference if above final double dispNorm, // disparity normalize (proportionally scale down disparity difference if above
final int [][] tileLayers, // final int [][] tileLayers,
final TileData [][] tileData, // final TileData [][] tileData,
final double [][][] dispStrength, final double [][][] dispStrength,
final int debugLevel, final int debugLevel,
final int dbg_X, final int dbg_X,
...@@ -1831,7 +1857,19 @@ public class TileSurface { ...@@ -1831,7 +1857,19 @@ public class TileSurface {
return stats_new; return stats_new;
} }
public void printStats(int []stats)
{
System.out.println("printStats(x):"+
" NEW_ASSIGNED = " + stats[NEW_ASSIGNED] +
" NO_SURF=" + stats[NO_SURF] +
" TOO_WEAK=" + stats[TOO_WEAK] +
" TOO_STRONG=" + stats[TOO_STRONG] +
" TOO_FAR=" + stats[TOO_FAR] +
" NOT_UNIQUE=" + stats[NOT_UNIQUE]);
}
/** /**
* Assign tiles to a certain disparity surface if there is only one surface candidate * Assign tiles to a certain disparity surface if there is only one surface candidate
* @param maxDiff maximal (normalized) disparity difference * @param maxDiff maximal (normalized) disparity difference
...@@ -1855,20 +1893,20 @@ public class TileSurface { ...@@ -1855,20 +1893,20 @@ public class TileSurface {
* @return * @return
*/ */
public int [] assignSingleCandidate( public int [] assignTilesToSurfaces(
final double maxDiff, final double maxDiff,
final double minDiffOther, // should be >= maxDiff final double minDiffOther, // should be >= maxDiff
final double minStrength, final double minStrength,
final double maxStrength, final double maxStrength,
final int moveDirs, // 1 increase disparity, 2 - decrease disparity, 3 - both directions final int moveDirs, // 1 increase disparity, 2 - decrease disparity, 3 - both directions
final boolean enMulti, final boolean enMulti,
final double surfStrPow, // surface string power final double surfStrPow, // surface strength power
final double sigma, final double sigma,
final double nSigma, final double nSigma,
final double minAdvantage, final double minAdvantage,
final double dispNorm, // disparity normalize (proportionally scale down disparity difference if above final double dispNorm, // disparity normalize (proportionally scale down disparity difference if above
final int [][] tileLayers, // final int [][] tileLayers, // use this.
final TileData [][] tileData, // final TileData [][] tileData,// use this.
final double [][][] dispStrength, final double [][][] dispStrength,
final int debugLevel, final int debugLevel,
final int dbg_X, final int dbg_X,
...@@ -1889,6 +1927,25 @@ public class TileSurface { ...@@ -1889,6 +1927,25 @@ public class TileSurface {
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
final boolean en_lower = (moveDirs & 1) != 0; final boolean en_lower = (moveDirs & 1) != 0;
final boolean en_higher = (moveDirs & 2) != 0; final boolean en_higher = (moveDirs & 2) != 0;
final double radius = sigma * nSigma;
final double rsigma2 = 1.0 / ( 2.0 * sigma * sigma);
final int iradius = (int) Math.round(radius + 0.001);
final int field_size = 2 * iradius + 1;
final int center_index = iradius * (field_size + 1);
final double cost_start = 1.0;
final double cost_ortho = 1.0;
final double cost_diag = Math.sqrt(2.0);
final int surfTilesX = stilesX * superTileSize;
final int [] ldirs8 = {
-field_size,
-field_size + 1,
1,
field_size + 1,
field_size,
field_size - 1,
-1,
-field_size - 1};
for (int ml = 0; ml < tileLayers.length; ml++) if (tileLayers[ml] != null){ for (int ml = 0; ml < tileLayers.length; ml++) if (tileLayers[ml] != null){
final int fml = ml; final int fml = ml;
ai_numThread.set(0); ai_numThread.set(0);
...@@ -1938,6 +1995,9 @@ public class TileSurface { ...@@ -1938,6 +1995,9 @@ public class TileSurface {
stats_all[numThread][NOT_UNIQUE] ++; stats_all[numThread][NOT_UNIQUE] ++;
} else { // multi, enabled } else { // multi, enabled
int [] candidates = new int [num_fit_other]; int [] candidates = new int [num_fit_other];
// reversed mapping - from layer to candidate (-1 = not a candidate)
// int [] rcandidates = new int [tileData[nSurfTile].length];
// for (int i = 0; i < rcandidates.length; i++) rcandidates[i] = -1;
boolean [] close_enough = new boolean [num_fit_other]; boolean [] close_enough = new boolean [num_fit_other];
num_fit_other = 0; num_fit_other = 0;
for (int ns = 0; ns < tileData[nSurfTile].length; ns++){ for (int ns = 0; ns < tileData[nSurfTile].length; ns++){
...@@ -1948,22 +2008,168 @@ public class TileSurface { ...@@ -1948,22 +2008,168 @@ public class TileSurface {
if (((surf_disp_diff >= 0) && en_higher) || ((surf_disp_diff <= 0) && en_lower)){ if (((surf_disp_diff >= 0) && en_higher) || ((surf_disp_diff <= 0) && en_lower)){
if (Math.abs(surf_disp_diff) <= minDiffOther){ if (Math.abs(surf_disp_diff) <= minDiffOther){
close_enough[num_fit_other] = (Math.abs(surf_disp_diff) <= maxDiff); close_enough[num_fit_other] = (Math.abs(surf_disp_diff) <= maxDiff);
// rcandidates[ns] = num_fit_other;
candidates[num_fit_other++] = ns; candidates[num_fit_other++] = ns;
} }
} }
} }
double [][] advantages = new double [num_fit_other][num_fit_other]; double [][][] distances = new double [num_fit_other][field_size * field_size ][];
// for each local index get surface tile index
int [] surfIndices = new int [field_size * field_size];
int [] imageIndices = new int [field_size * field_size];
int stx0 = (nTile % surfTilesX) - iradius;
int sty0 = (nTile / surfTilesX) - iradius;
for (int iy = 0; iy < field_size; iy++){
for (int ix = 0; ix < field_size; ix++){
int indx = iy * field_size + ix;
surfIndices[indx] = (sty0 + iy)* surfTilesX + (stx0 + ix);
imageIndices[indx] = getImageTileIndex(surfIndices[indx]);
}
}
// calculate distances from the center point for each surface with wave
// algorithm, first regardless of who is closer.
// later, when comparing pairs only use the same side
for (int isurf = 0; isurf < num_fit_other; isurf++){
ArrayList<Point> lwave = new ArrayList<Point>();
Point p0 = new Point(center_index, candidates[isurf]);
distances[isurf][p0.x] = new double [tileData[nSurfTile].length];
distances[isurf][p0.x][p0.y] = cost_start;
lwave.add(p0);
// run wave build radius (plus 1.0) along each surface connections,
// until next radius >= radius
while (!lwave.isEmpty()){
p0 = lwave.remove(0);
int [] neibs = tileData[surfIndices[p0.x]][p0.y].getNeighbors();
// try ortho directions first
double new_dist = distances[isurf][p0.x][p0.y] + cost_ortho;
if (new_dist <= (radius + cost_start)) {
for (int dir = 0; dir < 8; dir +=2) if ( neibs[dir] >= 0){
Point pn = new Point (p0.x + ldirs8[dir], neibs[dir]);
if (distances[isurf][pn.x] == null){
distances[isurf][pn.x] = new double [tileData[surfIndices[pn.x]].length];
}
if ((distances[isurf][pn.x][pn.y] == 0) || (distances[isurf][pn.x][pn.y] > new_dist)){
distances[isurf][pn.x][pn.y] = new_dist;
lwave.add(pn);
}
}
}
// try diagonal directions second
new_dist = distances[isurf][p0.x][p0.y] + cost_diag;
if (new_dist <= (radius + cost_start)) {
for (int dir = 1; dir < 8; dir +=2) if ( neibs[dir] >= 0){
Point pn = new Point (p0.x + ldirs8[dir], neibs[dir]);
if (distances[isurf][pn.x] == null){
distances[isurf][pn.x] = new double [tileData[surfIndices[pn.x]].length];
}
if ((distances[isurf][pn.x][pn.y] == 0) || (distances[isurf][pn.x][pn.y] > new_dist)){
distances[isurf][pn.x][pn.y] = new_dist;
lwave.add(pn);
}
}
}
}
}
// pulls belong to pairs, not individual surfaces (difference when they cross)
double [][] surface_pulls = new double [num_fit_other][num_fit_other];
// now calculate advantage of each one surface (close_enough) to each other (as a ratio) // now calculate advantage of each one surface (close_enough) to each other (as a ratio)
// and then see if it is above minAdvantage // and then see if it is above minAdvantage
for (int ns1 = 0; ns1 < num_fit_other; ns1++){ for (int other_ml = 0; other_ml < tileLayers.length; other_ml++) if (tileLayers[other_ml] != null){
for (int ns2 = ns1 + 1; ns2 < num_fit_other; ns2++){ for (int lindx = 0; lindx < imageIndices.length; lindx ++){
if (close_enough[ns1] || close_enough[ns2]){ if (imageIndices[lindx] >= 0) {
int nsurf = tileLayers_src[other_ml][imageIndices[lindx]] - 1; // assigned surface number (>=0)
if ( nsurf >= 0){
double strength = dispStrength[other_ml][1][imageIndices[lindx]];
// see if this tile belongs to any of the considered surfaces
int num_found = 0;
boolean [] on_surface = new boolean [num_fit_other];
for (int i = 0; i < num_fit_other; i++) {
if ((distances[i][lindx] != null) && (distances[i][lindx][nsurf] > 0.0)){
num_found++;
on_surface[i] = true;
}
}
if (num_found > 0) { // tile lies on at least one of the considered surfaces
for (int is1 = 0; is1 < num_fit_other; is1++) if (on_surface[is1]) {
// is2 can be any other candidate, just check it is on the same side
// of is1 as in the center (new tile)
for (int is2 = 0; is2 < num_fit_other; is2++) if (is2 != is1) {
boolean good_pair = true;
if (distances[is2][lindx] != null) { // otherwise OK
for (int i = 0; i < distances[is2][lindx].length; i++){
if (distances[is2][lindx][i] >= 0){
if ( ((is2 > is1) && (i < nsurf)) ||
((is2 > is1) && (i < nsurf))) {
good_pair = false; // surfaces cross between
break;
}
}
}
}
if (good_pair){
double r = distances[is1][lindx][nsurf] - cost_start;
// pull to is1 when in pair with is2
surface_pulls[is1][is2] = Math.exp(- r * r * rsigma2) * strength ;
}
}
}
}
}
} }
} }
} }
double [][] advantages = new double [num_fit_other][num_fit_other];
for (int is1 = 0; is1 < num_fit_other; is1++){
for (int is2 = is1 + 1; is2 < num_fit_other; is2++){
advantages[is1][is2] = surface_pulls[is1][is2]/surface_pulls[is2][is1];
advantages[is2][is1] = 1.0/advantages[is1][is2];
if (surfStrPow != 0.0){ // consider surface strength also
double str1 = tileData[nSurfTile][candidates[is1]].getStrength();
double str2 = tileData[nSurfTile][candidates[is1]].getStrength();
if ((str1 > 0.0) && (str2 > 0.0)){
advantages[is1][is2] *= Math.pow(str1/str2, surfStrPow);
advantages[is2][is1] = 1.0/advantages[is1][is2];
} else if (str1 > 0.0) {
advantages[is1][is2] = 2.0 * minAdvantage; // sure will win
advantages[is2][is1] = (minAdvantage > 0.0) ? (1.0/advantages[is1][is2]) : 0.0;
//minAdvantage
} else if (str2 > 0.0) {
advantages[is2][is1] = 2.0 * minAdvantage; // sure will win
advantages[is1][is2] = (minAdvantage > 0.0) ? (1.0/advantages[is2][is1]) : 0.0;
} else { // both zero - do nothing about surface strengths
}
}
}
}
// Now see if we have a winner that is (2 could not satisfy, look for the first:
// a) close enough, and
// b) sufficient advantage over all other candidates
fit = -1;
for (int is1 = 0; is1 < num_fit_other; is1++){
if (close_enough[is1]){ //
boolean is_a_winner = true;
for (int is2 = is1 + 1; is2 < num_fit_other; is2++){
if (advantages[is1][is2] < minAdvantage){
is_a_winner = false;
break;
}
}
if (is_a_winner){
fit = is1;
break;
}
}
}
if (fit >= 0) {
tileLayers[fml][nTile] = fit + 1;
stats_all[numThread][NEW_ASSIGNED] ++;
} else {
stats_all[numThread][NOT_UNIQUE] ++;
}
} }
} }
} }
...@@ -1981,7 +2187,36 @@ public class TileSurface { ...@@ -1981,7 +2187,36 @@ public class TileSurface {
} }
return stats_new; return stats_new;
} }
public int [] InitTilesAssignment(
final boolean force,
final double [][][] dispStrength,
final boolean [][] tileSel,
final int debugLevel)
{
if (force || (this.tileLayers == null)) {
int [][] tileLayers = new int [tileSel.length][];
for (int ml = 0; ml < tileSel.length; ml++){
if (tileSel[ml] != null){
tileLayers[ml] = new int [tileSel[ml].length];
for (int i = 0; i < tileSel[ml].length; i++){
tileLayers[ml][i] = tileSel[ml][i] ? 0: -1; // 0 - unassigned, -1 - prohibited
}
}
}
this.tileLayers = tileLayers;
}
int []stats = getTilesAssignStats(tileLayers);
if (debugLevel >= -1) {
System.out.println("sortTilesToSurfaces(): using "+stats[STAT_NUM_ML] +" measurement layers"+
", number of assigned tiles: "+stats[STAT_ASSIGNED]+
", number of unassigned tiles: "+stats[STAT_UNASSIGNED]+
", number of prohibited tiles: "+stats[STAT_PROHIBITED]+
", number of impossible tiles: "+stats[STAT_IMPOSSIBLE]);
}
return stats;
}
......
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