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

bug fixes, NaNs in eigen, blanking individual tiles with fpn

parent 388be26d
Loading
Loading
Loading
Loading
+28 −8
Original line number Diff line number Diff line
@@ -2753,15 +2753,21 @@ public class Correlation2d {
		}
		x0 += sx / s0; // relative to top-left
		y0 += sy / s0;
		
		//https://users.cs.utah.edu/~tch/CS4640/resources/A%20geometric%20interpretation%20of%20the%20covariance%20matrix.pdf
		double cxx = sx2 - sx * sx / s0, cyy= sy2 - sy * sy / s0, cxy = sxy - sx * sy / s0;
		if ((sx2 == 0) ||(sy2 == 0) || (cxx == 0) || (cyy == 0)){
			return null;
		}
		
		double [][] acovar =  {{cxx, cxy},{cxy,cyy}};
		// TODO: calculate for 2x2 faster?
		double [] xy = {x0-center_xy, y0-center_xy}; // relative to the center
		double [] rslt;
		if (eig_fast2x2) {
			double [] eig = getEigen2x2(acovar);
			if (eig == null) {
				return null;
			}
			rslt = new double[] {
					xy[0], // x0 - center_xy,
					xy[1], // y0 - center_xy,
@@ -2787,13 +2793,19 @@ public class Correlation2d {
					eigval[1-eig_indx]};
			if (debug){
				 double [] r = getEigen2x2(acovar);
 				 if (r!= null) {
 					 System.out.println(String.format("%10f %10f", rslt[3], r[0])); 
 					 System.out.println(String.format("%10f %10f", rslt[4], r[1])); 
 					 System.out.println(String.format("%10f %10f", rslt[5], r[2])); 
 					 System.out.println(String.format("%10f %10f", rslt[6], r[3]));
 				 } else {
 					 System.out.println("Got null from getEigen2x2()"); 
 				 }
			}
		
		}
		if (Double.isNaN(rslt[3])) {
			System.out.println("getMaxXYCmEig(): Got NaN");
		}
		
		if (debug){
			System.out.println("getMaxXYCm() -> "+rslt[0]+":"+rslt[1]+" ("+rslt[2]+
@@ -2882,10 +2894,18 @@ public class Correlation2d {
		}
		double [] lambda = {hapd-d, hapd+d};
		double [] v0 = {A[0][0] - lambda[1], A[1][0]};
		double  k = 1.0/Math.sqrt(v0[0]*v0[0] + v0[1]*v0[1]);
		double l = Math.sqrt(v0[0]*v0[0] + v0[1]*v0[1]);
		if (l==0) {
			return null;
		}
		double  k = 1.0/l;
		if (v0[0] < 0) { // to be compatible with standard?
			k = -k;
		}
		if (Double.isNaN(k) || Double.isNaN(v0[0])) {
			System.out.println("getEigen2x2(): Got NaN");
		}

		return new double [] {k*v0[0], k*v0[1], lambda[0], lambda[1]};
	}
	
+53 −6
Original line number Diff line number Diff line
@@ -3841,6 +3841,7 @@ public class Interscene {

	    boolean fpn_remove =           !fpn_disable && clt_parameters.imp.fpn_remove;
	    double  fpn_max_offset =       clt_parameters.imp.fpn_max_offset;
	    final double  fpn_min_offset = clt_parameters.imp.fpn_min_offset;
	    double  fpn_radius =           clt_parameters.imp.fpn_radius;
	    boolean fpn_ignore_border =    clt_parameters.imp.fpn_ignore_border; // only if fpn_mask != null - ignore tile if maximum touches fpn_mask
	    boolean show_tptask_ref =      false;
@@ -4193,16 +4194,14 @@ public class Interscene {
			}
		}

		double [][] fpn_offsets = null;
		if (fpn_remove) {
			fpn_offsets = getInterCorrOffsets(
		final double [][] fpn_offsets = fpn_remove ?  getInterCorrOffsets(
					fpn_max_offset, // final double   max_offset,
					tp_tasks_ref,   // final TpTask[] tp_tasks_ref,
					tp_tasks[0],       // final TpTask[] tp_tasks,
					first_scene.getNumSensors(), // final int      numSens,
					tilesX,         // final int      tilesX,
					tilesY);        // final int      tilesY);
		}
					tilesY) : null;        // final int      tilesY);
		
		// Verify offsets before running LMA, return null and reason if test fails.
		if (min_max != null) {
			double [][] offsets = getInterCorrOffsets(
@@ -4438,8 +4437,20 @@ public class Interscene {
				}
				return null;
			}
			
		}
		int nremoved = 0;
		if ((fpn_offsets != null) && (fpn_min_offset > 0)) {
			nremoved = removeFPNTiles(
					fpn_offsets,     // final double [][]   fpn_offsets,
					fpn_min_offset,  // final double        fpn_min_offset,
					coord_motion,    // final double [][][] coord_motion,
					1); // final int           offset_index)
			if (debug_level > -3) {
				System.out.println("Removed "+nremoved+
						" tiles as their peaks are too close to the FPN predicted offset (<"+fpn_min_offset+"pix");
			}
		}
		
		// optional coord_motion[1][3..4] is reserved for disparity difference and strength
		// final int                 globalDebugLevel);
		if (use3D) {//(scene_disparity_strength != null)
@@ -4823,6 +4834,42 @@ public class Interscene {
		return null;
	}
	
	public static int removeFPNTiles(
			final double [][]   fpn_offsets,
			final double        fpn_min_offset,
			final double [][][] coord_motion,
			final int           offset_index) {
		if (fpn_offsets == null) {
			return 0;
		}
		final double fpn_min_offset2 = fpn_min_offset * fpn_min_offset;
		final Thread[] threads = ImageDtt.newThreadArray(THREADS_MAX);
		final AtomicInteger ai =        new AtomicInteger(0);
		final AtomicInteger anremoved = new AtomicInteger(0);
		for (int ithread = 0; ithread < threads.length; ithread++) {
			threads[ithread] = new Thread() {
				public void run() {
					for (int nTile = ai.getAndIncrement(); nTile < fpn_offsets.length; nTile = ai.getAndIncrement()) {
						if ((fpn_offsets[nTile] != null) && (coord_motion[offset_index][nTile] != null)) {
							double dx = coord_motion[offset_index][nTile][0] - fpn_offsets[nTile][0];
							double dy = coord_motion[offset_index][nTile][1] - fpn_offsets[nTile][1];
							double l2 = dx*dx + dy*dy;
							if (l2 < fpn_min_offset2) {
								for (int i = 0; i < coord_motion.length; i++) {
									coord_motion[i][nTile] = null;
								}
								anremoved.getAndIncrement();
							}
						}
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
		return anremoved.get();
		
	}

	
	public static boolean [] getMovementMask(
			CLTParameters clt_parameters,
+22 −7
Original line number Diff line number Diff line
@@ -806,7 +806,7 @@ public class IntersceneLma {
		if (eigen == null) {
			return null;
		}
		final double [][][] transform = new double[eigen.length][2][2];
		final double [][][] transform = new double[eigen.length][][];
		final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
		final AtomicInteger ai = new AtomicInteger(0);
		final double k0 = 1.0/eig_max_sqrt;
@@ -816,6 +816,8 @@ public class IntersceneLma {
				public void run() {
					for (int iTile = ai.getAndIncrement(); iTile < eigen.length; iTile = ai.getAndIncrement()) if (eigen[iTile] != null){
						double [][] am = {{eigen[iTile][0],eigen[iTile][1]},{eigen[iTile][1],-eigen[iTile][0]}};
						if (!Double.isNaN(am[0][0]) && !Double.isNaN(am[0][1])) {
							transform[iTile] = new double [2][2];
							for (int i = 0; i < 2; i++) {
								double k = Math.max(0, 1/Math.max(eig_min_sqrt, Math.sqrt(eigen[iTile][2+i]))-k0);
								for (int j = 0; j < 2; j++) {
@@ -824,6 +826,7 @@ public class IntersceneLma {
							}
						}
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
@@ -849,8 +852,13 @@ public class IntersceneLma {
					int thread_num = ati.getAndIncrement();
					for (int iMTile = ai.getAndIncrement(); iMTile < vector_XYSDS.length; iMTile = ai.getAndIncrement()) if (vector_XYSDS[iMTile] != null){
						double w = vector_XYSDS[iMTile][2];
						if ((eig_trans != null) && (eig_trans[iMTile] == null)) {
							w = 0;
							continue;
						}
						if (Double.isNaN(w)) {
							w = 0;
							continue;
						}
						if (w > 0) {
							anum_defined.getAndIncrement();
@@ -1069,6 +1077,9 @@ public class IntersceneLma {
												jt[i][num_components * iMTile + 2] = deriv_params[indx][2]; // pY (disparity is used)
											}
										}
										if (Double.isNaN(jt[0][num_components * iMTile + 0])) {
											System.out.println("getFxDerivs(): NaN, iMTile="+iMTile);
										}
									}
								}
							} else if (mb_mode) {
@@ -1123,9 +1134,13 @@ public class IntersceneLma {
							double d = 0.0;
							for (int k = 0; k < nup_points; k++) {
								if (jt[i][k] != 0) {
									d+=0;
									d+=0; // ???
								}
								d += weights[k]*jt[i][k]*jt[j][k];
								if (Double.isNaN(d)) {
									System.out.println("getWJtJlambda(): NAN i="+i+", j="+j+", k="+k);
								}
								
							}
							wjtjl[i][j] = d;
							if (i == j) {
+7 −0
Original line number Diff line number Diff line
@@ -509,6 +509,7 @@ min_str_neib_fpn 0.35
	// Remove correlation caused by FPN
	public  boolean fpn_remove =                    true;  // only use reference DSI tiles that have LMA (strong) disparity
	public  double  fpn_max_offset =                8.0;   // pix - ignore larger FPN offsets
	public  double  fpn_min_offset =                1.8;   // pix - ignore tile if maximum differs less from fpn offset 
	public  double  fpn_radius =                    0.75;  // pix - zero around center 
	public  boolean fpn_ignore_border =             false; // only if fpn_mask != null - ignore tile if maximum touches fpn_mask
	
@@ -1461,6 +1462,8 @@ min_str_neib_fpn 0.35
				"Zero-out integrated inter-scene correlation around zero-shift offset");
		gd.addNumericField("Maximal FPN offset to consider",         this.fpn_max_offset, 6,7,"pix",
				"Maximal offset from the zero shift to consider (normally just 8 pix)");
		gd.addNumericField("Closest peak from the FPN offset",       this.fpn_min_offset, 6,7,"pix",
				"Discard tile if maximum is closer to the fpn offset");
		gd.addNumericField("FPN suppression radius",                 this.fpn_radius, 6,7,"pix",
				"Blank correlation pixels closer than this distance from the FPN offset");
		gd.addCheckbox ("Ignore maximums \"touching\" FPN",          this.fpn_ignore_border,
@@ -2119,6 +2122,7 @@ min_str_neib_fpn 0.35
		this.use_lma_dsi =              gd.getNextBoolean();
		this.fpn_remove =               gd.getNextBoolean();
		this.fpn_max_offset =           gd.getNextNumber();
		this.fpn_min_offset =           gd.getNextNumber();
		this.fpn_radius =               gd.getNextNumber();
		this.fpn_ignore_border =        gd.getNextBoolean();

@@ -2691,6 +2695,7 @@ min_str_neib_fpn 0.35
		properties.setProperty(prefix+"use_lma_dsi",          this.use_lma_dsi+"");         // boolean
		properties.setProperty(prefix+"fpn_remove",           this.fpn_remove+"");          // boolean
		properties.setProperty(prefix+"fpn_max_offset",       this.fpn_max_offset+"");      // double
		properties.setProperty(prefix+"fpn_min_offset",       this.fpn_min_offset+"");      // double
		properties.setProperty(prefix+"fpn_radius",           this.fpn_radius+"");          // double
		properties.setProperty(prefix+"fpn_ignore_border",    this.fpn_ignore_border+"");   // boolean
		
@@ -3221,6 +3226,7 @@ min_str_neib_fpn 0.35
		if (properties.getProperty(prefix+"use_lma_dsi")!=null)          this.use_lma_dsi=Boolean.parseBoolean(properties.getProperty(prefix+"use_lma_dsi"));
		if (properties.getProperty(prefix+"fpn_remove")!=null)           this.fpn_remove=Boolean.parseBoolean(properties.getProperty(prefix+"fpn_remove"));
		if (properties.getProperty(prefix+"fpn_max_offset")!=null)       this.fpn_max_offset=Double.parseDouble(properties.getProperty(prefix+"fpn_max_offset"));
		if (properties.getProperty(prefix+"fpn_min_offset")!=null)       this.fpn_min_offset=Double.parseDouble(properties.getProperty(prefix+"fpn_min_offset"));
		if (properties.getProperty(prefix+"fpn_radius")!=null)           this.fpn_radius=Double.parseDouble(properties.getProperty(prefix+"fpn_radius"));
		if (properties.getProperty(prefix+"fpn_ignore_border")!=null)    this.fpn_ignore_border=Boolean.parseBoolean(properties.getProperty(prefix+"fpn_ignore_border"));
		
@@ -3759,6 +3765,7 @@ min_str_neib_fpn 0.35
		imp.use_lma_dsi           = this.use_lma_dsi;
		imp.fpn_remove            = this.fpn_remove;
		imp.fpn_max_offset        = this.fpn_max_offset;
		imp.fpn_min_offset        = this.fpn_min_offset;
		imp.fpn_radius            = this.fpn_radius;
		imp.fpn_ignore_border     = this.fpn_ignore_border;
		
+12 −1
Original line number Diff line number Diff line
@@ -6492,19 +6492,30 @@ public class OpticalFlow {
			start_ref_pointers[0] = earliest_scene;
			start_ref_pointers[1] = ref_index;
		}
		String top_dir = quadCLTs[ref_index].getX3dTopDirectory();
		// temporary fix save/restore linkedModels, sourceDirectory, sourcePaths
		// that are copied main-> aux in EyesisCorrectionParameters.updateAuxFromMain()
		// quadCLT_main.correctionsParameters
		String bkp_linkedModels = quadCLT_main.correctionsParameters.linkedModels;
		String bkp_videoDirectory = quadCLT_main.correctionsParameters.videoDirectory;
		String bkp_x3dDirectory = quadCLT_main.correctionsParameters.x3dDirectory;
		String bkp_mlDirectory = quadCLT_main.correctionsParameters.mlDirectory;
		String bkp_sourceDirectory =  quadCLT_main.correctionsParameters.sourceDirectory;
		String [] bkp_sourcePaths =   quadCLT_main.correctionsParameters.sourcePaths;
		boolean bkp_use_set_dirs = quadCLT_main.correctionsParameters.use_set_dirs;
		quadCLTs[ref_index].saveConfInModelDirectory(); // save all (global) configurations in model/version directory
		quadCLT_main.correctionsParameters.linkedModels =    bkp_linkedModels;
		quadCLT_main.correctionsParameters.videoDirectory = bkp_videoDirectory;
		quadCLT_main.correctionsParameters.x3dDirectory = bkp_x3dDirectory;
		quadCLT_main.correctionsParameters.mlDirectory = bkp_mlDirectory;
		quadCLT_main.correctionsParameters.sourceDirectory = bkp_sourceDirectory;
		quadCLT_main.correctionsParameters.sourceDirectory = bkp_sourceDirectory;
		quadCLT_main.correctionsParameters.sourcePaths =     bkp_sourcePaths;
		quadCLT_main.correctionsParameters.use_set_dirs =    bkp_use_set_dirs;
		
		System.out.println("buildSeries(): DONE"); //
		return quadCLTs[ref_index].getX3dTopDirectory();
		String top_dir0=quadCLTs[ref_index].getX3dTopDirectory();
		return quadCLTs[ref_index].getX3dTopDirectory(); // top_dir; // 
    }
    
	public void adjustLYSeries(