Commit bdf3d47f authored by Andrey Filippov's avatar Andrey Filippov
Browse files

splitting planes into pairs

parent 41d614cb
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -2162,6 +2162,10 @@ public class EyesisCorrectionParameters {
  		public int        plIterations         =  10;   // Maximal number of smoothing iterations for each step
  		public int        plPrecision          =  6;    // Maximal step difference (1/power of 10)
  		
  		public double     plSplitPull          =  .5;   // Relative weight of center plane when splitting into pairs
  		public int        plSplitMinNeib       =  2;    // Minimal number of neighbors to split plane in pairs
  		
  		
  		public boolean    plFuse               =  true; // Fuse planes together (off for debug only)
  		public boolean    plKeepOrphans        =  true; // Keep unconnected supertiles
  		public double     plMinOrphan          =  2.0;  // Minimal strength unconnected supertiles to keep
@@ -2427,6 +2431,10 @@ public class EyesisCorrectionParameters {
			properties.setProperty(prefix+"plPull",           this.plPull +"");
  			properties.setProperty(prefix+"plIterations",     this.plIterations+"");
  			properties.setProperty(prefix+"plPrecision",      this.plPrecision+"");

			properties.setProperty(prefix+"plSplitPull",      this.plSplitPull +"");
  			properties.setProperty(prefix+"plSplitMinNeib",   this.plSplitMinNeib+"");

  			properties.setProperty(prefix+"plFuse",           this.plFuse+"");
			properties.setProperty(prefix+"plKeepOrphans",    this.plKeepOrphans+"");
			properties.setProperty(prefix+"plMinOrphan",      this.plMinOrphan +"");
@@ -2680,6 +2688,10 @@ public class EyesisCorrectionParameters {
  			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+"plSplitPull")!=null)       this.plSplitPull=Double.parseDouble(properties.getProperty(prefix+"plSplitPull"));
  			if (properties.getProperty(prefix+"plSplitMinNeib")!=null)    this.plSplitMinNeib=Integer.parseInt(properties.getProperty(prefix+"plSplitMinNeib"));

  			if (properties.getProperty(prefix+"plFuse")!=null)            this.plFuse=Boolean.parseBoolean(properties.getProperty(prefix+"plFuse"));
  			if (properties.getProperty(prefix+"plKeepOrphans")!=null)     this.plKeepOrphans=Boolean.parseBoolean(properties.getProperty(prefix+"plKeepOrphans"));
  			if (properties.getProperty(prefix+"plMinOrphan")!=null)       this.plMinOrphan=Double.parseDouble(properties.getProperty(prefix+"plMinOrphan"));
@@ -2955,6 +2967,10 @@ public class EyesisCorrectionParameters {
  			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.addNumericField("Relative weight of center plane when splitting into pairs",                    this.plSplitPull,  6);
  			gd.addNumericField("Minimal number of neighbors to split plane in pairs",                          this.plSplitMinNeib,  0);
  			
  			gd.addCheckbox    ("Fuse planes together (off for debug only)",                                    this.plFuse);
  			gd.addCheckbox    ("Keep unconnected supertiles",                                                  this.plKeepOrphans);
  			gd.addNumericField("Minimal strength unconnected supertiles to keep",                              this.plMinOrphan,  6);
@@ -3218,6 +3234,10 @@ public class EyesisCorrectionParameters {
  			this.plPull=                gd.getNextNumber();
  			this.plIterations=    (int) gd.getNextNumber();
  			this.plPrecision=     (int) gd.getNextNumber();

  			this.plSplitPull=           gd.getNextNumber();
  			this.plSplitMinNeib=  (int) gd.getNextNumber();

  			this.plFuse=                gd.getNextBoolean();
  			this.plKeepOrphans=         gd.getNextBoolean();
  			this.plMinOrphan=           gd.getNextNumber();
+199 −0
Original line number Diff line number Diff line
@@ -2680,6 +2680,205 @@ public class SuperTiles{
		return diff; // return maximal difference
	}

	public double [][] planesGetDiff(
			final TilePlanes.PlaneData[][] measured_planes,
			final TilePlanes.PlaneData[][] mod_planes,
			final int debugLevel,
			final int dbg_X,
			final int dbg_Y)
	{
		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 double [][] diffs = null;

		return diffs;
	}
	
	/**
	 * Create candidate planes to break a single plane in 2 by splitting consecutive connected
	 * neighbors in 2 groups that make the smallest weighted sum of the eigenvalues
	 * Groups may be optionally supplemented by the center supertile 
	 * @param center_planes [per supertile][per plane] array of plane objects to use as
	 *        the source of connections and optionally other data for the center tiles
	 * @param neib_planes  [per supertile][per plane] array of plane objects to use for
	 *        neighbor data. May be the same as center_planes or different
	 * @param center_pull - merge with center plane when calculating half-planes with this
	 *  relative weight: 0.0 - only neighbors, 1.0 - same weight of the center as each neighbor.
	 * @param min_neibs - minimal number of connected neighbors to work with (>=2)       
	 * @param preferDisparity - the first eigenvalue/vector is the most disparity-like
	 *                          (false - smallest eigenvalue)
	 * @param debugLevel debug level
	 * @param dbg_X supertile horizontal index to show debug information
	 * @param dbg_Y supertile vertical index to show debug information
	 * @return a pair of plane objects for each [supertile][plane][3] and a combination of both
	 *         (to compare eigenvalues)
	 */
	public TilePlanes.PlaneData[][][] breakPlanesToPairs(
			final TilePlanes.PlaneData[][] center_planes, // measured_planes,
			final TilePlanes.PlaneData[][] neib_planes,   //mod_planes,
			final double                   center_pull,
			final int                      min_neibs, // 2
			final boolean                  preferDisparity, // Always start with disparity-most axis (false - lowest eigenvalue)
			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[][][] rslt_planes = new TilePlanes.PlaneData[center_planes.length][][];
		final Thread[] threads = ImageDtt.newThreadArray(tileProcessor.threadsMax);
		final AtomicInteger ai = new AtomicInteger(0);
		final String [] titles= {"center", "first", "second", "all"};

		for (int ithread = 0; ithread < threads.length; ithread++) {
			threads[ithread] = new Thread() {
				public void run() {
					double [][] dbg_img=null;
					for (int nsTile0 = ai.getAndIncrement(); nsTile0 < center_planes.length; nsTile0 = ai.getAndIncrement()) {
						int sty0 = nsTile0 / stilesX;  
						int stx0 = nsTile0 % stilesX;
						int dl = ((debugLevel > -1) && (nsTile0 == debug_stile)) ? 1:0;
						if ( center_planes[nsTile0] != null) {
							rslt_planes[nsTile0] = new TilePlanes.PlaneData[center_planes[nsTile0].length][];
							if (dl > 0){
								System.out.println("breakPlanesToPairs nsTile0="+nsTile0);
								dbg_img = new double [titles.length][];
							}
							int np0_min = (center_planes[nsTile0].length > 1) ? 1:0; // Modify if overall plane will be removed
							for (int np0 = np0_min; np0 < center_planes[nsTile0].length; np0 ++){
								TilePlanes.PlaneData center_plane = center_planes[nsTile0][np0];
								if (dl > 0) dbg_img[ 0] = center_plane.getPlaneDisparity(false);
								int [] neibs = center_plane.getNeibBest();
								int num_neibs = 0;
								for (int i = 0; i < neibs.length; i++) if (neibs[i] >= 0) num_neibs++;
								if (num_neibs >= min_neibs) {
									// create all pairs to test
									int num_splits = num_neibs * (num_neibs - 1) / 2;
									double [] split_quality = new double [num_splits]; // weighted sum of eigenvalues of merged
									int [][][] neibs12 = new int [2][num_splits][];
									TilePlanes.PlaneData[][] plane_triads = new TilePlanes.PlaneData[num_splits][3]; 
									int [] neib_index = new int [num_neibs];
									int nn = 0;
									for (int i = 0; i < neibs.length; i++) if (neibs[i] >= 0) neib_index[nn++] = i;
									nn = 0;
									for (int nStart = 1; nStart < num_neibs; nStart++) {
										for (int nEnd = nStart+1; nEnd <= num_neibs; nEnd++){
											neibs12[0][nn] = neibs.clone();
											neibs12[1][nn] = neibs.clone();
											for (int i = 0; i < neib_index.length; i++) {
												if ((i < nStart) || (i >= nEnd)){
													neibs12[0][nn][neib_index[i]] = -1;
												} else {
													neibs12[1][nn][neib_index[i]] = -1;
												}
											}
											nn++;
										}
									}
									
									for (int nSplit = 0; nSplit < num_splits; nSplit++) {
										// Calculate merged plane for each selection (and other), weighted average and store to split_quality
										for (int nis = 0; nis < 2; nis++) {
											plane_triads[nSplit][nis] = center_planes[nsTile0][np0].clone();
											plane_triads[nSplit][nis].setWeight(center_pull * plane_triads[nSplit][nis].getWeight());
											for (int dir = 0; dir <8; dir++){
												int np = neibs12[nis][nSplit][dir];
												if (np >= 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 = plane_triads[nSplit][nis].getPlaneToThis(
															neib_planes[nsTile][np],
															dl); // debugLevel);
													// if (dl > 0) dbg_img[ 2 + dir] = other_plane.getPlaneDisparity(false);
													if (other_plane != null){
														if (plane_triads[nSplit][nis].getWeight() > 0.0){
															plane_triads[nSplit][nis] = plane_triads[nSplit][nis].mergePlaneToThis(
																	other_plane, // PlaneData otherPd,
																	1.0,         // double    scale_other,
																	false,       // boolean   ignore_weights,
																	preferDisparity,
																	dl); // int       debugLevel)
														} else {
															plane_triads[nSplit][nis] = other_plane; 
														}
														//if (dl > 0) dbg_img[10 + dir] = this_new_plane.getPlaneDisparity(false);
													} else {
														plane_triads[nSplit][nis] = null;
														break;
													}
												}
											}
										} // for (int nis = 0; nis < 2; nis++) {
										if ((plane_triads[nSplit][0] != null) && (plane_triads[nSplit][1] != null)){
											double w1 = plane_triads[nSplit][0].getWeight();
											double w2 = plane_triads[nSplit][1].getWeight();
											split_quality[nSplit] = (w1 * plane_triads[nSplit][0].getValue() + w2 * plane_triads[nSplit][1].getValue())/
													(w1 + w2);
										} else {
											split_quality[nSplit] = Double.NaN;
										}
									}
									// find minimum in split_quality and generate a pair of plane objects, setting neighbors for each
									// later use these plane pairs to assign tiles to each and generate a new eigenvalues/vectors
									// TODO: How to handle a pair? Any special treatment (like fusing?), 
									// if the plane intersection line is inside supertile - use min/max for snapping
									int best_index = -1;
									for (int nSplit = 0; nSplit < num_splits; nSplit++) {
										if (!Double.isNaN(split_quality[nSplit]) && ((best_index < 0) || (split_quality[nSplit] < split_quality[best_index]))){
											best_index = nSplit;
										}
									}
									if (best_index >= 0) {
										plane_triads[best_index][2] = plane_triads[best_index][0].clone().mergePlaneToThis(
												plane_triads[best_index][1], // PlaneData otherPd,
													1.0,                    // double    scale_other,
													false,                  // boolean   ignore_weights,
													preferDisparity,
													dl);										
										for (int nis = 0; nis < 2; nis++) {
											plane_triads[best_index][nis].setNeibBest(neibs12[nis][best_index]);
										}
										rslt_planes[nsTile0][np0] = plane_triads[best_index];
										if (dl > 0) dbg_img[ 1] = plane_triads[best_index][0].getPlaneDisparity(false);
										if (dl > 0) dbg_img[ 2] = plane_triads[best_index][1].getPlaneDisparity(false);
										if (dl > 0) dbg_img[ 3] = plane_triads[best_index][2].getPlaneDisparity(false);
										
										// merged_eig_val are not set - will have to be recalculated when updating after changing tile selections
										// to make each plane
										// TODO save gain from splitting to planes 
										
									}
									
									if ((dl > 0) && (debugLevel > -1)){
										showDoubleFloatArrays sdfa_instance = new showDoubleFloatArrays();
										sdfa_instance.showArrays(dbg_img, superTileSize, superTileSize, true, "breakPlanesToPairs"+stx0+"_y"+sty0+"_p"+np0, titles);
									}
								}
							}
						}								
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
		return rslt_planes;
	}




	public boolean [][] selectPlanes(
			final double dispNorm,
			final double maxEigen, // maximal eigenvalue of planes to consider
+5 −0
Original line number Diff line number Diff line
@@ -204,6 +204,11 @@ public class TilePlanes {
			return this.neib_best[dir];
		}

		public void setNeibBest(int [] vals)
		{
			this.neib_best = vals;
		}

		public void setNeibBest(int dir, int val)
		{
			this.neib_best[dir] = val;
+11 −0
Original line number Diff line number Diff line
@@ -3039,6 +3039,17 @@ public class TileProcessor {
		// save surfaces with SuperTiles instance. They can be used to snap to for the per-tile disparity maps.
		st.setSurfaces(surfaces);

		TilePlanes.PlaneData[][][]       split_planes =  
				st.breakPlanesToPairs(
				st.getPlanes(), // Mod(),             // final TilePlanes.PlaneData[][] center_planes, // measured_planes,
				st.getPlanes(), // Mod(),              // final TilePlanes.PlaneData[][] neib_planes,   //mod_planes,
				clt_parameters.plSplitPull ,    // final double                   center_pull,
				clt_parameters.plSplitMinNeib , // min_neibs, // 2
				clt_parameters.plPreferDisparity,
				1,                              // final int debugLevel)
				clt_parameters.tileX,
				clt_parameters.tileY); 
		
		if (clt_parameters.show_planes){
			int [] wh = st.getShowPlanesWidthHeight();
			double [][] plane_data_nonan = st.getShowPlanes(