Commit 5e03168f authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Fixed affine inversion

parent 0da53711
Loading
Loading
Loading
Loading
+158 −15
Original line number Diff line number Diff line
@@ -805,12 +805,26 @@ public class ComboMatch {
					int default_choice = 0;
					int num_scene_lines = 50;
					String scene_name = 	maps_collection.selectOneScene(
							0, // int num_scene,
							default_choice, // int default_choice,
							num_scene_lines); // int num_choice_lines)
					if (scene_name == null) {
						return false;
					}
					if (process_correlation) { // select a second image to match
						// select a second image and set gpu_spair
						int default_choice1 = 0;
						String scene_name1 = 	maps_collection.selectOneScene(
								1, // int num_scene,
								default_choice1, // int default_choice,
								num_scene_lines); // int num_choice_lines)
						if (scene_name1 == null) {
							return false;
						}
						gpu_spair = new String[] {scene_name, scene_name1};
					} else { // pattern match - single image
						gpu_spair = new String[] {scene_name};
					}
				} else {
					gpu_spair = new String[] {
							maps_collection.ortho_maps[available_pairs[pair][0]].getName(),
@@ -818,15 +832,19 @@ public class ComboMatch {
				}
        	}
        	int [] gpu_pair = new int[gpu_spair.length];
        	for (int i = 0; i < gpu_pair.length; i++) {
        		gpu_pair[i] = maps_collection.getIndex(gpu_spair[i]);
        	}
        	int min_zoom_lev = maps_collection.ortho_maps[gpu_pair[0]].getOriginalZoomLevel();
        	int max_zoom_lev = maps_collection.ortho_maps[gpu_pair[0]].getOriginalZoomLevel();

        	double max_agl = maps_collection.ortho_maps[gpu_pair[0]].getAGL();
        	for (int i = 0; i < gpu_pair.length; i++) {
        		gpu_pair[i] = maps_collection.getIndex(gpu_spair[i]);
        		max_agl = Math.max(max_agl, maps_collection.ortho_maps[gpu_pair[i]].getAGL());
        		min_zoom_lev = Math.min(min_zoom_lev, maps_collection.ortho_maps[gpu_pair[i]].getOriginalZoomLevel());
        		max_zoom_lev = Math.max(max_zoom_lev, maps_collection.ortho_maps[gpu_pair[i]].getOriginalZoomLevel());
        		
        	}
        	double agl_ratio = max_agl/50.0;
        	double metric_error_adj = metric_error * agl_ratio * agl_ratio; // metric_error settings is good for 50m. Increase for higher Maybe squared?
        	int initial_zoom = max_zoom_lev - 4;  // another algorithm?

        	System.out.println("Setting up GPU");
@@ -849,7 +867,7 @@ public class ComboMatch {
    		double [][] affine1 = null;

        	if (gpu_spair.length < 2) {
        		System.out.println("Selected a single image");
        		System.out.println("Selected a single image, not a pair");
    			double [][][] affines = {affine0}; // or use affine1 = null as second?
				if (pattern_match) {
					ImagePlus imp_pat_match = maps_collection.patternMatchDualWrap (
@@ -860,9 +878,23 @@ public class ComboMatch {
					//						imp_pat_match.show();
				}
        		
        	} else {
        		if (process_correlation && !use_marked_image) { // match may or may not exist
        			// if match exists - ask if use it. If not - open dialog and start spiral
        			pairwiseOrthoMatch = initialPairAdjust(
        					clt_parameters,  // CLTParameters       clt_parameters,
        					maps_collection, // OrthoMapsCollection maps_collection,
        					frac_remove,     // double              frac_remove, //  =        0.25
        					metric_error_adj,// double              metric_error,
        					gpu_spair,       // String[]            gpu_spair,
        					debugLevel);     // int                 debugLevel)
        			if (pairwiseOrthoMatch == null) { // if OK - either match existed or created by SpiralMatch()
        				return false;
        			}
        		} else {
        			pairwiseOrthoMatch = maps_collection.ortho_maps[gpu_pair[0]].getMatch(
        					maps_collection.ortho_maps[gpu_pair[1]].getName());
        		}
        		if (pairwiseOrthoMatch == null) {
        			System.out.println("No correlation data is available for pairs "+gpu_spair[0]+
        					" - "+gpu_spair[1]+" need to implement/search reverse,  a spiral search or restart command");
@@ -874,8 +906,10 @@ public class ComboMatch {
        			int [] zooms = {initial_zoom, min_zoom_lev, 1000,1000}; // make automatic
        			double scale = 2.0; // scale vectors when warping;
        			//				int num_tries  = 5; // make configurable
        			if (!process_correlation) {
        			if (!process_correlation || !use_marked_image) { // skip low-res
        				zooms = new int[] {min_zoom_lev, 1000};
        			}
        			if (!process_correlation) { // 0 LMA adjustments
        				num_tries_fit = 0;
        				update_match = false;
        			}
@@ -884,24 +918,31 @@ public class ComboMatch {
        			boolean ignore_prev_rms = true;
        			Rectangle woi = new Rectangle(); // used to return actual woi from correlateOrthoPair()
        			double [][] ground_planes = null;
					double           max_std = 1.5;      // maximal standard deviation to limit center area  
					double           min_std_rad = 2.0;  // minimal radius of the central area (if less - fail)

        			for (int zi = 0; zi < zooms.length; zi++) {
        				zoom_lev = zooms[zi];
        				if (zoom_lev >=1000) {
        					break;
        				}
        				boolean show_vf = render_match || pattern_match;
        				boolean show_vf = false; // render_match || pattern_match;
        				if (render_match || pattern_match) {
        					ground_planes = new double [gpu_pair.length][];
        				}
        				// will modify affines[1], later add jtj, weight, smth. else?
        				PairwiseOrthoMatch pmatch = process_correlation? pairwiseOrthoMatch: null;
        				FineXYCorr warp = maps_collection.correlateOrthoPair(
        						clt_parameters,  // CLTParameters    clt_parameters,
        						(process_correlation? pairwiseOrthoMatch: null), //PairwiseOrthoMatch pairwiseOrthoMatch, // will return statistics
        						0, // 			int              min_overlap,
        						max_std,         // double           max_std,      // maximal standard deviation to limit center area  
        						min_std_rad,     // double           min_std_rad,  // minimal radius of the central area (if less - fail)
        						frac_remove,     // double           frac_remove, //  =        0.25
        						metric_error,    // 			double           metric_error,
        						metric_error_adj,// 			double           metric_error,
        						ignore_prev_rms, // boolean ignore_prev_rms,
        						num_tries_fit,   //  = 5int              num_tries, //  = 5
        						true,            // boolean          calc_warp,
        						true,            // boolean          calc_warp, (will return null if false)
        						batch_mode,      // boolean          batch_mode,
        						gpu_pair,        // String []        gpu_spair,
        						affines,         // double [][][]    affines, // on top of GPS offsets
@@ -910,7 +951,7 @@ public class ComboMatch {
        						show_vf,         // boolean show_vf,
        						ground_planes,   // double [][]      ground_planes, // null or double[2] - will return ground planes
        						debugLevel);     // final int        debugLevel)
        				if (warp == null) {
        				if ((warp == null) || ((pmatch != null) &&  Double.isNaN(pmatch.rms))) {
        					System.out.println("Failed correlateOrthoPair()");
        					return false;
        				}
@@ -948,10 +989,10 @@ public class ComboMatch {
        					//						imp_pat_match.show();
        				}
        				if (render_match) {
        					String title=String.format("multi_%03d-%03d_%s-%s_zoom%d_%d",gpu_pair[0],gpu_pair[1],gpu_spair[0],gpu_spair[1],min_zoom_lev,zoom_lev);
        					ImagePlus imp_img_pair = 	maps_collection.renderMulti (
        							//_zoom<integer> is needed for opening with "Extract Objects" command
        							"multi_"+gpu_spair[0]+"-"+gpu_spair[1]+"_zoom"+min_zoom_lev+"_"+zoom_lev, // String      title,
        							//								false,             // boolean     use_alt,
        							title, // String      title,
        							OrthoMapsCollection.MODE_IMAGE,  // int           mode,    // 0 - regular image, 1 - altitudes, 2 - black/white mask       // boolean     use_alt,
        							gpu_pair,          // int []        indices, // null or which indices to use (normally just 2 for pairwise comparison)
        							bounds_to_indices, // boolean       bounds_to_indices,
@@ -978,6 +1019,98 @@ public class ComboMatch {
        }
        return true;
	}
	public static PairwiseOrthoMatch initialPairAdjust(
			CLTParameters       clt_parameters,
			OrthoMapsCollection maps_collection,
			double              frac_remove, //  =        0.25
			double              metric_error,
			String[]            gpu_spair,
			int                 debugLevel) {
    	int [] gpu_pair = new int[gpu_spair.length];
    	gpu_pair[0] = maps_collection.getIndex(gpu_spair[0]);
    	int min_zoom_lev = maps_collection.ortho_maps[gpu_pair[0]].getOriginalZoomLevel();
    	int max_zoom_lev = maps_collection.ortho_maps[gpu_pair[0]].getOriginalZoomLevel();

    	for (int i = 0; i < gpu_pair.length; i++) {
    		gpu_pair[i] = maps_collection.getIndex(gpu_spair[i]);
    		min_zoom_lev = Math.min(min_zoom_lev, maps_collection.ortho_maps[gpu_pair[i]].getOriginalZoomLevel());
    		max_zoom_lev = Math.max(max_zoom_lev, maps_collection.ortho_maps[gpu_pair[i]].getOriginalZoomLevel());
    	}
    	int initial_zoom = max_zoom_lev - 4;  // another algorithm?

		PairwiseOrthoMatch pairwiseOrthoMatch = maps_collection.ortho_maps[gpu_pair[0]].getMatch(
				maps_collection.ortho_maps[gpu_pair[1]].getName());
//		boolean has_match = pairwiseOrthoMatch != null;
		PairwiseOrthoMatch inv_match =  maps_collection.ortho_maps[gpu_pair[1]].getMatch(
				maps_collection.ortho_maps[gpu_pair[0]].getName());
		
		// dialog - ask parameters and if has_match -ask if to use it (then just return true)
		// if has inv - ask and, if yes, = create inverted as initial
		boolean use_exixting_pair =    false;
		boolean invert_exixting_pair = false;
		double search_step =           8.0; // pix
		double search_range =         50.0; // pix
		double maximal_rms =           0.25; //
		int    min_overlap =          3000; // do not try to match if there is too small overlap (scaled pixels)
		int    num_iter_lma =          5;
		GenericJTabbedDialog gd = new GenericJTabbedDialog("Setup SpiralMatch",1200,900);
		if (pairwiseOrthoMatch != null) {
			gd.addCheckbox    ("Use existing image pair",  use_exixting_pair, "Use existing affine settings for this pair, do not use spiral search.");
		}
		if (inv_match != null) {
			gd.addCheckbox    ("Invert existing image pair", invert_exixting_pair, "Invert existing image pair affine transform, do not use spiral search.");
		}
		gd.addNumericField("Spiral search step",     search_step,  3,7,"scaled pix",	"Distance between spiral search probes, in scaled pixels.");
		gd.addNumericField("Spiral search radius",   search_range, 3,7,"scaled pix",	"Maximal radius of the spiral search, in scaled pixels.");
		gd.addNumericField("Maximal RMSE",           maximal_rms,  3,7,"scaled pix",	"Maximal RMSE to consider match, in scaled pixels.");
		gd.addNumericField("Minimal overlap",        min_overlap,  0,4,"scaled pix ^ 2","Minimal overlap area in square scaled pixels.");
		gd.addNumericField("LMA iterations",         num_iter_lma, 0,2,"",              "Number of LMA iterations.");
		gd.showDialog();
		if (gd.wasCanceled()) return null;
		if (pairwiseOrthoMatch != null) {
			use_exixting_pair =    gd.getNextBoolean();
		}
		if (inv_match != null) {
			invert_exixting_pair = gd.getNextBoolean();
		}
		search_step=               gd.getNextNumber();
		search_range=              gd.getNextNumber();
		maximal_rms =              gd.getNextNumber();
		min_overlap =        (int) gd.getNextNumber();
		num_iter_lma =       (int) gd.getNextNumber();
		if (use_exixting_pair) {
			if (invert_exixting_pair) {
				System.out.println("Both direct and inverted matches are selected, using direct match");
			}
			return pairwiseOrthoMatch;
		} else if (invert_exixting_pair) {
			double [] enuOffset = maps_collection.ortho_maps[gpu_pair[0]].enuOffsetTo(maps_collection.ortho_maps[gpu_pair[1]]);
			double [] rd = {enuOffset[0], -enuOffset[1]}; // {right,down} of the image 
			// create inverted pairwiseOrthoMatch - move to PairwiseOrthoMatch
			return inv_match.getInverse(rd);
		}
		double [][] affine0 = {{1,0,0},{0,1,0}}; // will always stay the same
		double [][] affine1 = {{1,0,0},{0,1,0}}; // here (manual mode) start from the center, may use prediction in auto
		double [][][] affines = new double[][][] {affine0,affine1};

		pairwiseOrthoMatch = maps_collection.SpiralMatch (
				clt_parameters,  // CLTParameters    clt_parameters,
//				PairwiseOrthoMatch pairwiseOrthoMatch, // will return statistics, may be null if not needed
				frac_remove,     // double           frac_remove, //  =        0.25
				metric_error,    // double           metric_error,
				gpu_pair,        // int []           gpu_pair,
				affines,         // double [][][]    affines_init,  // here in meters, relative to vertical points
				initial_zoom,    // int              zoom_lev,
				search_step,     // double           pix_step,
				search_range,    // double           pix_range,
				maximal_rms,     // double           need_rms,
				num_iter_lma,    // int              num_tries, //  = 5
				min_overlap,     // int              min_overlap, // 3000
				debugLevel);    // int              debugLevel){
		return pairwiseOrthoMatch;
	}
	
	
	
	public static boolean updateBlBcFileNames(
			String suffix,
@@ -1375,7 +1508,9 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341
		// get TD interscene correlation of 2 scenes, use only combo (all channels) data
		TDCorrTile [] corr_tiles = TDCorrTile.getFromGpu(
				GPU_QUAD_AFFINE);
		double  neib_radius =      clt_parameters.imp.rln_neib_radius;;
		
// depends on zoom level		
		double  neib_radius =      clt_parameters.imp.rln_neib_radius;
		boolean rln_neibs_fill =   clt_parameters.imp.rln_neibs_fill;		
		double  rln_fat_zero =     clt_parameters.imp.rln_fat_zero;
		boolean rln_use_neibs =    clt_parameters.imp.rln_use_neibs;
@@ -1384,6 +1519,14 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341
		double  rln_sngl_rstr =    clt_parameters.imp.rln_sngl_rstr;
		double  rln_neib_rstr =    clt_parameters.imp.rln_neib_rstr;
		
		double max_neib_radius = Math.min(woi.width, woi.height)/GPUTileProcessor.DTT_SIZE * clt_parameters.imp.rln_radius_frac;
		if (neib_radius > max_neib_radius) {
			neib_radius = max_neib_radius;
		}

		
		
		
		double [][][] corr_tiles_pd = new double [(neib_radius>0)? 2: 1][][];
		// use TDCorrTile.calcNeibs() here to get 8-neighbors
		corr_tiles_pd[0] = TDCorrTile.convertTDtoPD(
+2 −0
Original line number Diff line number Diff line
@@ -3005,6 +3005,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
		}
		return true;
	}
	
	public static double [][] combineAffine(
			double [][] ref_affine,
			double [][] other_affine){
@@ -3023,6 +3024,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
	}

	
	
	/**
	 * Get planar approximation of the ground
	 * 
Loading