Commit f60cc3af authored by Andrey Filippov's avatar Andrey Filippov

merging planes

parent cee97f1b
...@@ -2150,9 +2150,13 @@ public class EyesisCorrectionParameters { ...@@ -2150,9 +2150,13 @@ public class EyesisCorrectionParameters {
public double plMinStrength = 0.1; // Minimal total strength of a plane public double plMinStrength = 0.1; // Minimal total strength of a plane
public double plMaxEigen = 0.3; // Maximal eigenvalue of a plane public double plMaxEigen = 0.3; // Maximal eigenvalue of a plane
public boolean plDbgMerge = true; // Combine 'other' plane with current public boolean plDbgMerge = true; // Combine 'other' plane with current
public double plWorstWorsening = 2.0; // Worst case worsening after merge public double plWorstWorsening = 1.0; // Worst case worsening after merge
public boolean plMutualOnly = true; // keep only mutual links, remove weakest if conflict public boolean plMutualOnly = true; // keep only mutual links, remove weakest if conflict
public double plPull = .1; // Relative weight of original (measured) plane when combing with neighbors
public int plIterations = 10; // Maximal number of smoothing iterations for each step
public int plPrecision = 6; // Maximal step difference (1/power of 10)
// other debug images // other debug images
public boolean show_ortho_combine = false; // Show 'ortho_combine' public boolean show_ortho_combine = false; // Show 'ortho_combine'
...@@ -2397,6 +2401,10 @@ public class EyesisCorrectionParameters { ...@@ -2397,6 +2401,10 @@ public class EyesisCorrectionParameters {
properties.setProperty(prefix+"plWorstWorsening", this.plWorstWorsening +""); properties.setProperty(prefix+"plWorstWorsening", this.plWorstWorsening +"");
properties.setProperty(prefix+"plMutualOnly", this.plMutualOnly+""); properties.setProperty(prefix+"plMutualOnly", this.plMutualOnly+"");
properties.setProperty(prefix+"plPull", this.plPull +"");
properties.setProperty(prefix+"plIterations", this.plIterations+"");
properties.setProperty(prefix+"plPrecision", this.plPrecision+"");
properties.setProperty(prefix+"show_ortho_combine", this.show_ortho_combine+""); properties.setProperty(prefix+"show_ortho_combine", this.show_ortho_combine+"");
properties.setProperty(prefix+"show_refine_supertiles", this.show_refine_supertiles+""); properties.setProperty(prefix+"show_refine_supertiles", this.show_refine_supertiles+"");
properties.setProperty(prefix+"show_bgnd_nonbgnd", this.show_bgnd_nonbgnd+""); properties.setProperty(prefix+"show_bgnd_nonbgnd", this.show_bgnd_nonbgnd+"");
...@@ -2631,6 +2639,10 @@ public class EyesisCorrectionParameters { ...@@ -2631,6 +2639,10 @@ public class EyesisCorrectionParameters {
if (properties.getProperty(prefix+"plWorstWorsening")!=null) this.plWorstWorsening=Double.parseDouble(properties.getProperty(prefix+"plWorstWorsening")); if (properties.getProperty(prefix+"plWorstWorsening")!=null) this.plWorstWorsening=Double.parseDouble(properties.getProperty(prefix+"plWorstWorsening"));
if (properties.getProperty(prefix+"plMutualOnly")!=null) this.plMutualOnly=Boolean.parseBoolean(properties.getProperty(prefix+"plMutualOnly")); if (properties.getProperty(prefix+"plMutualOnly")!=null) this.plMutualOnly=Boolean.parseBoolean(properties.getProperty(prefix+"plMutualOnly"));
if (properties.getProperty(prefix+"plPull")!=null) this.plPull=Double.parseDouble(properties.getProperty(prefix+"plPull"));
if (properties.getProperty(prefix+"plIterations")!=null) this.plIterations=Integer.parseInt(properties.getProperty(prefix+"plIterations"));
if (properties.getProperty(prefix+"plPrecision")!=null) this.plPrecision=Integer.parseInt(properties.getProperty(prefix+"plPrecision"));
if (properties.getProperty(prefix+"show_ortho_combine")!=null) this.show_ortho_combine=Boolean.parseBoolean(properties.getProperty(prefix+"show_ortho_combine")); if (properties.getProperty(prefix+"show_ortho_combine")!=null) this.show_ortho_combine=Boolean.parseBoolean(properties.getProperty(prefix+"show_ortho_combine"));
if (properties.getProperty(prefix+"show_refine_supertiles")!=null) this.show_refine_supertiles=Boolean.parseBoolean(properties.getProperty(prefix+"show_refine_supertiles")); if (properties.getProperty(prefix+"show_refine_supertiles")!=null) this.show_refine_supertiles=Boolean.parseBoolean(properties.getProperty(prefix+"show_refine_supertiles"));
if (properties.getProperty(prefix+"show_bgnd_nonbgnd")!=null) this.show_bgnd_nonbgnd=Boolean.parseBoolean(properties.getProperty(prefix+"show_bgnd_nonbgnd")); if (properties.getProperty(prefix+"show_bgnd_nonbgnd")!=null) this.show_bgnd_nonbgnd=Boolean.parseBoolean(properties.getProperty(prefix+"show_bgnd_nonbgnd"));
...@@ -2887,6 +2899,10 @@ public class EyesisCorrectionParameters { ...@@ -2887,6 +2899,10 @@ public class EyesisCorrectionParameters {
gd.addNumericField("Worst case worsening after merge", this.plWorstWorsening, 6); gd.addNumericField("Worst case worsening after merge", this.plWorstWorsening, 6);
gd.addCheckbox ("Keep only mutual links, remove weakest if conflict", this.plMutualOnly); gd.addCheckbox ("Keep only mutual links, remove weakest if conflict", this.plMutualOnly);
gd.addNumericField("Relative weight of original (measured) plane when combing with neighbors", this.plPull, 6);
gd.addNumericField("Maximal number of smoothing iterations for each step", this.plIterations, 0);
gd.addNumericField("Maximal step difference (1/power of 10) ", this.plPrecision, 0);
gd.addMessage ("--- Other debug images ---"); gd.addMessage ("--- Other debug images ---");
gd.addCheckbox ("Show 'ortho_combine'", this.show_ortho_combine); gd.addCheckbox ("Show 'ortho_combine'", this.show_ortho_combine);
gd.addCheckbox ("Show 'refine_disparity_supertiles'", this.show_refine_supertiles); gd.addCheckbox ("Show 'refine_disparity_supertiles'", this.show_refine_supertiles);
...@@ -3130,8 +3146,12 @@ public class EyesisCorrectionParameters { ...@@ -3130,8 +3146,12 @@ public class EyesisCorrectionParameters {
this.plWorstWorsening= gd.getNextNumber(); this.plWorstWorsening= gd.getNextNumber();
this.plMutualOnly= gd.getNextBoolean(); this.plMutualOnly= gd.getNextBoolean();
this.plPull= gd.getNextNumber();
this.plIterations= (int) gd.getNextNumber();
this.plPrecision= (int) gd.getNextNumber();
this.show_ortho_combine= gd.getNextBoolean(); this.show_ortho_combine= gd.getNextBoolean();
this.show_refine_supertiles= gd.getNextBoolean(); this.show_refine_supertiles=gd.getNextBoolean();
this.show_bgnd_nonbgnd= gd.getNextBoolean(); // first on second pass this.show_bgnd_nonbgnd= gd.getNextBoolean(); // first on second pass
this.show_filter_scan= gd.getNextBoolean(); // first on refine this.show_filter_scan= gd.getNextBoolean(); // first on refine
this.show_combined= gd.getNextBoolean(); this.show_combined= gd.getNextBoolean();
......
...@@ -5126,7 +5126,7 @@ public class QuadCLT { ...@@ -5126,7 +5126,7 @@ public class QuadCLT {
System.out.println("Generating cluster images (limit is set to "+clt_parameters.max_clusters+") largest, scan #"+scanIndex); System.out.println("Generating cluster images (limit is set to "+clt_parameters.max_clusters+") largest, scan #"+scanIndex);
} }
// ImagePlus cluster_image = getPassImage( // get image form a single pass // ImagePlus cluster_image = getPassImage( // get image form a single pass
String texturePath = getPassImage( // get image form a single pass String texturePath = getPassImage( // get image from a single pass
clt_parameters, clt_parameters,
colorProcParameters, colorProcParameters,
rgbParameters, rgbParameters,
......
...@@ -52,6 +52,8 @@ public class SuperTiles{ ...@@ -52,6 +52,8 @@ public class SuperTiles{
CLTPass3d cltPass3d; CLTPass3d cltPass3d;
// ArrayList<TilePlanes.PlaneData>[] planes = null; // ArrayList<TilePlanes.PlaneData>[] planes = null;
TilePlanes.PlaneData [][] planes = null; TilePlanes.PlaneData [][] planes = null;
//
TilePlanes.PlaneData [][] planes_mod = null;
public SuperTiles( public SuperTiles(
CLTPass3d cltPass3d, CLTPass3d cltPass3d,
double step_near, double step_near,
...@@ -129,6 +131,11 @@ public class SuperTiles{ ...@@ -129,6 +131,11 @@ public class SuperTiles{
{ {
return planes; return planes;
} }
public TilePlanes.PlaneData [][] getPlanesMod()
{
return planes_mod;
}
private double [][] getLapWeights(){ private double [][] getLapWeights(){
final int superTileSize = tileProcessor.superTileSize; final int superTileSize = tileProcessor.superTileSize;
final double [][] lapWeight = new double [2 * superTileSize][2 * superTileSize]; final double [][] lapWeight = new double [2 * superTileSize][2 * superTileSize];
...@@ -1433,6 +1440,18 @@ public class SuperTiles{ ...@@ -1433,6 +1440,18 @@ public class SuperTiles{
return neib_planes; return neib_planes;
} }
/**
* Measure how merging of two plains degrades individual flatness (smaller - better). For comparing divide by (w1+w2) to make strong
* planes score better
* @param L1 smallest eigenvalue of the first plane
* @param L2 smallest eigenvalue of the second plane
* @param L smallest eigenvalue of the merged plane
* @param w1 weight of the first plane
* @param w2 weight of the second plane
* @return degrading by merging measure. 0 if both are co-planar, is supposed to be positive. very "bad" planes do produce negative results -
* not yet clear why (related to non-linear coordinate transformation?)
*/
public double mergeRQuality( public double mergeRQuality(
double L1, double L1,
double L2, double L2,
...@@ -1443,7 +1462,8 @@ public class SuperTiles{ ...@@ -1443,7 +1462,8 @@ public class SuperTiles{
// double Lav = Math.sqrt((L1*L1*w1 + L2*L2*w2)/(w1+w2)); // double Lav = Math.sqrt((L1*L1*w1 + L2*L2*w2)/(w1+w2));
double Lav = (L1*w1 + L2*w2)/(w1+w2); double Lav = (L1*w1 + L2*w2)/(w1+w2);
/// double wors = (L - Lav)*(w1+w2)*(w1+w2) /(Lav*w1*w2); /// double wors = (L - Lav)*(w1+w2)*(w1+w2) /(Lav*w1*w2);
double rquality = (L - Lav)*(w1+w2) /(Lav*w1*w2); // ==wors/(w1+w2) to amplify stronger planes /// double rquality = (L - Lav)*(w1+w2) /(Lav*w1*w2); // ==wors/(w1+w2) to amplify stronger planes
double rquality = (L - Lav)*(w1+w2)*(w1+w2) /(Lav*w1*w2);
return rquality; return rquality;
} }
...@@ -1480,7 +1500,7 @@ public class SuperTiles{ ...@@ -1480,7 +1500,7 @@ public class SuperTiles{
for (int np0 = 0; np0 < planes[nsTile0].length; np0++){ // nu for (int np0 = 0; np0 < planes[nsTile0].length; np0++){ // nu
// planes[nsTile0][np0].initNeibBest(); // // planes[nsTile0][np0].initNeibBest(); //
TilePlanes.PlaneData this_plane = planes[nsTile0][np0]; TilePlanes.PlaneData this_plane = planes[nsTile0][np0];
this_plane.initNeibMatch(); this_plane.initMergedValue();
for (int dir = 0; dir < 4; dir++){ // just half directions - relations are symmetrical for (int dir = 0; dir < 4; dir++){ // just half directions - relations are symmetrical
int stx = stx0 + dirsYX[dir][1]; int stx = stx0 + dirsYX[dir][1];
int sty = sty0 + dirsYX[dir][0]; int sty = sty0 + dirsYX[dir][0];
...@@ -1493,7 +1513,7 @@ public class SuperTiles{ ...@@ -1493,7 +1513,7 @@ public class SuperTiles{
TilePlanes.PlaneData [] other_planes = planes[nsTile]; TilePlanes.PlaneData [] other_planes = planes[nsTile];
if (other_planes != null) { if (other_planes != null) {
this_plane.initNeibMatch(dir,other_planes.length); // filled with NaN this_plane.initMergedValue(dir,other_planes.length); // filled with NaN
for (int np = 0; np < other_planes.length; np ++){ for (int np = 0; np < other_planes.length; np ++){
TilePlanes.PlaneData other_plane = this_plane.getPlaneToThis( TilePlanes.PlaneData other_plane = this_plane.getPlaneToThis(
other_planes[np], other_planes[np],
...@@ -1505,26 +1525,7 @@ public class SuperTiles{ ...@@ -1505,26 +1525,7 @@ public class SuperTiles{
false, // boolean ignore_weights, false, // boolean ignore_weights,
dl); // int debugLevel) dl); // int debugLevel)
if (merged_pd !=null) { // now always, but may add later if (merged_pd !=null) { // now always, but may add later
// calculate worsening of the merge (the lower - the better) this_plane.setNeibMatch(dir, np, merged_pd.getValue()); // smallest eigenValue
double rquality = mergeRQuality(
this_plane.getValue(), // double L1,
other_plane.getValue(), // double L2,
merged_pd.getValue(), // double L,
this_plane.getWeight(), // double w1,
other_plane.getWeight()); // double w2)
this_plane.setNeibMatch(dir, np, rquality);
// still happens negative but only for very bad planes - investigate?
if ((rquality < 0) && (this_plane.getWeight() > 0.0) && (other_plane.getWeight() > 0.0) && (merged_pd.getValue() < 1.0) ){ //
System.out.println("nsTile0="+nsTile0+":"+np0+", nsTile="+nsTile+":"+np+", rquality="+rquality+
" w1="+this_plane.getWeight()+" w2="+other_plane.getWeight()+
" L1="+this_plane.getValue()+" L2="+other_plane.getValue()+" L="+merged_pd.getValue());
}
if ((merged_pd.getValue() < 0.1) && (this_plane.getWeight() > 1.0) && (other_plane.getWeight() > 1.0) ){ // fixed
System.out.println("nsTile0="+nsTile0+":"+np0+", nsTile="+nsTile+":"+np+", rquality="+rquality+
" w1="+this_plane.getWeight()+" w2="+other_plane.getWeight()+
" L1="+this_plane.getValue()+" L2="+other_plane.getValue()+" L="+merged_pd.getValue());
}
} }
} }
} }
...@@ -1555,7 +1556,7 @@ public class SuperTiles{ ...@@ -1555,7 +1556,7 @@ public class SuperTiles{
if ( planes[nsTile0] != null) { if ( planes[nsTile0] != null) {
for (int np0 = 0; np0 < planes[nsTile0].length; np0++){ // nu for (int np0 = 0; np0 < planes[nsTile0].length; np0++){ // nu
TilePlanes.PlaneData this_plane = planes[nsTile0][np0]; TilePlanes.PlaneData this_plane = planes[nsTile0][np0];
// this_plane.initNeibMatch(); // this_plane.initMergedValue();
for (int dir = 4; dir < 8; dir++){ // other half - copy from opposite for (int dir = 4; dir < 8; dir++){ // other half - copy from opposite
int stx = stx0 + dirsYX[dir][1]; int stx = stx0 + dirsYX[dir][1];
int sty = sty0 + dirsYX[dir][0]; int sty = sty0 + dirsYX[dir][0];
...@@ -1565,18 +1566,18 @@ public class SuperTiles{ ...@@ -1565,18 +1566,18 @@ public class SuperTiles{
int nsTile = sty * stilesX + stx; // from where to get int nsTile = sty * stilesX + stx; // from where to get
TilePlanes.PlaneData [] other_planes = planes[nsTile]; TilePlanes.PlaneData [] other_planes = planes[nsTile];
if (other_planes !=null) { if (other_planes !=null) {
this_plane.initNeibMatch(dir,other_planes.length); // filled with NaN this_plane.initMergedValue(dir,other_planes.length); // filled with NaN
for (int np = 0; np < other_planes.length; np ++){ for (int np = 0; np < other_planes.length; np ++){
/* /*
if ((other_planes[np] != null) && (other_planes[np].getNeibMatch(dir-4) != null)) { if ((other_planes[np] != null) && (other_planes[np].getMergedValue(dir-4) != null)) {
double [] dbg_nm = other_planes[np].getNeibMatch(dir-4); double [] dbg_nm = other_planes[np].getMergedValue(dir-4);
this_plane.setNeibMatch(dir,np, other_planes[np].getNeibMatch(dir-4, np0)); // this_plane.setNeibMatch(dir,np, other_planes[np].getMergedValue(dir-4, np0)); //
} }
*/ */
if (other_planes[np] != null) { // && (other_planes[np].getNeibMatch(dir-4) != null)) { if (other_planes[np] != null) { // && (other_planes[np].getMergedValue(dir-4) != null)) {
double [] nm = other_planes[np].getNeibMatch(dir-4); double [] nm = other_planes[np].getMergedValue(dir-4);
if (nm != null) { if (nm != null) {
// this_plane.setNeibMatch(dir,np, other_planes[np].getNeibMatch(dir-4, np0)); // // this_plane.setNeibMatch(dir,np, other_planes[np].getMergedValue(dir-4, np0)); //
this_plane.setNeibMatch(dir,np, nm[np0]); // this_plane.setNeibMatch(dir,np, nm[np0]); //
} }
} }
...@@ -1594,7 +1595,7 @@ public class SuperTiles{ ...@@ -1594,7 +1595,7 @@ public class SuperTiles{
ImageDtt.startAndJoin(threads); ImageDtt.startAndJoin(threads);
} }
// Oscolete?
public void selectNeighborPlanes( public void selectNeighborPlanes(
final double worst_worsening, final double worst_worsening,
final boolean mutual_only, final boolean mutual_only,
...@@ -1627,9 +1628,9 @@ public class SuperTiles{ ...@@ -1627,9 +1628,9 @@ public class SuperTiles{
for (int np0 = np0_min; np0 < planes[nsTile0].length; np0++){ // nu for (int np0 = np0_min; np0 < planes[nsTile0].length; np0++){ // nu
TilePlanes.PlaneData this_plane = planes[nsTile0][np0]; TilePlanes.PlaneData this_plane = planes[nsTile0][np0];
this_plane.initNeibBest(); this_plane.initNeibBest();
if (this_plane.getNeibMatch() != null) { if (this_plane.getMergedValue() != null) {
for (int dir = 0; dir < 8; dir++){ // for (int dir = 0; dir < 8; dir++){ //
double [] neib_worse = this_plane.getNeibMatch(dir); double [] neib_worse = this_plane.getMergedValue(dir);
if (neib_worse != null) { if (neib_worse != null) {
int best_index = -1; int best_index = -1;
int np_min = (neib_worse.length > 1) ? 1:0; // Modify if overall plane will be removed int np_min = (neib_worse.length > 1) ? 1:0; // Modify if overall plane will be removed
...@@ -1709,10 +1710,18 @@ public class SuperTiles{ ...@@ -1709,10 +1710,18 @@ public class SuperTiles{
} }
} }
/**
* Find mutual links between multi-layer planes for supertiles. requires that for each plane there are calculated smalles eigenvalues
* for merging with each plane for each of 8 neighbors
* @param rquality maximal degradation by merging (does not depend on the total weight)
* @param maxEigen maximal eigenvalue of each of the merged planes
* @param minWeight minimal weight of each of the planes
* @param debugLevel debug level
* @param dbg_X debug supertile X coordinate
* @param dbg_Y debug supertile Y coordinate
*/
public void selectNeighborPlanesMutual( public void selectNeighborPlanesMutual(
final double rquality, final double rquality,
// final boolean mutual_only,
final double maxEigen, // maximal eigenvalue of planes to consider final double maxEigen, // maximal eigenvalue of planes to consider
final double minWeight, // minimal pain weight to consider final double minWeight, // minimal pain weight to consider
final int debugLevel, final int debugLevel,
...@@ -1736,6 +1745,23 @@ public class SuperTiles{ ...@@ -1736,6 +1745,23 @@ public class SuperTiles{
final Thread[] threads = ImageDtt.newThreadArray(tileProcessor.threadsMax); final Thread[] threads = ImageDtt.newThreadArray(tileProcessor.threadsMax);
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nsTile0 = ai.getAndIncrement(); nsTile0 < nStiles; nsTile0 = ai.getAndIncrement()) {
if ( planes[nsTile0] != null) {
for (int np0 = 0; np0 < planes[nsTile0].length; np0++){ // nu
TilePlanes.PlaneData this_plane = planes[nsTile0][np0];
this_plane.initNeibBest();
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() { threads[ithread] = new Thread() {
public void run() { public void run() {
...@@ -1756,8 +1782,8 @@ public class SuperTiles{ ...@@ -1756,8 +1782,8 @@ public class SuperTiles{
int num_other_planes = 0; int num_other_planes = 0;
for (int np0 = np0_min; np0 < planes[nsTile0].length; np0++){ for (int np0 = np0_min; np0 < planes[nsTile0].length; np0++){
if (planes[nsTile0][np0].getNeibMatch(dir) != null){ if (planes[nsTile0][np0].getMergedValue(dir) != null){
int l = planes[nsTile0][np0].getNeibMatch(dir).length; int l = planes[nsTile0][np0].getMergedValue(dir).length;
if (l > num_other_planes)num_other_planes = l; if (l > num_other_planes)num_other_planes = l;
} }
} }
...@@ -1772,22 +1798,39 @@ public class SuperTiles{ ...@@ -1772,22 +1798,39 @@ public class SuperTiles{
int [] best_pair = {-1,-1}; int [] best_pair = {-1,-1};
double best_rqual = Double.NaN; double best_rqual = Double.NaN;
for (int np0 = np0_min; np0 < this_matched.length; np0++){ for (int np0 = np0_min; np0 < this_matched.length; np0++){
double [] this_rq = planes[nsTile0][np0].getNeibMatch(dir); double [] merge_ev = planes[nsTile0][np0].getMergedValue(dir);
if (!this_matched[np0] && if (!this_matched[np0] &&
(this_rq != null) && (merge_ev != null) &&
((maxEigen == 0.0) || (planes[nsTile0][np0].getValue() < maxEigen)) && ((maxEigen == 0.0) || (planes[nsTile0][np0].getValue() < maxEigen)) &&
(planes[nsTile0][np0].getWeight() > minWeight)) { (planes[nsTile0][np0].getWeight() > minWeight)) {
for (int np = np_min; np < this_rq.length; np++){ for (int np = np_min; np < merge_ev.length; np++){
if (!other_matched[np] && if (!other_matched[np] &&
!Double.isNaN(this_rq[np]) && !Double.isNaN(merge_ev[np]) &&
((maxEigen == 0.0) || (planes[nsTile][np].getValue() < maxEigen)) && ((maxEigen == 0.0) || (planes[nsTile][np].getValue() < maxEigen)) &&
(planes[nsTile][np].getWeight() > minWeight)) { (planes[nsTile][np].getWeight() > minWeight)) {
if (Double.isNaN(best_rqual) || (this_rq[np] < best_rqual)){ // OK if Double.isNaN(this_rq[np]) double w1 = planes[nsTile0][np0].getWeight();
best_rqual = this_rq[np]; double w2 = planes[nsTile][np].getWeight();
double this_rq = mergeRQuality(
planes[nsTile0][np0].getValue(), // double L1,
planes[nsTile][np].getValue(), // double L2,
merge_ev[np], // double L,
w1, // double w1,
w2); // double w2)
// if (this_rq <= rquality) { // compare with the threshold before applying strengths
if ((w1 + w2) * this_rq <= rquality) { // forgive more for weak planes
this_rq /= (w1 + w2); // for comparision reduce this value for stronger planes
if (Double.isNaN(best_rqual) || (this_rq < best_rqual)){ // OK if Double.isNaN(this_rq[np])
best_rqual = this_rq;
best_pair[0]= np0; best_pair[0]= np0;
best_pair[1]= np; best_pair[1]= np;
} }
} }
if ((merge_ev[np] < 0.4) && (w1 > 1.0) && (w2 > 1.0) ){
System.out.println("nsTile0="+nsTile0+":"+np0+", nsTile="+nsTile+":"+np+", this_rq="+this_rq+
" w1="+w1+" w2="+w2+
" L1="+planes[nsTile0][np0].getValue()+" L2="+planes[nsTile][np].getValue()+" L="+merge_ev[np]);
}
}
} }
} }
} }
...@@ -1933,4 +1976,212 @@ public class SuperTiles{ ...@@ -1933,4 +1976,212 @@ public class SuperTiles{
return data; return data;
} }
public TilePlanes.PlaneData[][] copyPlanes(
TilePlanes.PlaneData[][] src_planes)
{
TilePlanes.PlaneData[][] dst_planes = new TilePlanes.PlaneData[src_planes.length][];
return copyPlanes(src_planes, dst_planes);
}
public TilePlanes.PlaneData[][] copyPlanes(
final TilePlanes.PlaneData[][] src_planes,
final TilePlanes.PlaneData[][] dst_planes)
{
final Thread[] threads = ImageDtt.newThreadArray(tileProcessor.threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nsTile = ai.getAndIncrement(); nsTile < src_planes.length; nsTile = ai.getAndIncrement()) {
if (src_planes[nsTile] != null){
dst_planes[nsTile] = new TilePlanes.PlaneData[src_planes[nsTile].length];
for (int np = 0; np < src_planes[nsTile].length; np++){
if (src_planes[nsTile][np] != null){
dst_planes[nsTile][np] = src_planes[nsTile][np].clone();
} else {
dst_planes[nsTile][np] = null;
}
}
} else {
dst_planes[nsTile] = null;
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return dst_planes;
}
public TilePlanes.PlaneData[][] planesSmooth(
final double meas_pull,// relative pull of the original (measured) plane with respect to the average of the neighbors
final int num_passes,
final double maxDiff, // maximal change in any of the disparity values
final int debugLevel,
final int dbg_X,
final int dbg_Y)
{
// if (this.planes_mod == null){
this.planes_mod =copyPlanes(this.planes); // make always (for now) *********************
// }
for (int pass = 0; pass < num_passes; pass++){
double diff = planesSmoothStep(
meas_pull, // relative pull of the original (measured) plane with respect to the average of the neighbors
this.planes, // final TilePlanes.PlaneData[][] measured_planes,
this.planes_mod, // final TilePlanes.PlaneData[][] mod_planes,
true, // final boolean calc_diff,
(pass < 10)? debugLevel: 0,
dbg_X,
dbg_Y);
if (diff < maxDiff){
if (debugLevel > -1){
System.out.println("planesSmooth(): pass:"+pass+" (of "+num_passes+"), rms = "+diff+" < "+maxDiff);
break;
}
}
if (debugLevel > -1){
System.out.println("planesSmooth() - pass:"+pass+" (of "+num_passes+"), rms = "+diff);
}
}
return this.planes_mod;
}
public double planesSmoothStep(
final double meas_pull,// relative pull of the original (measured) plane with respect to the average of the neighbors
final TilePlanes.PlaneData[][] measured_planes,
final TilePlanes.PlaneData[][] mod_planes,
final boolean calc_diff,
final int debugLevel,
final int dbg_X,
final int dbg_Y)
{
final int [][] dirsYX = {{-1, 0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
final int tilesX = tileProcessor.getTilesX();
final int tilesY = tileProcessor.getTilesY();
final int superTileSize = tileProcessor.getSuperTileSize();
final int stilesX = (tilesX + superTileSize -1)/superTileSize;
final int stilesY = (tilesY + superTileSize -1)/superTileSize;
final int debug_stile = dbg_Y * stilesX + dbg_X;
final TilePlanes.PlaneData[][] new_planes = copyPlanes(mod_planes);
final Thread[] threads = ImageDtt.newThreadArray(tileProcessor.threadsMax);
final int numThreads = threads.length;
final double [] rslt_diffs = calc_diff ? new double [numThreads] : null; // all 0;
final AtomicInteger ai_numThread = new AtomicInteger(0);
final AtomicInteger ai = new AtomicInteger(0);
final String [] titles= {
"orig", // 0
"measured", // 1
"n0","n1","n2","n3","n4","n5","n6","n7", // 2 .. 9
"m0","m1","m2","m3","m4","m5","m6","m7","mm", // 10..18
"diff"}; // 19
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [][] dbg_img=null;
int numThread = ai_numThread.getAndIncrement(); // unique number of thread to write to rslt_diffs[numThread]
for (int nsTile0 = ai.getAndIncrement(); nsTile0 < mod_planes.length; nsTile0 = ai.getAndIncrement()) {
int sty0 = nsTile0 / stilesX;
int stx0 = nsTile0 % stilesX;
int dl = ((debugLevel > -1) && (nsTile0 == debug_stile)) ? 1:0;
if ( new_planes[nsTile0] != null) {
if (dl > 0){
System.out.println("planesSmoothStep nsTile0="+nsTile0);
dbg_img = new double [titles.length][];
}
int np0_min = (new_planes[nsTile0].length > 1) ? 1:0; // Modify if overall plane will be removed
for (int np0 = np0_min; np0 < new_planes[nsTile0].length; np0 ++){
TilePlanes.PlaneData this_new_plane = new_planes[nsTile0][np0];
if (dl > 0) dbg_img[ 0] = this_new_plane.getPlaneDisparity(false);
if (dl > 0) dbg_img[ 1] = measured_planes[nsTile0][np0].getPlaneDisparity(false);
int [] neibs = this_new_plane.getNeibBest();
this_new_plane.setWeight(0.0);
for (int dir = 0; dir < neibs.length; dir++){
if (neibs[dir] >= 0) {
int stx = stx0 + dirsYX[dir][1];
int sty = sty0 + dirsYX[dir][0];
int nsTile = sty * stilesX + stx; // from where to get
TilePlanes.PlaneData other_plane = this_new_plane.getPlaneToThis(
mod_planes[nsTile][neibs[dir]], // neighbor, previous value
dl); // debugLevel);
if (dl > 0) dbg_img[ 2 + dir] = other_plane.getPlaneDisparity(false);
if (other_plane != null){
if (this_new_plane.getWeight() > 0.0){
this_new_plane = this_new_plane.mergePlaneToThis(
other_plane, // PlaneData otherPd,
1.0, // double scale_other,
false, // boolean ignore_weights,
dl); // int debugLevel)
} else {
this_new_plane = other_plane;
}
new_planes[nsTile0][np0] = this_new_plane;
if (dl > 0) dbg_img[10 + dir] = this_new_plane.getPlaneDisparity(false);
}
}
}
if ( (meas_pull > 0.0) &&
(measured_planes != null) &&
(measured_planes[nsTile0] != null) &&
(measured_planes[nsTile0][np0] != null)){ // merge with "measured"
if (this_new_plane.getWeight() > 0.0){
this_new_plane = this_new_plane.mergePlaneToThis(
measured_planes[nsTile0][np0], // PlaneData otherPd,
meas_pull, // double scale_other,
false, // boolean ignore_weights,
dl); // int debugLevel)
} else {
this_new_plane = measured_planes[nsTile0][np0].clone();
}
new_planes[nsTile0][np0] = this_new_plane;
if (dl > 0) dbg_img[18] = this_new_plane.getPlaneDisparity(false);
}
// calculate largest disparity difference between old and new plane
if (rslt_diffs != null){
// get plane for both old and new, calc rms of diff
double [] oldPlane = mod_planes[nsTile0][np0].getPlaneDisparity(
false); // use_NaN)
double [] newPlane = new_planes[nsTile0][np0].getPlaneDisparity(
false); // use_NaN)
double s = 0.0;
for (int i = 0; i < oldPlane.length; i++){
double d = newPlane[i] - oldPlane[i];
s+= d*d;
}
s= Math.sqrt(s/oldPlane.length);
if (s > rslt_diffs[numThread]){
rslt_diffs[numThread] = s;
}
if (dl > 0) {
dbg_img[19] = new double[oldPlane.length];
for (int i = 0; i < oldPlane.length; i++){
dbg_img[19][i] = newPlane[i] - oldPlane[i];
}
}
}
if (dl > 0){
showDoubleFloatArrays sdfa_instance = new showDoubleFloatArrays(); // just for debugging?
sdfa_instance.showArrays(dbg_img, superTileSize, superTileSize, true, "smooth_step_x"+stx0+"_y"+sty0, titles);
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
copyPlanes (new_planes, mod_planes); // copy back
if (rslt_diffs == null){
return Double.NaN;
}
double diff = 0.0;
for (int i = 0; (i < numThreads) ; i++) if (diff < rslt_diffs[i]) diff = rslt_diffs[i];
return diff; // return maximal difference
}
} // end of class SuperTiles } // end of class SuperTiles
...@@ -57,8 +57,8 @@ public class TilePlanes { ...@@ -57,8 +57,8 @@ public class TilePlanes {
double [] world_v1 = null; // world in-plane vector, corresponding to vectors[1] double [] world_v1 = null; // world in-plane vector, corresponding to vectors[1]
double [] world_v2 = null; // world in-plane vector, corresponding to vectors[1] double [] world_v2 = null; // world in-plane vector, corresponding to vectors[1]
// double [] daxy = null; // disparity and 2 relative angles (ax and ay) corresponding to fisheye view, near (0,0) scale is pixel size // double [] daxy = null; // disparity and 2 relative angles (ax and ay) corresponding to fisheye view, near (0,0) scale is pixel size
double [][] neib_match = null; // for each of the directions (N, NE, .. NW) quality match for each layer double [][] merged_eig_val = null; // for each of the directions (N, NE, .. NW) quality match for each layer
int [] neib_best = new int [8]; // for each of the directions (N, NE, .. NW) index of best match, -1 if none int [] neib_best = null; // new int [8]; // for each of the directions (N, NE, .. NW) index of best match, -1 if none
// stores "worsening" of merging 2 planes. if L1,L2,L = values[0] of plane1, plane2 plane composite: w1, w2 - weights for plane1, plane2 // stores "worsening" of merging 2 planes. if L1,L2,L = values[0] of plane1, plane2 plane composite: w1, w2 - weights for plane1, plane2
// Lav = Math.sqrt((L1 * L1 * w1 + L2 * L2 * w2)/(w1 + w2)) // Lav = Math.sqrt((L1 * L1 * w1 + L2 * L2 * w2)/(w1 + w2))
// worsening_12 = (L - Lav) * (w1 + w2) * (w1 + w2) / (Lav * x1 * w2) // worsening_12 = (L - Lav) * (w1 + w2) * (w1 + w2) / (Lav * x1 * w2)
...@@ -92,18 +92,44 @@ public class TilePlanes { ...@@ -92,18 +92,44 @@ public class TilePlanes {
pd.vectors[1] = this.vectors[1].clone(); pd.vectors[1] = this.vectors[1].clone();
pd.vectors[2] = this.vectors[2].clone(); pd.vectors[2] = this.vectors[2].clone();
} }
if (this.neib_match != null){ copyNeib(this,pd);
pd.neib_match = this.neib_match.clone(); /*
for (int i = 0; i<this.neib_match.length; i++){ if (this.merged_eig_val != null){
if (this.neib_match[i] != null){ pd.merged_eig_val = this.merged_eig_val.clone();
pd.neib_match[i] = this.neib_match[i].clone(); for (int i = 0; i<this.merged_eig_val.length; i++){
if (this.merged_eig_val[i] != null){
pd.merged_eig_val[i] = this.merged_eig_val[i].clone();
} }
} }
} }
if (this.neib_best != null) pd.neib_best = this.neib_best.clone(); if (this.neib_best != null) pd.neib_best = this.neib_best.clone();
*/
return pd; return pd;
} }
public void copyNeib(
PlaneData src,
PlaneData dst)
{
if (src.merged_eig_val != null){
dst.merged_eig_val = src.merged_eig_val.clone();
for (int i = 0; i < src.merged_eig_val.length; i++){
if (src.merged_eig_val[i] != null){
dst.merged_eig_val[i] = src.merged_eig_val[i].clone();
}
}
}
if (src.neib_best != null) dst.neib_best = src.neib_best.clone();
}
public void invalidateCalculated()
{
this.center_xyz = null; // center of this supertile this plane center in world coordinates
this.world_xyz = null; // world coordinates of the nearest point of the plane, in meters
this.world_v1 = null; // world in-plane vector, corresponding to vectors[1]
this.world_v2 = null; // world in-plane vector, corresponding to vectors[1]
}
public PlaneData ( public PlaneData (
int [] sTileXY, int [] sTileXY,
...@@ -117,40 +143,40 @@ public class TilePlanes { ...@@ -117,40 +143,40 @@ public class TilePlanes {
this.sTileXY = sTileXY.clone(); this.sTileXY = sTileXY.clone();
} }
public double [][] initNeibMatch() public double [][] initMergedValue()
{ {
this.neib_match = new double[8][]; this.merged_eig_val = new double[8][];
return this.neib_match; return this.merged_eig_val;
} }
public double [][] getNeibMatch() public double [][] getMergedValue()
{ {
return this.neib_match; return this.merged_eig_val;
} }
public double [] initNeibMatch(int dir, int leng) public double [] initMergedValue(int dir, int leng)
{ {
this.neib_match[dir] = new double[leng]; this.merged_eig_val[dir] = new double[leng];
for (int i = 0; i < leng; i++) this.neib_match[dir][i] = Double.NaN; for (int i = 0; i < leng; i++) this.merged_eig_val[dir][i] = Double.NaN;
return getNeibMatch(dir); return getMergedValue(dir);
} }
public double [] getNeibMatch(int dir) public double [] getMergedValue(int dir)
{ {
if (this.neib_match == null) { if (this.merged_eig_val == null) {
return null; return null;
} }
return this.neib_match[dir]; return this.merged_eig_val[dir];
} }
public double getNeibMatch(int dir, int plane) public double getMergedValue(int dir, int plane)
{ {
if ((this.neib_match == null) ||(this.neib_match[dir] == null)){ if ((this.merged_eig_val == null) ||(this.merged_eig_val[dir] == null)){
return Double.NaN; return Double.NaN;
} }
return this.neib_match[dir][plane]; return this.merged_eig_val[dir][plane];
} }
public void setNeibMatch(int dir, int plane, double value) public void setNeibMatch(int dir, int plane, double value)
{ {
this.neib_match[dir][plane] = value; this.merged_eig_val[dir][plane] = value;
} }
public int [] initNeibBest() public int [] initNeibBest()
...@@ -452,6 +478,7 @@ public class TilePlanes { ...@@ -452,6 +478,7 @@ public class TilePlanes {
PlaneData pd = this.clone(); // will copy selections too PlaneData pd = this.clone(); // will copy selections too
pd.invalidateCalculated(); // real world vectors
pd.setValues(eig_val[oindx][oindx],eig_val[vindx][vindx],eig_val[hindx][hindx]); // eigenvalues [0] - thickness, 2 other to detect skinny (poles) pd.setValues(eig_val[oindx][oindx],eig_val[vindx][vindx],eig_val[hindx][hindx]); // eigenvalues [0] - thickness, 2 other to detect skinny (poles)
pd.setVectors(plane); pd.setVectors(plane);
...@@ -477,7 +504,8 @@ public class TilePlanes { ...@@ -477,7 +504,8 @@ public class TilePlanes {
PlaneData otherPd, PlaneData otherPd,
int debugLevel) int debugLevel)
{ {
PlaneData pd = otherPd.clone(); PlaneData pd = otherPd.clone(); // TODO: use clone of this, copy only needed info from otherPD
// keep world vectors from otherPd
if (debugLevel > 0) { if (debugLevel > 0) {
System.out.println("getPlaneToThis()"); System.out.println("getPlaneToThis()");
} }
...@@ -596,6 +624,7 @@ public class TilePlanes { ...@@ -596,6 +624,7 @@ public class TilePlanes {
// System.out.println("getPlaneToThis(): "+pd.sTileXY[0]+":"+pd.sTileXY[1]+" -> "+pd.vectors[0][0]+", disp = "+disp+ // System.out.println("getPlaneToThis(): "+pd.sTileXY[0]+":"+pd.sTileXY[1]+" -> "+pd.vectors[0][0]+", disp = "+disp+
// ", other_det = "+((new Matrix(otherPd.vectors).det()) +", pdr_det = "+((new Matrix(pd.vectors).det())))); // ", other_det = "+((new Matrix(otherPd.vectors).det()) +", pdr_det = "+((new Matrix(pd.vectors).det()))));
} }
copyNeib(this, pd);
return pd; // make sure pd are updated // "this" is not used. Should it be used instead of pd? return pd; // make sure pd are updated // "this" is not used. Should it be used instead of pd?
} }
......
...@@ -2823,7 +2823,6 @@ public class TileProcessor { ...@@ -2823,7 +2823,6 @@ public class TileProcessor {
clt_parameters.tileX, clt_parameters.tileX,
clt_parameters.tileY); clt_parameters.tileY);
if (clt_parameters.plMutualOnly) {
st.selectNeighborPlanesMutual( st.selectNeighborPlanesMutual(
clt_parameters.plWorstWorsening, // final double worst_worsening, clt_parameters.plWorstWorsening, // final double worst_worsening,
clt_parameters.plMaxEigen, clt_parameters.plMaxEigen,
...@@ -2831,19 +2830,30 @@ public class TileProcessor { ...@@ -2831,19 +2830,30 @@ public class TileProcessor {
0, // final int debugLevel) 0, // final int debugLevel)
clt_parameters.tileX, clt_parameters.tileX,
clt_parameters.tileY); clt_parameters.tileY);
TilePlanes.PlaneData [][] planes_mod = null;
if (clt_parameters.plMutualOnly) { // temporarily re-use obsolete parameter to test smoothing
planes_mod = st.planesSmooth(
clt_parameters.plPull, // final double meas_pull,// relative pull of the original (measured) plane with respect to the average of the neighbors
clt_parameters.plIterations, // final int num_passes,
Math.pow(10.0, -clt_parameters.plPrecision), // final double maxDiff, // maximal change in any of the disparity values
0, // final int debugLevel)
clt_parameters.tileX,
clt_parameters.tileY);
} else { // } else {
st.selectNeighborPlanes( // st.selectNeighborPlanes(
clt_parameters.plWorstWorsening, // final double worst_worsening, // clt_parameters.plWorstWorsening, // final double worst_worsening,
clt_parameters.plMutualOnly, // final boolean mutual_only, // clt_parameters.plMutualOnly, // final boolean mutual_only,
0); // final int debugLevel) // 0); // final int debugLevel)
} }
if (clt_parameters.show_planes){ if (clt_parameters.show_planes){
int [] wh = st.getShowPlanesWidthHeight(); int [] wh = st.getShowPlanesWidthHeight();
double [][] plane_data_nonan = st.getShowPlanes( double [][] plane_data_nonan = st.getShowPlanes(
st.getPlanes(), (planes_mod != null) ? st.getPlanesMod():st.getPlanes(),
clt_parameters.plMinStrength, // minWeight, clt_parameters.plMinStrength, // minWeight,
clt_parameters.plMaxEigen, // maxEigen, clt_parameters.plMaxEigen, // maxEigen,
clt_parameters.plDispNorm, clt_parameters.plDispNorm,
...@@ -2851,7 +2861,7 @@ public class TileProcessor { ...@@ -2851,7 +2861,7 @@ public class TileProcessor {
0.0, 0.0,
10.0); 10.0);
double [][] plane_data_nan = st.getShowPlanes( double [][] plane_data_nan = st.getShowPlanes(
st.getPlanes(), (planes_mod != null) ? st.getPlanesMod():st.getPlanes(),
clt_parameters.plMinStrength, // minWeight, clt_parameters.plMinStrength, // minWeight,
clt_parameters.plMaxEigen, // maxEigen, clt_parameters.plMaxEigen, // maxEigen,
clt_parameters.plDispNorm, clt_parameters.plDispNorm,
...@@ -2870,6 +2880,12 @@ public class TileProcessor { ...@@ -2870,6 +2880,12 @@ public class TileProcessor {
// sdfa_instance.showArrays(plane_data_nonan, wh[0], wh[1], true, "plane_data_noNaN"); // sdfa_instance.showArrays(plane_data_nonan, wh[0], wh[1], true, "plane_data_noNaN");
// sdfa_instance.showArrays(plane_data_nan, wh[0], wh[1], true, "plane_data_NaN"); // sdfa_instance.showArrays(plane_data_nan, wh[0], wh[1], true, "plane_data_NaN");
sdfa_instance.showArrays(plane_data, wh[0], wh[1], true, "plane_data"); sdfa_instance.showArrays(plane_data, wh[0], wh[1], true, "plane_data");
// show plane data // show plane data
/* /*
......
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