Commit 612b68e3 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

debugging iterations

parent 22cc393a
Loading
Loading
Loading
Loading
+220 −35
Original line number Original line Diff line number Diff line
@@ -70,7 +70,7 @@ public class OpticalFlow {
				public void run() {
				public void run() {
					for (int iMTile = ai.getAndIncrement(); iMTile < nan_tiles.length; iMTile = ai.getAndIncrement()) {
					for (int iMTile = ai.getAndIncrement(); iMTile < nan_tiles.length; iMTile = ai.getAndIncrement()) {
						if (iMTile == dbg_mtile) {
						if (iMTile == dbg_mtile) {
							System.out.println("iMTile = "+iMTile);
//							System.out.println("iMTile = "+iMTile);
						}
						}
						if (nan_tiles[iMTile] != null) {
						if (nan_tiles[iMTile] != null) {
							tilesFillNaN(
							tilesFillNaN(
@@ -95,7 +95,7 @@ public class OpticalFlow {
					qthis,        // final QuadCLT qthis,
					qthis,        // final QuadCLT qthis,
					margin);      // final int     margin); // extra margins over 16x16 tiles to accommodate distorted destination tiles
					margin);      // final int     margin); // extra margins over 16x16 tiles to accommodate distorted destination tiles
		}
		}
		System.out.println("fillTilesNans() DONE.");
//		System.out.println("fillTilesNans() DONE.");
	}
	}


	public double [][] correlate2DIterate( // returns optical flow and confidence
	public double [][] correlate2DIterate( // returns optical flow and confidence
@@ -138,6 +138,11 @@ public class OpticalFlow {
		double [][] flowXY_run = flowXY; // only non-nulls for the tiles to correlate
		double [][] flowXY_run = flowXY; // only non-nulls for the tiles to correlate
		final double []   abs_change = new double [reference_tiles.length]; // updated 
		final double []   abs_change = new double [reference_tiles.length]; // updated 
		Arrays.fill(abs_change, Double.NaN);
		Arrays.fill(abs_change, Double.NaN);
		final double [] step_scale =  new double [reference_tiles.length]; // multiply increment if change exceeds previous
		Arrays.fill(step_scale, 1.0);
		final double [][] flowXY_prev =  new double [reference_tiles.length][]; // multiply increment if change exceeds previous

		
		for (int ntry = 0; ntry < max_tries; ntry++) {
		for (int ntry = 0; ntry < max_tries; ntry++) {
			double [][][] scene_tiles = prepareSceneTiles(// to match to reference
			double [][][] scene_tiles = prepareSceneTiles(// to match to reference
					// null for {scene,reference}{xyz,atr} uses instances globals 
					// null for {scene,reference}{xyz,atr} uses instances globals 
@@ -177,13 +182,21 @@ public class OpticalFlow {
					dradius,                // final double      dradius,      // weight calculation (1/(r/dradius)^2 + 1)
					dradius,                // final double      dradius,      // weight calculation (1/(r/dradius)^2 + 1)
					refine_num,             // final int         refine_num,   // number of iterations to apply weights around new center
					refine_num,             // final int         refine_num,   // number of iterations to apply weights around new center
					-1);                    //final int         debug_level)
					-1);                    //final int         debug_level)
			double      this_min_change = (ntry < num_run_all)? 0.0: min_change;
			boolean     ignore_worsening = ntry < (num_run_all + 10);
			if (debug_level > 0) {
				System.out.println("======== NTRY "+ntry +" ========");
			}
			flowXY_run = recalculateFlowXY(
			flowXY_run = recalculateFlowXY(
					flowXY,                     // final double [][] flowXY, // will update
					flowXY,                     // final double [][] flowXY, // will update
					flowXY_prev,                // final double [][] flowXY_prev, // previous flowXY (may be null for tiles)   
					vectorsXYS,                 // final double [][] corr_vectorsXY,
					vectorsXYS,                 // final double [][] corr_vectorsXY,
					abs_change,                 // final double []   abs_change, // updated
					abs_change,                 // final double []   abs_change, // updated
					step_scale,                 // final double []   step_scale, // multiply increment if change exceeds previous
					ignore_worsening,           // final boolean     boolean     ignore_worsening 
					magic_scale/transform_size, // final double      magic_scale, // 0.85 for CM
					magic_scale/transform_size, // final double      magic_scale, // 0.85 for CM
					((ntry < num_run_all)? 0.0: min_change), // final double      min_change,
					this_min_change,            // final double      min_change,
					1);                         // final int         debug_level);
					2);                         // final int         debug_level);
			if (flowXY_run == null) { // nothing to do left
			if (flowXY_run == null) { // nothing to do left
				break; 
				break; 
			}
			}
@@ -212,7 +225,7 @@ public class OpticalFlow {
					for (int iMTile = ai.getAndIncrement(); iMTile < currentFlowXY.length; iMTile = ai.getAndIncrement())
					for (int iMTile = ai.getAndIncrement(); iMTile < currentFlowXY.length; iMTile = ai.getAndIncrement())
						if ((currentFlowXY[iMTile] != null) && (corr_vectorsXY[iMTile] != null)){
						if ((currentFlowXY[iMTile] != null) && (corr_vectorsXY[iMTile] != null)){
  						if (iMTile == dbg_mtile) {
  						if (iMTile == dbg_mtile) {
							System.out.println("iMTile = "+iMTile);
//							System.out.println("iMTile = "+iMTile);
						}
						}
  						flowXY[iMTile]= new double[] {
  						flowXY[iMTile]= new double[] {
  								currentFlowXY[iMTile][0] + rmagic_scale * corr_vectorsXY[iMTile][0],
  								currentFlowXY[iMTile][0] + rmagic_scale * corr_vectorsXY[iMTile][0],
@@ -227,8 +240,10 @@ public class OpticalFlow {
	/**
	/**
	 * Recalculate optical flow vector (in image pixels)
	 * Recalculate optical flow vector (in image pixels)
	 * @param flowXY current per-tile vectors (null for undefined), updated
	 * @param flowXY current per-tile vectors (null for undefined), updated
	 * @param flowXY_prev  previous flowXY (may be null for tiles) 
	 * @param corr_vectorsXY correction vector from correlation to apply
	 * @param corr_vectorsXY correction vector from correlation to apply
	 * @param abs_change absolute value of last coordinate change for each tile
	 * @param abs_change absolute value of last coordinate change for each tile
	 * @param ignore_worsening continue even if the change exceeds previous
	 * @param magic_scale divide correlation vector (typically 0.85/8 for CM argmax) 
	 * @param magic_scale divide correlation vector (typically 0.85/8 for CM argmax) 
	 * @param min_change minimal vector coordinate difference to repeat correlations
	 * @param min_change minimal vector coordinate difference to repeat correlations
	 * @param debug_level if > 0; print number of tiles to correlate
	 * @param debug_level if > 0; print number of tiles to correlate
@@ -236,8 +251,11 @@ public class OpticalFlow {
	 */
	 */
	double [][] recalculateFlowXY(
	double [][] recalculateFlowXY(
			final double [][] flowXY, // will update
			final double [][] flowXY, // will update
			final double [][] flowXY_prev, // previous flowXY (may be null for tiles)   
			final double [][] corr_vectorsXY,
			final double [][] corr_vectorsXY,
			final double []   abs_change, // updated
			final double []   abs_change, // updated
			final double []   step_scale, // multiply increment if change exceeds previous
			final boolean     ignore_worsening, 
			final double      magic_scale, // 0.85 for CM
			final double      magic_scale, // 0.85 for CM
			final double      min_change,
			final double      min_change,
			final int         debug_level)  
			final int         debug_level)  
@@ -246,36 +264,104 @@ public class OpticalFlow {
		final Thread[] threads = ImageDtt.newThreadArray(threadsMax);
		final Thread[] threads = ImageDtt.newThreadArray(threadsMax);
		final AtomicInteger ai = new AtomicInteger(0);
		final AtomicInteger ai = new AtomicInteger(0);
		final double [][]   flowXY_task =  new double [flowXY.length][];
		final double [][]   flowXY_task =  new double [flowXY.length][];
		final int dbg_mtile = 620; // 453; // 500;
		final int dbg_mtile = 473; // 295; // 15/7 620; // 453; // 500;
		final double rmagic_scale = 1.0/magic_scale;
		final double rmagic_scale = 1.0/magic_scale;
		final AtomicInteger aupdate = new AtomicInteger(0); //number of tiles to recalculate
		final AtomicInteger aupdate = new AtomicInteger(0); //number of tiles to recalculate
		final double reduce_step = 0.5; //multiply step if calculated difference is larger thart the previous
		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() {
					for (int iMTile = ai.getAndIncrement(); iMTile < flowXY.length; iMTile = ai.getAndIncrement()) {
					for (int iMTile = ai.getAndIncrement(); iMTile < flowXY.length; iMTile = ai.getAndIncrement()) {
  						if (iMTile == dbg_mtile) {
  						if (iMTile == dbg_mtile) {
							System.out.println("iMTile = "+iMTile);
//							System.out.println("iMTile = "+iMTile);
						}
						}
  						if (flowXY[iMTile] != null){
  						if (flowXY[iMTile] != null){
  							if (corr_vectorsXY[iMTile] == null) {
  							if (corr_vectorsXY[iMTile] == null) {
  								if (min_change <= 0.0) {
  								if (min_change <= 0.0) {
  									if (flowXY_prev[iMTile] != null) {
  										flowXY_prev[iMTile][0] = flowXY[iMTile][0];
  										flowXY_prev[iMTile][1] = flowXY[iMTile][1];
  									} else {
  										flowXY_prev[iMTile] = flowXY[iMTile].clone();
  									}
  									flowXY_task[iMTile] = flowXY[iMTile];
  									flowXY_task[iMTile] = flowXY[iMTile];
  									abs_change[iMTile] = Double.NaN;
  									abs_change[iMTile] = Double.NaN;
  									aupdate.getAndIncrement();
  									aupdate.getAndIncrement();
  								}
  								}
  							} else { // if (corr_vectorsXY[iMTile] == null)
  							} else { // if (corr_vectorsXY[iMTile] == null)
  								double dx = rmagic_scale * corr_vectorsXY[iMTile][0];
  								double dx = step_scale[iMTile] * rmagic_scale * corr_vectorsXY[iMTile][0];
  								double dy = rmagic_scale * corr_vectorsXY[iMTile][1];
  								double dy = step_scale[iMTile] * rmagic_scale * corr_vectorsXY[iMTile][1];
  								// apply correction in any case
  								// apply correction in any case
  								flowXY[iMTile][0] += dx;
//  								flowXY[iMTile][0] += dx;
  								flowXY[iMTile][1] += dy;
//  								flowXY[iMTile][1] += dy;
  								
  								double new_diff = Math.sqrt(dx*dx + dy*dy);
  								double new_diff = Math.sqrt(dx*dx + dy*dy);
//  		  						if ((debug_level > 0) && (iMTile == dbg_mtile)) {
//  									System.out.print(String.format("iMTile = %4d (%2d / %2d) flowXY = [%8.6f/%8.6f] dx = %8.6f dy =  %8.6f  abs= %8.6f ",
//  											iMTile,  (iMTile %40), (iMTile / 40), flowXY[iMTile][0], flowXY[iMTile][1], dx,dy,new_diff));
//  								}
  								
  								double last_change = abs_change[iMTile]; // may be NaN;
  								double last_change = abs_change[iMTile]; // may be NaN;
  								abs_change[iMTile] = new_diff;
  								abs_change[iMTile] = new_diff;
  								if (!(new_diff > last_change) && (new_diff > min_change)) { // not worse (any value are not worse than NaN) and larger than threshold
  								
  								if ((debug_level >2) && (new_diff > last_change) && (min_change > 0.0)) {
  									System.out.println("iMTile="+iMTile+", new_diff="+ new_diff+", last_change="+last_change);
  								}
//  								if ((new_diff > min_change) || (min_change <= 0.0)) { // not worse (any value are not worse than NaN) and larger than threshold
  								if (new_diff < min_change) {
  									if (flowXY_prev[iMTile] != null) {
  										flowXY_prev[iMTile][0] = flowXY[iMTile][0];
  										flowXY_prev[iMTile][1] = flowXY[iMTile][1];
  									} else {
  										flowXY_prev[iMTile] = flowXY[iMTile].clone();
  									}
  									flowXY[iMTile][0] += dx;
  									flowXY[iMTile][1] += dy;
  								} else {
  									if (ignore_worsening || !(new_diff >= last_change)) { // better or ignore - continue iterations
  										//
  										if ((debug_level > 0) && (iMTile == dbg_mtile))  {
  											System.out.println(String.format("iMTile = %4d (%2d / %2d) flowXY = [%8.6f/%8.6f] step_scale = %8.6f dx = %8.6f dy =  %8.6f  abs= %8.6f previous = %8.6f CONTINUE",
  													iMTile, (iMTile %40), (iMTile / 40), flowXY[iMTile][0], flowXY[iMTile][1], step_scale[iMTile], dx,dy,new_diff, last_change));
  										}
  	  									if (flowXY_prev[iMTile] != null) {
  	  										flowXY_prev[iMTile][0] = flowXY[iMTile][0];
  	  										flowXY_prev[iMTile][1] = flowXY[iMTile][1];
  	  									} else {
  	  										flowXY_prev[iMTile] = flowXY[iMTile].clone();
  	  									}
  										flowXY[iMTile][0] += dx;
  										flowXY[iMTile][1] += dy;
  										flowXY_task[iMTile] = flowXY[iMTile]; // set to measure
  										flowXY_task[iMTile] = flowXY[iMTile]; // set to measure
  										abs_change[iMTile] = new_diff;
  										aupdate.getAndIncrement();
  										aupdate.getAndIncrement();
  									} else if ((new_diff >= last_change) && (min_change > 0)) { // worse - reduce step, but still apply
   										if (debug_level > 1) {
   											System.out.println(String.format("iMTile = %4d (%2d / %2d) flowXY = [%8.6f/%8.6f] step_scale = %8.6f dx = %8.6f dy =  %8.6f  abs= %8.6f previous = %8.6f REDUCED STEP",
   													iMTile, (iMTile %40), (iMTile / 40), flowXY[iMTile][0], flowXY[iMTile][1], step_scale[iMTile], dx,dy,new_diff, last_change));
   										}
   										// do not update previous (it should be not null
  	  									if (flowXY_prev[iMTile] == null) { // should not happen
  	  										System.out.println("BUG!");
  	  										flowXY_prev[iMTile] = flowXY[iMTile].clone();
  	  									}
  	  									dx = flowXY[iMTile][0] - flowXY_prev[iMTile][0];
  	  									dy = flowXY[iMTile][1] - flowXY_prev[iMTile][1];
  	  									flowXY[iMTile][0] = flowXY_prev[iMTile][0];
  	  									flowXY[iMTile][1] = flowXY_prev[iMTile][1];
   										
  	  									step_scale[iMTile] *= reduce_step;
   										dx *= reduce_step;
   										dx *= reduce_step;
   										
   										flowXY[iMTile][0] += dx;
   										flowXY[iMTile][1] += dy;
   										flowXY_task[iMTile] = flowXY[iMTile]; // set to measure
   										abs_change[iMTile] = last_change; // restore previous step
   										aupdate.getAndIncrement();
//   									} else if (debug_level > 1) {
//	  									System.out.println(String.format("iMTile = %4d (%2d / %2d) dx = %8.6f dy =  %8.6f  abs= %8.6f previous = %8.6f",
//  	  											iMTile, (iMTile %40), (iMTile / 40), dx,dy,new_diff, last_change));
  									}
  								}
  								}
  							}
  							}
						}
						}
@@ -316,7 +402,7 @@ public class OpticalFlow {
				public void run() {
				public void run() {
					for (int iMTile = ai.getAndIncrement(); iMTile < corr2d_tiles.length; iMTile = ai.getAndIncrement()) if (corr2d_tiles[iMTile] != null) {
					for (int iMTile = ai.getAndIncrement(); iMTile < corr2d_tiles.length; iMTile = ai.getAndIncrement()) if (corr2d_tiles[iMTile] != null) {
  						if (iMTile == dbg_mtile) {
  						if (iMTile == dbg_mtile) {
							System.out.println("iMTile = "+iMTile);
//							System.out.println("iMTile = "+iMTile);
						}
						}
						vectors_xys[iMTile] = getCorrCenterXYS_CM(
						vectors_xys[iMTile] = getCorrCenterXYS_CM(
								corr2d_tiles[iMTile], // double []   corr2d_tile,
								corr2d_tiles[iMTile], // double []   corr2d_tile,
@@ -375,6 +461,12 @@ public class OpticalFlow {
		}
		}
		int iYMmax = (int) Math.round(yMax); 
		int iYMmax = (int) Math.round(yMax); 
		int iXMmax = (int) Math.round(xMax); 
		int iXMmax = (int) Math.round(xMax); 
		if (iYMmax >= transform_size) {
			iYMmax = transform_size -1;
		}
		if (iYMmax >= transform_size) {
			iXMmax = transform_size -1;
		}
		double dMax = corr2d_tile[iYMmax * corr_size + iXMmax]; // negative
		double dMax = corr2d_tile[iYMmax * corr_size + iXMmax]; // negative
		double s1=0.0, s2 =0.0;
		double s1=0.0, s2 =0.0;
		for (int i = 0; i < corr2d_tile.length; i++) {
		for (int i = 0; i < corr2d_tile.length; i++) {
@@ -488,7 +580,7 @@ public class OpticalFlow {
						}
						}
						if ((scene_tiles[iMTile] != null) && (reference_tiles[iMTile] != null)) {
						if ((scene_tiles[iMTile] != null) && (reference_tiles[iMTile] != null)) {
							if (iMTile == dbg_mtile) {
							if (iMTile == dbg_mtile) {
								System.out.println("iMTile = "+iMTile);
//								System.out.println("iMTile = "+iMTile);
							}
							}
							// convert reference tile
							// convert reference tile
							double [][][] fold_coeff_ref = dtt.get_shifted_fold_2d ( // get_shifted_fold_2d(
							double [][][] fold_coeff_ref = dtt.get_shifted_fold_2d ( // get_shifted_fold_2d(
@@ -574,7 +666,7 @@ public class OpticalFlow {
//							if ((scene_tiles[iMTile] != null) && (reference_tiles[iMTile] != null)) {
//							if ((scene_tiles[iMTile] != null) && (reference_tiles[iMTile] != null)) {
							if (true) { // !combine_empty_only  || (corr_tiles_TD[iMTile] == null)) {
							if (true) { // !combine_empty_only  || (corr_tiles_TD[iMTile] == null)) {
								if (iMTile == dbg_mtile) {
								if (iMTile == dbg_mtile) {
									System.out.println("iMTile = "+iMTile);
//									System.out.println("iMTile = "+iMTile);
								}
								}
								if ((combine_radius > 0) && (!combine_empty_only  || (corr_tiles_TD[iMTile] == null))) { // 
								if ((combine_radius > 0) && (!combine_empty_only  || (corr_tiles_TD[iMTile] == null))) { // 
									for (int q = 0; q< 4; q++) {
									for (int q = 0; q< 4; q++) {
@@ -689,7 +781,7 @@ public class OpticalFlow {
					for (int iMTile = ai.getAndIncrement(); iMTile < reference_tiles.length; iMTile = ai.getAndIncrement())
					for (int iMTile = ai.getAndIncrement(); iMTile < reference_tiles.length; iMTile = ai.getAndIncrement())
						if ((reference_tiles[iMTile] != null) && (flowXY[iMTile] != null)){
						if ((reference_tiles[iMTile] != null) && (flowXY[iMTile] != null)){
							if (iMTile == dbg_mtile) {
							if (iMTile == dbg_mtile) {
								System.out.println("iMTile = "+iMTile);
//								System.out.println("iMTile = "+iMTile);
							}
							}
							int mtileY = iMTile / macroTilesX; 
							int mtileY = iMTile / macroTilesX; 
							int mtileX = iMTile % macroTilesX;
							int mtileX = iMTile % macroTilesX;
@@ -809,6 +901,7 @@ public class OpticalFlow {
							// use offsX, offsY as fractional shift and for data interpolation
							// use offsX, offsY as fractional shift and for data interpolation
							if (offsX >= .5) offsX -= 1.0;
							if (offsX >= .5) offsX -= 1.0;
							if (offsY >= .5) offsY -= 1.0;
							if (offsY >= .5) offsY -= 1.0;
//							flowXY_frac[iMTile] = new double [] {offsX, offsY};
							flowXY_frac[iMTile] = new double [] {-offsX, -offsY};
							flowXY_frac[iMTile] = new double [] {-offsX, -offsY};
							double min_tX = Double.NaN, max_tX = Double.NaN, min_tY = Double.NaN, max_tY = Double.NaN;
							double min_tX = Double.NaN, max_tX = Double.NaN, min_tY = Double.NaN, max_tY = Double.NaN;
							for (int iY = 0; iY < fullTileSize; iY++) {
							for (int iY = 0; iY < fullTileSize; iY++) {
@@ -1090,7 +1183,7 @@ public class OpticalFlow {
			
			
			
			
		}
		}
		System.out.println("fillTilesNans() DONE.");
//		System.out.println("fillTilesNans() DONE.");
		return scene_tiles;
		return scene_tiles;
		
		
	}
	}
@@ -1435,6 +1528,64 @@ public class OpticalFlow {
		
		
	}
	}


	public void showMacroTiles(
			String title,
			double [][][][] source_tiles_sets,
			final QuadCLT qthis,
			final int     margin) // extra margins over 16x16 tiles to accommodate distorted destination tiles
	{
		final TileProcessor tp =         qthis.getTileProcessor();
		final double [][] dsrbg =        qthis.getDSRBG();
		final int tilesX =               tp.getTilesX();
		final int tilesY =               tp.getTilesY();
		final int transform_size =       tp.getTileSize();
		final int macroTilesX =          tilesX/transform_size;
		final int macroTilesY =          tilesY/transform_size;
		final int fullTileSize =         2 * (transform_size + margin);
		
		// show debug image
		final int dbg_with =   macroTilesX * (fullTileSize +1) - 1;
		final int dbg_height = macroTilesY * (fullTileSize +1) - 1;
		final double [][] dbg_img = new double [dsrbg.length * source_tiles_sets.length][dbg_with * dbg_height];
		for (int l = 0; l < dbg_img.length; l++) {
			Arrays.fill(dbg_img[l],  Double.NaN);
		}
		String [] titles = {"d", "s", "r", "b", "g"};
		String [] dsrbg_titles = new String [titles.length * source_tiles_sets.length ]; 
		
		for (int iset = 0; iset < source_tiles_sets.length; iset ++) {
			for (int l = 0; l < titles.length; l++) {
				dsrbg_titles[l * source_tiles_sets.length + iset] = titles[l]+"-"+iset;
			}
			double [][][] source_tiles = source_tiles_sets[iset];
			for (int mtile = 0; mtile < source_tiles.length; mtile++) if (source_tiles[mtile] != null){
				int mTileY = mtile / macroTilesX;
				int mTileX = mtile % macroTilesX;
				for (int iY = 0; iY < fullTileSize; iY++) {
					int tileY = (fullTileSize +1) * mTileY + iY;
					for (int iX = 0; iX < fullTileSize; iX++) {
						int tileX = (fullTileSize +1) * mTileX + iX;
						for (int l = 0; l < titles.length; l++) {
							dbg_img[l*source_tiles_sets.length + iset][tileY * dbg_with + tileX] = source_tiles[mtile][l][iY * fullTileSize + iX];
						}							
					}
				}
			}
		}
//		String [] dsrbg_titles = {"d", "s", "r", "b", "g"};
		(new ShowDoubleFloatArrays()).showArrays(
				dbg_img,
				dbg_with,
				dbg_height,
				true,
				title,
				dsrbg_titles);
		
	}
	
	
	
	
	public void showCorrTiles(
	public void showCorrTiles(
			String title,
			String title,
			double [][][] source_tiles,
			double [][][] source_tiles,
@@ -1579,19 +1730,19 @@ public class OpticalFlow {
				tolerance_absolute, // final double      tolerance_absolute, // absolute disparity half-range in each tile
				tolerance_absolute, // final double      tolerance_absolute, // absolute disparity half-range in each tile
				tolerance_relative, // final double      tolerance_relative, // relative disparity half-range in each tile
				tolerance_relative, // final double      tolerance_relative, // relative disparity half-range in each tile
				center_occupancy,   // final double      center_occupancy,   // fraction of remaining  tiles in the center 8x8 area (<1.0)
				center_occupancy,   // final double      center_occupancy,   // fraction of remaining  tiles in the center 8x8 area (<1.0)
				1); // -1); // 2); // final int         debug_level)
				-1); // -1); // 2); // final int         debug_level)
		
		
		fillTilesNans(
		fillTilesNans(
				reference_tiles,          // final double [][][] nan_tiles,
				reference_tiles,          // final double [][][] nan_tiles,
				reference_QuadCLT,                 // final QuadCLT     qthis,
				reference_QuadCLT,                 // final QuadCLT     qthis,
				num_passes,            // final int         num_passes,
				num_passes,            // final int         num_passes,
				max_change,            // final double      max_change,
				max_change,            // final double      max_change,
				1); //-1); // 2);                    // final int         debug_level)
				-1); //-1); // 2);                    // final int         debug_level)
		
		
		double [][] flowXY = new double [reference_tiles.length][2]; // zero pre-shifts
		double [][] flowXY = new double [reference_tiles.length][2]; // zero pre-shifts
		double [][] flowXY_frac = new double [reference_tiles.length][]; // Will contain fractional X/Y shift for CLT
		double [][] flowXY_frac = new double [reference_tiles.length][]; // Will contain fractional X/Y shift for CLT
		double []   chn_weights = {1.0,1.0,1.0,1.0}; // strength, r,b,g
//		double []   chn_weights = {1.0,1.0,1.0,1.0}; // strength, r,b,g
//		double []   chn_weights = {1.0,0.0,0.0,0.0}; // strength, r,b,g
		double []   chn_weights = {1.0,0.0,0.0,0.0}; // strength, r,b,g
//		double []   chn_weights = {0.0,1.0,1.0,1.0}; // strength, r,b,g
//		double []   chn_weights = {0.0,1.0,1.0,1.0}; // strength, r,b,g
		// Apply DOG to colors, normalize by standard deviation?
		// Apply DOG to colors, normalize by standard deviation?
		double      corr_sigma = 0.5;
		double      corr_sigma = 0.5;
@@ -1603,16 +1754,17 @@ public class OpticalFlow {
		double      dradius =    1.5;      // weight calculation (1/(r/dradius)^2 + 1)
		double      dradius =    1.5;      // weight calculation (1/(r/dradius)^2 + 1)
		int         refine_num = 5;   // number of iterations to apply weights around new center
		int         refine_num = 5;   // number of iterations to apply weights around new center
		int max_rad = 3;
		int max_rad = 3;
		
		boolean combine_empty_only = true; // false;
		boolean combine_empty_only = true; // false;
		double magic_scale = 0.85;
		double magic_scale = 0.85; // 2.0 * 0.85;


		boolean late_normalize_iterate = true;
		boolean late_normalize_iterate = true;
		
		
		int          num_run_all = 2; // run all tiles for few iterations before filtering
		int          num_run_all = 10; // 5; // run all tiles for few iterations before filtering
		int          max_tries =  100;
		int          max_tries =   50; // 100;
		
		
		// for recalculateFlowXY()
		// for recalculateFlowXY()
		double      min_change = 0.001;//   sqrt (dx*dx + dy*dy) for correction (int tiles)
		double      min_change = 0.01;//   sqrt (dx*dx + dy*dy) for correction (int tiles) in pixels
		
		
//		double []   abs_change = new double [reference_tiles.length]; // updated 
//		double []   abs_change = new double [reference_tiles.length]; // updated 
		int         debug_level_iterate = 1;
		int         debug_level_iterate = 1;
@@ -1689,7 +1841,28 @@ public class OpticalFlow {
				occupancy_inter,          // final double      occupancy,          // fraction of remaining  tiles (<1.0)
				occupancy_inter,          // final double      occupancy,          // fraction of remaining  tiles (<1.0)
				num_passes,               // final int         num_passes,
				num_passes,               // final int         num_passes,
				max_change,               // final double      max_change,
				max_change,               // final double      max_change,
				1); //-1); // 1); // 2);                       // final int         debug_level)
				-1); //-1); // 1); // 2);                       // final int         debug_level)

		if (debug_level > -1) {
			String dbg_title = "flowXY_frac-"+scene_QuadCLT.getImageName()+"-"+reference_QuadCLT.getImageName();
			String [] dbg_titles = {"dpX", "dpY"};
			double [][] dbg_img = new double [dbg_titles.length][macroTilesX*macroTilesY];
				Arrays.fill(dbg_img[0], Double.NaN);
				Arrays.fill(dbg_img[1], Double.NaN);
				for (int i = 0; i < flowXY_frac.length; i++) if (flowXY_frac[i] != null){
					dbg_img[0][i] = flowXY_frac[i][0];
					dbg_img[1][i] = flowXY_frac[i][1];
				}
			(new ShowDoubleFloatArrays()).showArrays(
					dbg_img,
					macroTilesX,
					macroTilesY,
					true,
					dbg_title,
					dbg_titles);
		}

		
		/* */
		/* */
		double [][][] corr2dscene_ref_multi = new double [max_rad + 2][][]; 
		double [][][] corr2dscene_ref_multi = new double [max_rad + 2][][]; 
		
		
@@ -1736,6 +1909,15 @@ public class OpticalFlow {
				tilesX/transform_size,     // int         tilesX,
				tilesX/transform_size,     // int         tilesX,
				(2 * transform_size - 1),  // int         tile_width,
				(2 * transform_size - 1),  // int         tile_width,
				(2 * transform_size - 1)); // int         tile_height) // extra margins over 16x16 tiles to accommodate distorted destination tiles
				(2 * transform_size - 1)); // int         tile_height) // extra margins over 16x16 tiles to accommodate distorted destination tiles
		//reference_tiles
		//double [][][] scene_tiles			
		double [][][][] scene_to_ref = {reference_tiles, scene_tiles};
		showMacroTiles(
				"tiles_scene-"+scene_QuadCLT.getImageName()+"-ref"+reference_QuadCLT.getImageName(),// String title,
				scene_to_ref,      // double [][][][] source_tiles_sets,
				reference_QuadCLT, // final QuadCLT qthis,
				0);                // final int     margin) // extra margins over 16x16 tiles to accommodate distorted destination tiles
		
		
		
		
		
		if (debug_level > 100) {
		if (debug_level > 100) {
@@ -1904,6 +2086,9 @@ public class OpticalFlow {
					1); //-1); // 1); // 2);                       // final int         debug_level)
					1); //-1); // 1); // 2);                       // final int         debug_level)
		}
		}
		
		
		
		
		
		return pair;
		return pair;
	}
	}