Loading src/main/java/com/elphel/imagej/correction/Eyesis_Correction.java +3 −1 Original line number Original line Diff line number Diff line Loading @@ -849,6 +849,7 @@ public class Eyesis_Correction implements PlugIn, ActionListener { addButton("Read Tiff", panelLWIRWorld, color_process); addButton("Read Tiff", panelLWIRWorld, color_process); addButton("Test video", panelLWIRWorld, color_process); addButton("Test video", panelLWIRWorld, color_process); addButton("Ortho Pairs", panelLWIRWorld, color_process); addButton("Ortho Pairs", panelLWIRWorld, color_process); addButton("Manual pair", panelLWIRWorld, color_process); addButton("Extract Objects", panelLWIRWorld, color_process); addButton("Extract Objects", panelLWIRWorld, color_process); addButton("Mismatched resolutions", panelLWIRWorld, color_process); addButton("Mismatched resolutions", panelLWIRWorld, color_process); addButton("Generate DATI", panelLWIRWorld, color_process); addButton("Generate DATI", panelLWIRWorld, color_process); Loading Loading @@ -5709,7 +5710,7 @@ public class Eyesis_Correction implements PlugIn, ActionListener { e.printStackTrace(); e.printStackTrace(); } } // ComboMatch.testReadTiff(); // ComboMatch.testReadTiff(); } else if (label.equals("Ortho Pairs") || label.equals("Extract Objects")) { } else if (label.equals("Ortho Pairs") || label.equals("Extract Objects") || label.equals("Manual pair")) { DEBUG_LEVEL = MASTER_DEBUG_LEVEL; DEBUG_LEVEL = MASTER_DEBUG_LEVEL; EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL); EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL); if (GPU_TILE_PROCESSOR == null) { if (GPU_TILE_PROCESSOR == null) { Loading @@ -5731,6 +5732,7 @@ public class Eyesis_Correction implements PlugIn, ActionListener { CLT_PARAMETERS, // CLTParameters clt_parameters, CLT_PARAMETERS, // CLTParameters clt_parameters, GPU_TILE_PROCESSOR, GPU_TILE_PROCESSOR, label.equals("Extract Objects"), // boolean extract_mines, label.equals("Extract Objects"), // boolean extract_mines, label.equals("Manual pair"), // boolean manual_pair, DEBUG_LEVEL); DEBUG_LEVEL); } else if (label.equals("Test video")) { } else if (label.equals("Test video")) { ImagePlus imp_sel = WindowManager.getCurrentImage(); ImagePlus imp_sel = WindowManager.getCurrentImage(); Loading src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,7 @@ public class ComboMatch { CLTParameters clt_parameters, CLTParameters clt_parameters, GPUTileProcessor gpu_tile_processor, // initialized by the caller GPUTileProcessor gpu_tile_processor, // initialized by the caller boolean extract_objects, boolean extract_objects, boolean manual_pair, int debugLevel) { int debugLevel) { boolean create_kernels = debugLevel>1000; boolean create_kernels = debugLevel>1000; if (create_kernels) { if (create_kernels) { Loading @@ -70,7 +71,7 @@ public class ComboMatch { GPU_TILE_PROCESSOR = gpu_tile_processor; GPU_TILE_PROCESSOR = gpu_tile_processor; PairwiseOrthoMatch pairwiseOrthoMatch = null; PairwiseOrthoMatch pairwiseOrthoMatch = null; String [] pair_names = new String[2]; String [] pair_names = new String[2]; ImagePlus imp_sel = WindowManager.getCurrentImage(); ImagePlus imp_sel = manual_pair? WindowManager.getCurrentImage() : null; String [] gpu_spair = null; String [] gpu_spair = null; boolean use_marked_image = false; // will be set if found boolean use_marked_image = false; // will be set if found String [] all_scenes = null; String [] all_scenes = null; Loading src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java +136 −0 Original line number Original line Diff line number Diff line Loading @@ -21,9 +21,11 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.Calendar; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.HashSet; import java.util.List; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -5230,6 +5232,19 @@ public class OrthoMapsCollection implements Serializable{ heur = (int) gd.getNextNumber(); heur = (int) gd.getNextNumber(); use_multi = gd.getNextBoolean(); use_multi = gd.getNextBoolean(); double max_rmse_reuse= max_rms_refine; double max_rmse_reuse= max_rms_refine; int [][] pairs_defined = filterPairs( indices, // int [] indices_in, min_overlap_frac, // double min_overlap_frac, max_rmse_reuse, // double max_rmse, true, // boolean max_resolution, null); // int [][] remove_pairs int [][] pairs_undefined = filterPairs( indices, // int [] indices_in, min_overlap_frac, // double min_overlap_frac, 0, // max_rmse_reuse, // double max_rmse, false, // boolean max_resolution, pairs_defined); // int [][] remove_pairs /* PairsGraph pairsGraph = new PairsGraph( PairsGraph pairsGraph = new PairsGraph( this, // OrthoMapsCollection orthoMapsCollection, this, // OrthoMapsCollection orthoMapsCollection, indices, // int [] indices, indices, // int [] indices, Loading @@ -5237,6 +5252,13 @@ public class OrthoMapsCollection implements Serializable{ max_rmse_reuse, // double max_rmse_reuse, max_rmse_reuse, // double max_rmse_reuse, use_multi, // boolean multi, use_multi, // boolean multi, debugLevel); // int debugLevel); debugLevel); // int debugLevel); */ PairsGraph pairsGraph = new PairsGraph( this, // OrthoMapsCollection orthoMapsCollection, pairs_undefined, // int [][] undefined_pairs, pairs_defined, // int [][] defined_pairs, use_multi, // boolean multi, debugLevel); // int debugLevel); if (dry_run) { if (dry_run) { return pairsGraph.dryRun( return pairsGraph.dryRun( Loading Loading @@ -6184,4 +6206,118 @@ public class OrthoMapsCollection implements Serializable{ ImageDtt.startAndJoin(threads); ImageDtt.startAndJoin(threads); return overlaps; return overlaps; } } public int [][] filterPairs( int [] indices_in, double min_overlap_frac, double max_rmse, boolean max_resolution, // require defined and full resolution int [][] remove_pairs) { if (indices_in == null) { indices_in = new int [ortho_maps.length]; for (int i = 0; i < indices_in.length; i++) { indices_in[i] = i; } } boolean [] used_scenes = new boolean [ortho_maps.length]; for (int i:indices_in) { used_scenes[i] = true; } HashSet <Point> donotuse_set = new HashSet<Point>(); if (remove_pairs != null) { for (int [] p: remove_pairs) { donotuse_set.add(new Point(p[0],p[1])); } } ArrayList<Point> pairs_list = new ArrayList<Point>(); for (int scene0:indices_in) { Set<String> match_names = ortho_maps[scene0].pairwise_matches.keySet(); ArrayList<String> names_list = new ArrayList<String>(); names_list.addAll(match_names); Collections.sort(names_list); for (String scene1_name:names_list) { PairwiseOrthoMatch match = ortho_maps[scene0].getMatch(scene1_name, !max_resolution); // may be not defined only if (match != null) { int scene1 = getIndex(scene1_name); if ( used_scenes[scene1] && (!max_resolution || match.isDefined()) && (match.getOverlap() >= min_overlap_frac) && ((max_rmse <= 0) || (match.getRMS() <= max_rmse)) ){ if (max_resolution) { int min_zoom = Math.min(ortho_maps[scene0].getOriginalZoomLevel(), ortho_maps[scene1].getOriginalZoomLevel()); if (match.getZoomLevel() < min_zoom) { continue; } } Point p = new Point(scene0, scene1); if (remove_pairs != null) { if (donotuse_set.contains(p)) { continue; } } System.out.println(String.format("%5d: %3d-%3d, %7.4f, %7.4f", pairs_list.size(), scene0, scene1, match.getOverlap(), match.getRMS())); pairs_list.add(p); } } } } int [][] pairs = new int [pairs_list.size()][2]; for (int i = 0; i < pairs.length; i++) { Point p = pairs_list.get(i); pairs[i][0] = p.x; pairs[i][1] = p.y; } return pairs; } public int [] getScenesFromPairs( int [][] pairs, int [] indices_in) { // preselected indices or null boolean [] used_scenes = new boolean [ortho_maps.length]; if (indices_in != null) { for (int i:indices_in) { used_scenes[i] = true; } } for (int [] p:pairs) { used_scenes[p[0]] = true; used_scenes[p[1]] = true; } int indx = 0; for (int i = 0; i < used_scenes.length; i++) if (used_scenes[i]){ indx++; } int [] indices = new int [indx]; indx = 0; for (int i = 0; i < used_scenes.length; i++) if (used_scenes[i]){ indices[indx++] = i; } return indices; } /** * Re-index pairs to exclude scenes not present in indices[] * @param pairs - array of start,end absolute scene numbers * @param indices - ascending array of used scenes (or null - all scenes) * @return re-indexed pairs, indices exclude scenes that are not in indices[] */ public int [][] condensePairs( int [][] pairs_all, int [] indices) { if (indices == null) { return pairs_all; } int [] reindex = new int [ortho_maps.length]; int [][] pairs = new int [pairs_all.length][2]; Arrays.fill(reindex, -1); for (int i = 0; i < indices.length; i++) { reindex[indices[i]] = i; } for (int i = 0; i < pairs.length; i++) { pairs[i][0] = reindex[pairs_all[i][0]]; pairs[i][1] = reindex[pairs_all[i][1]]; } return pairs; } } } src/main/java/com/elphel/imagej/orthomosaic/OrthoMultiLMA.java +62 −21 Original line number Original line Diff line number Diff line Loading @@ -221,6 +221,8 @@ public class OrthoMultiLMA { String orthoMapsCollection_path String orthoMapsCollection_path ) { ) { boolean all_pairs = true; boolean all_pairs = true; double min_overlap_frac = clt_parameters.imp.pwise_overlap; // 0.25; double max_rms_refine = clt_parameters.imp.pwise_max_rms; // 0.35; // boolean move_only = clt_parameters.imp.pmap_move_only; // false; boolean move_only = clt_parameters.imp.pmap_move_only; // false; boolean ignore_affines = clt_parameters.imp.pmap_ignore_affines; // false; boolean ignore_affines = clt_parameters.imp.pmap_ignore_affines; // false; boolean use_inv = clt_parameters.imp.pmap_use_inv; // false; boolean use_inv = clt_parameters.imp.pmap_use_inv; // false; Loading @@ -236,6 +238,8 @@ public class OrthoMultiLMA { GenericJTabbedDialog gd = new GenericJTabbedDialog("Pairwise Match Parameters",1200,400); GenericJTabbedDialog gd = new GenericJTabbedDialog("Pairwise Match Parameters",1200,400); gd.addCheckbox ("Use all available pairs", all_pairs, "Use all available pairs."); gd.addCheckbox ("Use all available pairs", all_pairs, "Use all available pairs."); gd.addNumericField("Minimal overlap fraction", min_overlap_frac, 3,7,"", "Minimal overlap fraction."); gd.addNumericField("Satisfactory RMSE, final", max_rms_refine,3,7,"scaled pix", "Maximal RMSE to consider match, in scaled pixels, during refine."); gd.addCheckbox ("Moves only", move_only, "Moves only, no affine transform."); gd.addCheckbox ("Moves only", move_only, "Moves only, no affine transform."); gd.addCheckbox ("Ignore existing affines", ignore_affines, "Start from unity matrices, ignore saved affines."); gd.addCheckbox ("Ignore existing affines", ignore_affines, "Start from unity matrices, ignore saved affines."); gd.addCheckbox ("Use reversed pairs", use_inv, "Use reversed (late-early timestamps) pairs."); gd.addCheckbox ("Use reversed pairs", use_inv, "Use reversed (late-early timestamps) pairs."); Loading @@ -252,6 +256,8 @@ public class OrthoMultiLMA { gd.showDialog(); gd.showDialog(); if (gd.wasCanceled()) return -1; if (gd.wasCanceled()) return -1; all_pairs = gd.getNextBoolean(); all_pairs = gd.getNextBoolean(); min_overlap_frac = gd.getNextNumber(); max_rms_refine = gd.getNextNumber(); move_only = gd.getNextBoolean(); move_only = gd.getNextBoolean(); ignore_affines = gd.getNextBoolean(); ignore_affines = gd.getNextBoolean(); use_inv = gd.getNextBoolean(); use_inv = gd.getNextBoolean(); Loading @@ -270,6 +276,10 @@ public class OrthoMultiLMA { maps_collection, // OrthoMapsCollection maps_collection, maps_collection, // OrthoMapsCollection maps_collection, orthoMapsCollection_path, // String orthoMapsCollection_path, orthoMapsCollection_path, // String orthoMapsCollection_path, all_pairs, // boolean all_pairs, all_pairs, // boolean all_pairs, // filtering of the pairs min_overlap_frac, // double min_overlap_frac, max_rms_refine, // double max_rms, move_only, // boolean move_only, move_only, // boolean move_only, ignore_affines, // boolean ignore_affines, ignore_affines, // boolean ignore_affines, use_inv, // boolean use_inv, use_inv, // boolean use_inv, Loading @@ -288,6 +298,9 @@ public class OrthoMultiLMA { OrthoMapsCollection maps_collection, OrthoMapsCollection maps_collection, String orthoMapsCollection_path, String orthoMapsCollection_path, boolean all_pairs, boolean all_pairs, double min_overlap_frac, double max_rms, boolean move_only, boolean move_only, boolean ignore_affines, boolean ignore_affines, boolean use_inv, boolean use_inv, Loading @@ -304,6 +317,7 @@ public class OrthoMultiLMA { boolean corr_avg= (skew_pull > 0) || (tilt_pull > 0) || (scale_pull > 0); boolean corr_avg= (skew_pull > 0) || (tilt_pull > 0) || (scale_pull > 0); int [] indices = null; int [] indices = null; if (all_pairs) { if (all_pairs) { /* boolean [] used_scenes = new boolean [maps_collection.ortho_maps.length]; boolean [] used_scenes = new boolean [maps_collection.ortho_maps.length]; for (int scene0 = 0; scene0 < (used_scenes.length-1); scene0++) { for (int scene0 = 0; scene0 < (used_scenes.length-1); scene0++) { Set<String> match_names = maps_collection.ortho_maps[scene0].pairwise_matches.keySet(); Set<String> match_names = maps_collection.ortho_maps[scene0].pairwise_matches.keySet(); Loading @@ -328,11 +342,25 @@ public class OrthoMultiLMA { if (debugLevel > -1) { if (debugLevel > -1) { System.out.println("buildOrthoMap(): got "+indices.length+" scenes with pairs"); System.out.println("buildOrthoMap(): got "+indices.length+" scenes with pairs"); } } */ } else { } else { indices = maps_collection.getScenesSelection( indices = maps_collection.getScenesSelection( null, // boolean select_all, null, // boolean select_all, " to build a map with LMA from pair-wise matches"); // String purpose) " to build a map with LMA from pair-wise matches"); // String purpose) } } int [][] pairs_defined_abs = maps_collection.filterPairs( // absolute indices indices, // int [] indices_in, min_overlap_frac, // double min_overlap_frac, max_rms, // double max_rmse, true, // boolean max_resolution, null); // int [][] remove_pairs indices= maps_collection.getScenesFromPairs( pairs_defined_abs,// int [][] pairs, null); // int [] indices_in) // preselected indices or null int [][] defined_pairs = maps_collection.condensePairs (pairs_defined_abs,indices); OrthoMultiLMA oml = new OrthoMultiLMA( OrthoMultiLMA oml = new OrthoMultiLMA( corr_avg, corr_avg, move_only); move_only); Loading @@ -345,6 +373,7 @@ public class OrthoMultiLMA { clt_parameters, // CLTParameters clt_parameters, clt_parameters, // CLTParameters clt_parameters, maps_collection, // OrthoMapsCollection maps_collection, maps_collection, // OrthoMapsCollection maps_collection, indices, // int [] indices, indices, // int [] indices, defined_pairs, // int [][] pairs, // or null? condensed ignore_affines, // boolean ignore_affines, ignore_affines, // boolean ignore_affines, val_coord, // double [] val_coord, // 1 - valid, 0 - invalid, minimize coordinates errors val_coord, // double [] val_coord, // 1 - valid, 0 - invalid, minimize coordinates errors position_pull, // double position_pull, position_pull, // double position_pull, Loading Loading @@ -442,6 +471,7 @@ public class OrthoMultiLMA { CLTParameters clt_parameters, CLTParameters clt_parameters, OrthoMapsCollection maps_collection, OrthoMapsCollection maps_collection, int [] indices, int [] indices, int [][] pairs_pre, // or null? boolean ignore_affines, boolean ignore_affines, double [] val_coord, // 1 - valid, 0 - invalid, minimize coordinates errors double [] val_coord, // 1 - valid, 0 - invalid, minimize coordinates errors double position_pull, double position_pull, Loading @@ -456,6 +486,16 @@ public class OrthoMultiLMA { matches = new PairwiseOrthoMatch[indices.length][indices.length]; matches = new PairwiseOrthoMatch[indices.length][indices.length]; ArrayList<Point> pairs_list = new ArrayList<Point>(); ArrayList<Point> pairs_list = new ArrayList<Point>(); // ArrayList<Double> offset_list = new ArrayList<Double>(); // ArrayList<Double> offset_list = new ArrayList<Double>(); if (pairs_pre != null) { for (int [] pair:pairs_pre) { int i = pair[0], j = pair[1]; int scene0=indices[i],scene1=indices[j]; PairwiseOrthoMatch match = maps_collection.ortho_maps[scene0].getMatch(maps_collection.ortho_maps[scene1].getName()); matches[i][j] = match; // matches[j][i] = inv_match; pairs_list.add(new Point(i,j)); // only once? } } else { for (int i = 0; i < num_scenes-1; i++) { for (int i = 0; i < num_scenes-1; i++) { int scene0 = indices[i]; int scene0 = indices[i]; for (int j = i+1; j < num_scenes; j++){ for (int j = i+1; j < num_scenes; j++){ Loading @@ -482,6 +522,7 @@ public class OrthoMultiLMA { } } } } } } } num_pairs = pairs_list.size(); num_pairs = pairs_list.size(); offsets = new double [num_pairs][2]; offsets = new double [num_pairs][2]; pairs = new int[num_pairs][2]; pairs = new int[num_pairs][2]; Loading src/main/java/com/elphel/imagej/orthomosaic/PairsGraph.java +45 −0 Original line number Original line Diff line number Diff line Loading @@ -54,6 +54,7 @@ public class PairsGraph { private final int debugLevel; private final int debugLevel; private boolean multi; // use single-threaded in debug mode? private boolean multi; // use single-threaded in debug mode? public PairsGraph ( public PairsGraph ( OrthoMapsCollection orthoMapsCollection, OrthoMapsCollection orthoMapsCollection, int [] indices, int [] indices, Loading Loading @@ -121,6 +122,50 @@ public class PairsGraph { } } } } public PairsGraph ( OrthoMapsCollection orthoMapsCollection, int [][] undefined_pairs_all, // indices in orthoMapsCollection.ortho_maps[] (all scenes, not just selected) int [][] defined_pairs_all, // indices in orthoMapsCollection.ortho_maps[] (all scenes, not just selected) boolean multi, int debugLevel) { this.orthoMapsCollection = orthoMapsCollection; int [] indices0 = orthoMapsCollection.getScenesFromPairs(undefined_pairs_all, null); this.indices = orthoMapsCollection.getScenesFromPairs(defined_pairs_all, indices0); int [][] undefined_pairs = orthoMapsCollection.condensePairs (undefined_pairs_all,indices); int [][] defined_pairs = orthoMapsCollection.condensePairs (defined_pairs_all,indices); this.debugLevel = debugLevel; this.multi = multi; pair_state = new int [indices.length][indices.length]; overlaps = new double [indices.length][indices.length]; timestamps = new double [indices.length]; groups = new int [indices.length]; dist = new int [indices.length][indices.length]; OrthoMap [] ortho_maps=orthoMapsCollection.getMaps(); for (int i = 0; i < indices.length; i++) { groups[i] = i; timestamps[i] = ortho_maps[indices[i]].getTimeStamp(); } for (int [] u_pair: undefined_pairs) { pair_state[u_pair[0]][u_pair[0]] = PAIR_UNDEFINED; } for (int [] d_pair: defined_pairs) { pair_state[d_pair[0]][d_pair[0]] = PAIR_DEFINED; recordPair( d_pair, // int [] pair, true, // boolean success, multi); } pairs = multi? getPairsIndicesMulti():getPairsIndicesSingle(); if (debugLevel > -1) { System.out.println("Number of scenes - "+indices.length); System.out.println("Number of defined pairs - "+defined_pairs.length); System.out.println("Number of undefined pairs - "+undefined_pairs.length); System.out.println("Number of disconnected groups - "+getNumberOfGroups()); } } public int getNumberOfGroups() { public int getNumberOfGroups() { HashSet<Integer> hs = new HashSet<Integer>(); HashSet<Integer> hs = new HashSet<Integer>(); for (int i:groups) { for (int i:groups) { Loading Loading
src/main/java/com/elphel/imagej/correction/Eyesis_Correction.java +3 −1 Original line number Original line Diff line number Diff line Loading @@ -849,6 +849,7 @@ public class Eyesis_Correction implements PlugIn, ActionListener { addButton("Read Tiff", panelLWIRWorld, color_process); addButton("Read Tiff", panelLWIRWorld, color_process); addButton("Test video", panelLWIRWorld, color_process); addButton("Test video", panelLWIRWorld, color_process); addButton("Ortho Pairs", panelLWIRWorld, color_process); addButton("Ortho Pairs", panelLWIRWorld, color_process); addButton("Manual pair", panelLWIRWorld, color_process); addButton("Extract Objects", panelLWIRWorld, color_process); addButton("Extract Objects", panelLWIRWorld, color_process); addButton("Mismatched resolutions", panelLWIRWorld, color_process); addButton("Mismatched resolutions", panelLWIRWorld, color_process); addButton("Generate DATI", panelLWIRWorld, color_process); addButton("Generate DATI", panelLWIRWorld, color_process); Loading Loading @@ -5709,7 +5710,7 @@ public class Eyesis_Correction implements PlugIn, ActionListener { e.printStackTrace(); e.printStackTrace(); } } // ComboMatch.testReadTiff(); // ComboMatch.testReadTiff(); } else if (label.equals("Ortho Pairs") || label.equals("Extract Objects")) { } else if (label.equals("Ortho Pairs") || label.equals("Extract Objects") || label.equals("Manual pair")) { DEBUG_LEVEL = MASTER_DEBUG_LEVEL; DEBUG_LEVEL = MASTER_DEBUG_LEVEL; EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL); EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL); if (GPU_TILE_PROCESSOR == null) { if (GPU_TILE_PROCESSOR == null) { Loading @@ -5731,6 +5732,7 @@ public class Eyesis_Correction implements PlugIn, ActionListener { CLT_PARAMETERS, // CLTParameters clt_parameters, CLT_PARAMETERS, // CLTParameters clt_parameters, GPU_TILE_PROCESSOR, GPU_TILE_PROCESSOR, label.equals("Extract Objects"), // boolean extract_mines, label.equals("Extract Objects"), // boolean extract_mines, label.equals("Manual pair"), // boolean manual_pair, DEBUG_LEVEL); DEBUG_LEVEL); } else if (label.equals("Test video")) { } else if (label.equals("Test video")) { ImagePlus imp_sel = WindowManager.getCurrentImage(); ImagePlus imp_sel = WindowManager.getCurrentImage(); Loading
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,7 @@ public class ComboMatch { CLTParameters clt_parameters, CLTParameters clt_parameters, GPUTileProcessor gpu_tile_processor, // initialized by the caller GPUTileProcessor gpu_tile_processor, // initialized by the caller boolean extract_objects, boolean extract_objects, boolean manual_pair, int debugLevel) { int debugLevel) { boolean create_kernels = debugLevel>1000; boolean create_kernels = debugLevel>1000; if (create_kernels) { if (create_kernels) { Loading @@ -70,7 +71,7 @@ public class ComboMatch { GPU_TILE_PROCESSOR = gpu_tile_processor; GPU_TILE_PROCESSOR = gpu_tile_processor; PairwiseOrthoMatch pairwiseOrthoMatch = null; PairwiseOrthoMatch pairwiseOrthoMatch = null; String [] pair_names = new String[2]; String [] pair_names = new String[2]; ImagePlus imp_sel = WindowManager.getCurrentImage(); ImagePlus imp_sel = manual_pair? WindowManager.getCurrentImage() : null; String [] gpu_spair = null; String [] gpu_spair = null; boolean use_marked_image = false; // will be set if found boolean use_marked_image = false; // will be set if found String [] all_scenes = null; String [] all_scenes = null; Loading
src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java +136 −0 Original line number Original line Diff line number Diff line Loading @@ -21,9 +21,11 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.Calendar; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.HashSet; import java.util.List; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -5230,6 +5232,19 @@ public class OrthoMapsCollection implements Serializable{ heur = (int) gd.getNextNumber(); heur = (int) gd.getNextNumber(); use_multi = gd.getNextBoolean(); use_multi = gd.getNextBoolean(); double max_rmse_reuse= max_rms_refine; double max_rmse_reuse= max_rms_refine; int [][] pairs_defined = filterPairs( indices, // int [] indices_in, min_overlap_frac, // double min_overlap_frac, max_rmse_reuse, // double max_rmse, true, // boolean max_resolution, null); // int [][] remove_pairs int [][] pairs_undefined = filterPairs( indices, // int [] indices_in, min_overlap_frac, // double min_overlap_frac, 0, // max_rmse_reuse, // double max_rmse, false, // boolean max_resolution, pairs_defined); // int [][] remove_pairs /* PairsGraph pairsGraph = new PairsGraph( PairsGraph pairsGraph = new PairsGraph( this, // OrthoMapsCollection orthoMapsCollection, this, // OrthoMapsCollection orthoMapsCollection, indices, // int [] indices, indices, // int [] indices, Loading @@ -5237,6 +5252,13 @@ public class OrthoMapsCollection implements Serializable{ max_rmse_reuse, // double max_rmse_reuse, max_rmse_reuse, // double max_rmse_reuse, use_multi, // boolean multi, use_multi, // boolean multi, debugLevel); // int debugLevel); debugLevel); // int debugLevel); */ PairsGraph pairsGraph = new PairsGraph( this, // OrthoMapsCollection orthoMapsCollection, pairs_undefined, // int [][] undefined_pairs, pairs_defined, // int [][] defined_pairs, use_multi, // boolean multi, debugLevel); // int debugLevel); if (dry_run) { if (dry_run) { return pairsGraph.dryRun( return pairsGraph.dryRun( Loading Loading @@ -6184,4 +6206,118 @@ public class OrthoMapsCollection implements Serializable{ ImageDtt.startAndJoin(threads); ImageDtt.startAndJoin(threads); return overlaps; return overlaps; } } public int [][] filterPairs( int [] indices_in, double min_overlap_frac, double max_rmse, boolean max_resolution, // require defined and full resolution int [][] remove_pairs) { if (indices_in == null) { indices_in = new int [ortho_maps.length]; for (int i = 0; i < indices_in.length; i++) { indices_in[i] = i; } } boolean [] used_scenes = new boolean [ortho_maps.length]; for (int i:indices_in) { used_scenes[i] = true; } HashSet <Point> donotuse_set = new HashSet<Point>(); if (remove_pairs != null) { for (int [] p: remove_pairs) { donotuse_set.add(new Point(p[0],p[1])); } } ArrayList<Point> pairs_list = new ArrayList<Point>(); for (int scene0:indices_in) { Set<String> match_names = ortho_maps[scene0].pairwise_matches.keySet(); ArrayList<String> names_list = new ArrayList<String>(); names_list.addAll(match_names); Collections.sort(names_list); for (String scene1_name:names_list) { PairwiseOrthoMatch match = ortho_maps[scene0].getMatch(scene1_name, !max_resolution); // may be not defined only if (match != null) { int scene1 = getIndex(scene1_name); if ( used_scenes[scene1] && (!max_resolution || match.isDefined()) && (match.getOverlap() >= min_overlap_frac) && ((max_rmse <= 0) || (match.getRMS() <= max_rmse)) ){ if (max_resolution) { int min_zoom = Math.min(ortho_maps[scene0].getOriginalZoomLevel(), ortho_maps[scene1].getOriginalZoomLevel()); if (match.getZoomLevel() < min_zoom) { continue; } } Point p = new Point(scene0, scene1); if (remove_pairs != null) { if (donotuse_set.contains(p)) { continue; } } System.out.println(String.format("%5d: %3d-%3d, %7.4f, %7.4f", pairs_list.size(), scene0, scene1, match.getOverlap(), match.getRMS())); pairs_list.add(p); } } } } int [][] pairs = new int [pairs_list.size()][2]; for (int i = 0; i < pairs.length; i++) { Point p = pairs_list.get(i); pairs[i][0] = p.x; pairs[i][1] = p.y; } return pairs; } public int [] getScenesFromPairs( int [][] pairs, int [] indices_in) { // preselected indices or null boolean [] used_scenes = new boolean [ortho_maps.length]; if (indices_in != null) { for (int i:indices_in) { used_scenes[i] = true; } } for (int [] p:pairs) { used_scenes[p[0]] = true; used_scenes[p[1]] = true; } int indx = 0; for (int i = 0; i < used_scenes.length; i++) if (used_scenes[i]){ indx++; } int [] indices = new int [indx]; indx = 0; for (int i = 0; i < used_scenes.length; i++) if (used_scenes[i]){ indices[indx++] = i; } return indices; } /** * Re-index pairs to exclude scenes not present in indices[] * @param pairs - array of start,end absolute scene numbers * @param indices - ascending array of used scenes (or null - all scenes) * @return re-indexed pairs, indices exclude scenes that are not in indices[] */ public int [][] condensePairs( int [][] pairs_all, int [] indices) { if (indices == null) { return pairs_all; } int [] reindex = new int [ortho_maps.length]; int [][] pairs = new int [pairs_all.length][2]; Arrays.fill(reindex, -1); for (int i = 0; i < indices.length; i++) { reindex[indices[i]] = i; } for (int i = 0; i < pairs.length; i++) { pairs[i][0] = reindex[pairs_all[i][0]]; pairs[i][1] = reindex[pairs_all[i][1]]; } return pairs; } } }
src/main/java/com/elphel/imagej/orthomosaic/OrthoMultiLMA.java +62 −21 Original line number Original line Diff line number Diff line Loading @@ -221,6 +221,8 @@ public class OrthoMultiLMA { String orthoMapsCollection_path String orthoMapsCollection_path ) { ) { boolean all_pairs = true; boolean all_pairs = true; double min_overlap_frac = clt_parameters.imp.pwise_overlap; // 0.25; double max_rms_refine = clt_parameters.imp.pwise_max_rms; // 0.35; // boolean move_only = clt_parameters.imp.pmap_move_only; // false; boolean move_only = clt_parameters.imp.pmap_move_only; // false; boolean ignore_affines = clt_parameters.imp.pmap_ignore_affines; // false; boolean ignore_affines = clt_parameters.imp.pmap_ignore_affines; // false; boolean use_inv = clt_parameters.imp.pmap_use_inv; // false; boolean use_inv = clt_parameters.imp.pmap_use_inv; // false; Loading @@ -236,6 +238,8 @@ public class OrthoMultiLMA { GenericJTabbedDialog gd = new GenericJTabbedDialog("Pairwise Match Parameters",1200,400); GenericJTabbedDialog gd = new GenericJTabbedDialog("Pairwise Match Parameters",1200,400); gd.addCheckbox ("Use all available pairs", all_pairs, "Use all available pairs."); gd.addCheckbox ("Use all available pairs", all_pairs, "Use all available pairs."); gd.addNumericField("Minimal overlap fraction", min_overlap_frac, 3,7,"", "Minimal overlap fraction."); gd.addNumericField("Satisfactory RMSE, final", max_rms_refine,3,7,"scaled pix", "Maximal RMSE to consider match, in scaled pixels, during refine."); gd.addCheckbox ("Moves only", move_only, "Moves only, no affine transform."); gd.addCheckbox ("Moves only", move_only, "Moves only, no affine transform."); gd.addCheckbox ("Ignore existing affines", ignore_affines, "Start from unity matrices, ignore saved affines."); gd.addCheckbox ("Ignore existing affines", ignore_affines, "Start from unity matrices, ignore saved affines."); gd.addCheckbox ("Use reversed pairs", use_inv, "Use reversed (late-early timestamps) pairs."); gd.addCheckbox ("Use reversed pairs", use_inv, "Use reversed (late-early timestamps) pairs."); Loading @@ -252,6 +256,8 @@ public class OrthoMultiLMA { gd.showDialog(); gd.showDialog(); if (gd.wasCanceled()) return -1; if (gd.wasCanceled()) return -1; all_pairs = gd.getNextBoolean(); all_pairs = gd.getNextBoolean(); min_overlap_frac = gd.getNextNumber(); max_rms_refine = gd.getNextNumber(); move_only = gd.getNextBoolean(); move_only = gd.getNextBoolean(); ignore_affines = gd.getNextBoolean(); ignore_affines = gd.getNextBoolean(); use_inv = gd.getNextBoolean(); use_inv = gd.getNextBoolean(); Loading @@ -270,6 +276,10 @@ public class OrthoMultiLMA { maps_collection, // OrthoMapsCollection maps_collection, maps_collection, // OrthoMapsCollection maps_collection, orthoMapsCollection_path, // String orthoMapsCollection_path, orthoMapsCollection_path, // String orthoMapsCollection_path, all_pairs, // boolean all_pairs, all_pairs, // boolean all_pairs, // filtering of the pairs min_overlap_frac, // double min_overlap_frac, max_rms_refine, // double max_rms, move_only, // boolean move_only, move_only, // boolean move_only, ignore_affines, // boolean ignore_affines, ignore_affines, // boolean ignore_affines, use_inv, // boolean use_inv, use_inv, // boolean use_inv, Loading @@ -288,6 +298,9 @@ public class OrthoMultiLMA { OrthoMapsCollection maps_collection, OrthoMapsCollection maps_collection, String orthoMapsCollection_path, String orthoMapsCollection_path, boolean all_pairs, boolean all_pairs, double min_overlap_frac, double max_rms, boolean move_only, boolean move_only, boolean ignore_affines, boolean ignore_affines, boolean use_inv, boolean use_inv, Loading @@ -304,6 +317,7 @@ public class OrthoMultiLMA { boolean corr_avg= (skew_pull > 0) || (tilt_pull > 0) || (scale_pull > 0); boolean corr_avg= (skew_pull > 0) || (tilt_pull > 0) || (scale_pull > 0); int [] indices = null; int [] indices = null; if (all_pairs) { if (all_pairs) { /* boolean [] used_scenes = new boolean [maps_collection.ortho_maps.length]; boolean [] used_scenes = new boolean [maps_collection.ortho_maps.length]; for (int scene0 = 0; scene0 < (used_scenes.length-1); scene0++) { for (int scene0 = 0; scene0 < (used_scenes.length-1); scene0++) { Set<String> match_names = maps_collection.ortho_maps[scene0].pairwise_matches.keySet(); Set<String> match_names = maps_collection.ortho_maps[scene0].pairwise_matches.keySet(); Loading @@ -328,11 +342,25 @@ public class OrthoMultiLMA { if (debugLevel > -1) { if (debugLevel > -1) { System.out.println("buildOrthoMap(): got "+indices.length+" scenes with pairs"); System.out.println("buildOrthoMap(): got "+indices.length+" scenes with pairs"); } } */ } else { } else { indices = maps_collection.getScenesSelection( indices = maps_collection.getScenesSelection( null, // boolean select_all, null, // boolean select_all, " to build a map with LMA from pair-wise matches"); // String purpose) " to build a map with LMA from pair-wise matches"); // String purpose) } } int [][] pairs_defined_abs = maps_collection.filterPairs( // absolute indices indices, // int [] indices_in, min_overlap_frac, // double min_overlap_frac, max_rms, // double max_rmse, true, // boolean max_resolution, null); // int [][] remove_pairs indices= maps_collection.getScenesFromPairs( pairs_defined_abs,// int [][] pairs, null); // int [] indices_in) // preselected indices or null int [][] defined_pairs = maps_collection.condensePairs (pairs_defined_abs,indices); OrthoMultiLMA oml = new OrthoMultiLMA( OrthoMultiLMA oml = new OrthoMultiLMA( corr_avg, corr_avg, move_only); move_only); Loading @@ -345,6 +373,7 @@ public class OrthoMultiLMA { clt_parameters, // CLTParameters clt_parameters, clt_parameters, // CLTParameters clt_parameters, maps_collection, // OrthoMapsCollection maps_collection, maps_collection, // OrthoMapsCollection maps_collection, indices, // int [] indices, indices, // int [] indices, defined_pairs, // int [][] pairs, // or null? condensed ignore_affines, // boolean ignore_affines, ignore_affines, // boolean ignore_affines, val_coord, // double [] val_coord, // 1 - valid, 0 - invalid, minimize coordinates errors val_coord, // double [] val_coord, // 1 - valid, 0 - invalid, minimize coordinates errors position_pull, // double position_pull, position_pull, // double position_pull, Loading Loading @@ -442,6 +471,7 @@ public class OrthoMultiLMA { CLTParameters clt_parameters, CLTParameters clt_parameters, OrthoMapsCollection maps_collection, OrthoMapsCollection maps_collection, int [] indices, int [] indices, int [][] pairs_pre, // or null? boolean ignore_affines, boolean ignore_affines, double [] val_coord, // 1 - valid, 0 - invalid, minimize coordinates errors double [] val_coord, // 1 - valid, 0 - invalid, minimize coordinates errors double position_pull, double position_pull, Loading @@ -456,6 +486,16 @@ public class OrthoMultiLMA { matches = new PairwiseOrthoMatch[indices.length][indices.length]; matches = new PairwiseOrthoMatch[indices.length][indices.length]; ArrayList<Point> pairs_list = new ArrayList<Point>(); ArrayList<Point> pairs_list = new ArrayList<Point>(); // ArrayList<Double> offset_list = new ArrayList<Double>(); // ArrayList<Double> offset_list = new ArrayList<Double>(); if (pairs_pre != null) { for (int [] pair:pairs_pre) { int i = pair[0], j = pair[1]; int scene0=indices[i],scene1=indices[j]; PairwiseOrthoMatch match = maps_collection.ortho_maps[scene0].getMatch(maps_collection.ortho_maps[scene1].getName()); matches[i][j] = match; // matches[j][i] = inv_match; pairs_list.add(new Point(i,j)); // only once? } } else { for (int i = 0; i < num_scenes-1; i++) { for (int i = 0; i < num_scenes-1; i++) { int scene0 = indices[i]; int scene0 = indices[i]; for (int j = i+1; j < num_scenes; j++){ for (int j = i+1; j < num_scenes; j++){ Loading @@ -482,6 +522,7 @@ public class OrthoMultiLMA { } } } } } } } num_pairs = pairs_list.size(); num_pairs = pairs_list.size(); offsets = new double [num_pairs][2]; offsets = new double [num_pairs][2]; pairs = new int[num_pairs][2]; pairs = new int[num_pairs][2]; Loading
src/main/java/com/elphel/imagej/orthomosaic/PairsGraph.java +45 −0 Original line number Original line Diff line number Diff line Loading @@ -54,6 +54,7 @@ public class PairsGraph { private final int debugLevel; private final int debugLevel; private boolean multi; // use single-threaded in debug mode? private boolean multi; // use single-threaded in debug mode? public PairsGraph ( public PairsGraph ( OrthoMapsCollection orthoMapsCollection, OrthoMapsCollection orthoMapsCollection, int [] indices, int [] indices, Loading Loading @@ -121,6 +122,50 @@ public class PairsGraph { } } } } public PairsGraph ( OrthoMapsCollection orthoMapsCollection, int [][] undefined_pairs_all, // indices in orthoMapsCollection.ortho_maps[] (all scenes, not just selected) int [][] defined_pairs_all, // indices in orthoMapsCollection.ortho_maps[] (all scenes, not just selected) boolean multi, int debugLevel) { this.orthoMapsCollection = orthoMapsCollection; int [] indices0 = orthoMapsCollection.getScenesFromPairs(undefined_pairs_all, null); this.indices = orthoMapsCollection.getScenesFromPairs(defined_pairs_all, indices0); int [][] undefined_pairs = orthoMapsCollection.condensePairs (undefined_pairs_all,indices); int [][] defined_pairs = orthoMapsCollection.condensePairs (defined_pairs_all,indices); this.debugLevel = debugLevel; this.multi = multi; pair_state = new int [indices.length][indices.length]; overlaps = new double [indices.length][indices.length]; timestamps = new double [indices.length]; groups = new int [indices.length]; dist = new int [indices.length][indices.length]; OrthoMap [] ortho_maps=orthoMapsCollection.getMaps(); for (int i = 0; i < indices.length; i++) { groups[i] = i; timestamps[i] = ortho_maps[indices[i]].getTimeStamp(); } for (int [] u_pair: undefined_pairs) { pair_state[u_pair[0]][u_pair[0]] = PAIR_UNDEFINED; } for (int [] d_pair: defined_pairs) { pair_state[d_pair[0]][d_pair[0]] = PAIR_DEFINED; recordPair( d_pair, // int [] pair, true, // boolean success, multi); } pairs = multi? getPairsIndicesMulti():getPairsIndicesSingle(); if (debugLevel > -1) { System.out.println("Number of scenes - "+indices.length); System.out.println("Number of defined pairs - "+defined_pairs.length); System.out.println("Number of undefined pairs - "+undefined_pairs.length); System.out.println("Number of disconnected groups - "+getNumberOfGroups()); } } public int getNumberOfGroups() { public int getNumberOfGroups() { HashSet<Integer> hs = new HashSet<Integer>(); HashSet<Integer> hs = new HashSet<Integer>(); for (int i:groups) { for (int i:groups) { Loading