Loading src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +2 −0 Original line number Diff line number Diff line Loading @@ -1303,6 +1303,8 @@ public class ComboMatch { System.out.println("This can happen if files have different resolution for new run."); System.out.println("Verify path, then modify filenames[i], break at line above: 'maps_collection.ortho_maps[i].setFileName(filenames[i])'."); System.out.println("Reduce i by 1 and continue"); } else { maps_collection.ortho_maps[i] = new OrthoMap(path); } } return true; Loading src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java +23 −8 Original line number Diff line number Diff line Loading @@ -913,6 +913,10 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ int swidth = getWidth(); int sheight = getHeight(); final float [] spix = orig_image.data; if (swidth*sheight != spix.length) { System.out.println ("downScaleForGPU(): swidth="+ swidth+", sheight="+sheight+", swidth*sheight="+(swidth*sheight)+", spix.length="+spix.length); System.out.println (); } final int width = (swidth+frscale-1)/frscale; final int height = (sheight+frscale-1)/frscale; final int tiles = width * height; Loading @@ -939,17 +943,28 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ for (int py = 0; py < tileH; py++) { int ls = (tileY*frscale + py)*swidth; for (int px = 0; px < tileW; px++) { double d = spix[ls + tileX*frscale+px]; int indx = ls + tileX*frscale+px; if ((indx >=0) && (indx < spix.length)) { double d = spix[ls + tileX*frscale+px]; //java.lang.ArrayIndexOutOfBoundsException: Index 3892800 out of bounds for length 3892680 if (!Double.isNaN(d)) { double w = wnd[py][px]; sw += w; swd += w*d; } if (sw > 0) { opix[tileY * width + tileX] = (float) (swd/sw); } else { System.out.println("downScaleForGPU(): indx = "+indx+" ("+spix.length+"), tileX= "+ tileX+", tileY="+tileY+", px="+px+", py="+py+", ls="+ls); } // if (sw > 0) { // opix[tileY * width + tileX] = (float) (swd/sw); // } } } if (sw > 0) { opix[tileY * width + tileX] = (float) (swd/sw); } } } }; Loading src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java +326 −465 File changed.Preview size limit exceeded, changes collapsed. Show changes src/main/java/com/elphel/imagej/orthomosaic/OrthoMultiLMA.java +43 −9 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ import java.awt.Point; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import com.elphel.imagej.cameras.CLTParameters; Loading Loading @@ -218,6 +220,7 @@ public class OrthoMultiLMA { OrthoMapsCollection maps_collection, String orthoMapsCollection_path ) { boolean all_pairs = true; boolean move_only = clt_parameters.imp.pmap_move_only; // false; boolean ignore_affines = clt_parameters.imp.pmap_ignore_affines; // false; boolean use_inv = clt_parameters.imp.pmap_use_inv; // false; Loading @@ -232,22 +235,23 @@ public class OrthoMultiLMA { int debugLevel = clt_parameters.imp.pmap_debugLevel; // 2; GenericJTabbedDialog gd = new GenericJTabbedDialog("Pairwise Match Parameters",1200,400); gd.addCheckbox ("Use all available pairs", all_pairs, "Use all available pairs."); 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 ("Use reversed pairs", use_inv, "Use reversed (late-early timestamps) pairs."); gd.addNumericField("Skew pull", skew_pull, 7,10,"", "Intention to have axes perpendicular."); gd.addNumericField("Tilt pull", tilt_pull, 7,10,"", "Intention to have axes same length."); gd.addNumericField("Scale pull", scale_pull, 7,10,"", "Intention to have average scale of images = 1.0."); gd.addNumericField("Position pull", position_pull,7,10,"", "Intension to match IMS (GNSS) coordinates."); gd.addNumericField("Skew pull", skew_pull, 7,11,"", "Intention to have axes perpendicular."); gd.addNumericField("Tilt pull", tilt_pull, 7,11,"", "Intention to have axes same length."); gd.addNumericField("Scale pull", scale_pull, 7,11,"", "Intention to have average scale of images = 1.0."); gd.addNumericField("Position pull", position_pull,7,11,"", "Intension to match IMS (GNSS) coordinates."); gd.addNumericField("Overlap inportance", overlap_pow, 3,7,"", "Raise overlap fraction (of the smaller image) to this power before using as weight."); gd.addNumericField("RMSE relative improvement",rms_diff, 8,10,"", "Relative RMSE improvement to exit LMA."); gd.addNumericField("RMSE relative improvement",rms_diff, 8,11,"", "Relative RMSE improvement to exit LMA."); gd.addNumericField("LMA iterations", num_iter, 0,3,"",".Maximal number of the LMA iterations."); gd.addCheckbox ("Show result image", show_result, "."); gd.addNumericField("Debug level for maps", debugLevel, 0,3,"","Debug building for LMA building maps."); gd.showDialog(); if (gd.wasCanceled()) return -1; all_pairs = gd.getNextBoolean(); move_only = gd.getNextBoolean(); ignore_affines = gd.getNextBoolean(); use_inv = gd.getNextBoolean(); Loading @@ -265,6 +269,7 @@ public class OrthoMultiLMA { clt_parameters, // CLTParameters clt_parameters, maps_collection, // OrthoMapsCollection maps_collection, orthoMapsCollection_path, // String orthoMapsCollection_path, all_pairs, // boolean all_pairs, move_only, // boolean move_only, ignore_affines, // boolean ignore_affines, use_inv, // boolean use_inv, Loading @@ -282,6 +287,7 @@ public class OrthoMultiLMA { CLTParameters clt_parameters, OrthoMapsCollection maps_collection, String orthoMapsCollection_path, boolean all_pairs, boolean move_only, boolean ignore_affines, boolean use_inv, Loading @@ -296,9 +302,37 @@ public class OrthoMultiLMA { int debugLevel) { double [] val_coord = null; // 1 - valid, 0 - invalid, minimize coordinates errors boolean corr_avg= (skew_pull > 0) || (tilt_pull > 0) || (scale_pull > 0); int [] indices = maps_collection.getScenesSelection( int [] indices = null; if (all_pairs) { boolean [] used_scenes = new boolean [maps_collection.ortho_maps.length]; for (int scene0 = 0; scene0 < (used_scenes.length-1); scene0++) { Set<String> match_names = maps_collection.ortho_maps[scene0].pairwise_matches.keySet(); for (String scene1_name:match_names) { PairwiseOrthoMatch match = maps_collection.ortho_maps[scene0].getMatch(scene1_name); // defined only if (match != null) { int scene1 = maps_collection.getIndex(scene1_name); used_scenes[scene0] = true; used_scenes[scene1] = true; } } } int num_scenes = 0; for (int i = 0; i < used_scenes.length; i++) if (used_scenes[i]){ num_scenes++; } indices = new int [num_scenes]; int indx = 0; for (int i = 0; i < used_scenes.length; i++) if (used_scenes[i]){ indices[indx++] = i; } if (debugLevel > -1) { System.out.println("buildOrthoMap(): got "+indices.length+" scenes with pairs"); } } else { indices = maps_collection.getScenesSelection( null, // boolean select_all, " to build a map"); // String purpose) " to build a map with LMA from pair-wise matches"); // String purpose) } OrthoMultiLMA oml = new OrthoMultiLMA( corr_avg, move_only); Loading src/main/java/com/elphel/imagej/orthomosaic/PairsGraph.java +49 −17 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ public class PairsGraph { public PairsGraph ( OrthoMapsCollection orthoMapsCollection, int [] indices, double min_overlap_frac, double max_rmse_reuse, boolean multi, int debugLevel) { this.orthoMapsCollection = orthoMapsCollection; Loading @@ -75,19 +77,30 @@ public class PairsGraph { } int num_defined = 0; int num_undefined = 0; int num_bad = 0; int num_low_overlap = 0; for (int i = 0; i < indices.length-1; i++) { for (int j = i+1; j < indices.length; j++){ String name2 = ortho_maps[indices[j]].getName(); PairwiseOrthoMatch match = ortho_maps[indices[i]].getMatch(name2,true); if (match != null) { if (match.getOverlap() < min_overlap_frac){ num_low_overlap++; } else { if (match.isDefined()) { if ((match.getOverlap() < min_overlap_frac) || ((max_rmse_reuse > 0) && !(match.getRMS() <= max_rmse_reuse))) { pair_state[i][j] = PAIR_UNDEFINED; num_undefined++; num_bad++; } else { pair_state[i][j] = PAIR_DEFINED; num_defined++; recordPair( new int [] {i,j}, // int [] pair, true, // boolean success, multi); } } else { pair_state[i][j] = PAIR_UNDEFINED; num_undefined++; Loading @@ -96,19 +109,38 @@ public class PairsGraph { } } } HashSet<Integer> hs = new HashSet<Integer>(); for (int i:groups) { hs.add(i); } pairs = multi? getPairsIndicesMulti():getPairsIndicesSingle(); if (debugLevel > 0) { if (debugLevel > -1) { System.out.println("Number of scenes - "+indices.length); System.out.println("Number of defined pairs - "+num_defined); System.out.println("Number of undefined pairs - "+num_undefined); System.out.println("Number of disconnected groups - "+hs.size()); System.out.println("Number of low overlap pairs ("+min_overlap_frac+") - "+num_low_overlap); System.out.println("Number of bad rms pairs ("+max_rmse_reuse+") - "+num_bad); System.out.println("Number of disconnected groups - "+getNumberOfGroups()); } } public int getNumberOfGroups() { HashSet<Integer> hs = new HashSet<Integer>(); for (int i:groups) { hs.add(i); } return hs.size(); } public int [] getIndices() { return indices; } public boolean useMultiThreaded() { return multi; } public double getOverlap( int [] pair) { return overlaps[Math.min(pair[0],pair[1])][Math.max(pair[0],pair[1])]; } public boolean dryRun( int heur, int debugLevel) { Loading Loading
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +2 −0 Original line number Diff line number Diff line Loading @@ -1303,6 +1303,8 @@ public class ComboMatch { System.out.println("This can happen if files have different resolution for new run."); System.out.println("Verify path, then modify filenames[i], break at line above: 'maps_collection.ortho_maps[i].setFileName(filenames[i])'."); System.out.println("Reduce i by 1 and continue"); } else { maps_collection.ortho_maps[i] = new OrthoMap(path); } } return true; Loading
src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java +23 −8 Original line number Diff line number Diff line Loading @@ -913,6 +913,10 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ int swidth = getWidth(); int sheight = getHeight(); final float [] spix = orig_image.data; if (swidth*sheight != spix.length) { System.out.println ("downScaleForGPU(): swidth="+ swidth+", sheight="+sheight+", swidth*sheight="+(swidth*sheight)+", spix.length="+spix.length); System.out.println (); } final int width = (swidth+frscale-1)/frscale; final int height = (sheight+frscale-1)/frscale; final int tiles = width * height; Loading @@ -939,17 +943,28 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ for (int py = 0; py < tileH; py++) { int ls = (tileY*frscale + py)*swidth; for (int px = 0; px < tileW; px++) { double d = spix[ls + tileX*frscale+px]; int indx = ls + tileX*frscale+px; if ((indx >=0) && (indx < spix.length)) { double d = spix[ls + tileX*frscale+px]; //java.lang.ArrayIndexOutOfBoundsException: Index 3892800 out of bounds for length 3892680 if (!Double.isNaN(d)) { double w = wnd[py][px]; sw += w; swd += w*d; } if (sw > 0) { opix[tileY * width + tileX] = (float) (swd/sw); } else { System.out.println("downScaleForGPU(): indx = "+indx+" ("+spix.length+"), tileX= "+ tileX+", tileY="+tileY+", px="+px+", py="+py+", ls="+ls); } // if (sw > 0) { // opix[tileY * width + tileX] = (float) (swd/sw); // } } } if (sw > 0) { opix[tileY * width + tileX] = (float) (swd/sw); } } } }; Loading
src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java +326 −465 File changed.Preview size limit exceeded, changes collapsed. Show changes
src/main/java/com/elphel/imagej/orthomosaic/OrthoMultiLMA.java +43 −9 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ import java.awt.Point; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import com.elphel.imagej.cameras.CLTParameters; Loading Loading @@ -218,6 +220,7 @@ public class OrthoMultiLMA { OrthoMapsCollection maps_collection, String orthoMapsCollection_path ) { boolean all_pairs = true; boolean move_only = clt_parameters.imp.pmap_move_only; // false; boolean ignore_affines = clt_parameters.imp.pmap_ignore_affines; // false; boolean use_inv = clt_parameters.imp.pmap_use_inv; // false; Loading @@ -232,22 +235,23 @@ public class OrthoMultiLMA { int debugLevel = clt_parameters.imp.pmap_debugLevel; // 2; GenericJTabbedDialog gd = new GenericJTabbedDialog("Pairwise Match Parameters",1200,400); gd.addCheckbox ("Use all available pairs", all_pairs, "Use all available pairs."); 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 ("Use reversed pairs", use_inv, "Use reversed (late-early timestamps) pairs."); gd.addNumericField("Skew pull", skew_pull, 7,10,"", "Intention to have axes perpendicular."); gd.addNumericField("Tilt pull", tilt_pull, 7,10,"", "Intention to have axes same length."); gd.addNumericField("Scale pull", scale_pull, 7,10,"", "Intention to have average scale of images = 1.0."); gd.addNumericField("Position pull", position_pull,7,10,"", "Intension to match IMS (GNSS) coordinates."); gd.addNumericField("Skew pull", skew_pull, 7,11,"", "Intention to have axes perpendicular."); gd.addNumericField("Tilt pull", tilt_pull, 7,11,"", "Intention to have axes same length."); gd.addNumericField("Scale pull", scale_pull, 7,11,"", "Intention to have average scale of images = 1.0."); gd.addNumericField("Position pull", position_pull,7,11,"", "Intension to match IMS (GNSS) coordinates."); gd.addNumericField("Overlap inportance", overlap_pow, 3,7,"", "Raise overlap fraction (of the smaller image) to this power before using as weight."); gd.addNumericField("RMSE relative improvement",rms_diff, 8,10,"", "Relative RMSE improvement to exit LMA."); gd.addNumericField("RMSE relative improvement",rms_diff, 8,11,"", "Relative RMSE improvement to exit LMA."); gd.addNumericField("LMA iterations", num_iter, 0,3,"",".Maximal number of the LMA iterations."); gd.addCheckbox ("Show result image", show_result, "."); gd.addNumericField("Debug level for maps", debugLevel, 0,3,"","Debug building for LMA building maps."); gd.showDialog(); if (gd.wasCanceled()) return -1; all_pairs = gd.getNextBoolean(); move_only = gd.getNextBoolean(); ignore_affines = gd.getNextBoolean(); use_inv = gd.getNextBoolean(); Loading @@ -265,6 +269,7 @@ public class OrthoMultiLMA { clt_parameters, // CLTParameters clt_parameters, maps_collection, // OrthoMapsCollection maps_collection, orthoMapsCollection_path, // String orthoMapsCollection_path, all_pairs, // boolean all_pairs, move_only, // boolean move_only, ignore_affines, // boolean ignore_affines, use_inv, // boolean use_inv, Loading @@ -282,6 +287,7 @@ public class OrthoMultiLMA { CLTParameters clt_parameters, OrthoMapsCollection maps_collection, String orthoMapsCollection_path, boolean all_pairs, boolean move_only, boolean ignore_affines, boolean use_inv, Loading @@ -296,9 +302,37 @@ public class OrthoMultiLMA { int debugLevel) { double [] val_coord = null; // 1 - valid, 0 - invalid, minimize coordinates errors boolean corr_avg= (skew_pull > 0) || (tilt_pull > 0) || (scale_pull > 0); int [] indices = maps_collection.getScenesSelection( int [] indices = null; if (all_pairs) { boolean [] used_scenes = new boolean [maps_collection.ortho_maps.length]; for (int scene0 = 0; scene0 < (used_scenes.length-1); scene0++) { Set<String> match_names = maps_collection.ortho_maps[scene0].pairwise_matches.keySet(); for (String scene1_name:match_names) { PairwiseOrthoMatch match = maps_collection.ortho_maps[scene0].getMatch(scene1_name); // defined only if (match != null) { int scene1 = maps_collection.getIndex(scene1_name); used_scenes[scene0] = true; used_scenes[scene1] = true; } } } int num_scenes = 0; for (int i = 0; i < used_scenes.length; i++) if (used_scenes[i]){ num_scenes++; } indices = new int [num_scenes]; int indx = 0; for (int i = 0; i < used_scenes.length; i++) if (used_scenes[i]){ indices[indx++] = i; } if (debugLevel > -1) { System.out.println("buildOrthoMap(): got "+indices.length+" scenes with pairs"); } } else { indices = maps_collection.getScenesSelection( null, // boolean select_all, " to build a map"); // String purpose) " to build a map with LMA from pair-wise matches"); // String purpose) } OrthoMultiLMA oml = new OrthoMultiLMA( corr_avg, move_only); Loading
src/main/java/com/elphel/imagej/orthomosaic/PairsGraph.java +49 −17 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ public class PairsGraph { public PairsGraph ( OrthoMapsCollection orthoMapsCollection, int [] indices, double min_overlap_frac, double max_rmse_reuse, boolean multi, int debugLevel) { this.orthoMapsCollection = orthoMapsCollection; Loading @@ -75,19 +77,30 @@ public class PairsGraph { } int num_defined = 0; int num_undefined = 0; int num_bad = 0; int num_low_overlap = 0; for (int i = 0; i < indices.length-1; i++) { for (int j = i+1; j < indices.length; j++){ String name2 = ortho_maps[indices[j]].getName(); PairwiseOrthoMatch match = ortho_maps[indices[i]].getMatch(name2,true); if (match != null) { if (match.getOverlap() < min_overlap_frac){ num_low_overlap++; } else { if (match.isDefined()) { if ((match.getOverlap() < min_overlap_frac) || ((max_rmse_reuse > 0) && !(match.getRMS() <= max_rmse_reuse))) { pair_state[i][j] = PAIR_UNDEFINED; num_undefined++; num_bad++; } else { pair_state[i][j] = PAIR_DEFINED; num_defined++; recordPair( new int [] {i,j}, // int [] pair, true, // boolean success, multi); } } else { pair_state[i][j] = PAIR_UNDEFINED; num_undefined++; Loading @@ -96,19 +109,38 @@ public class PairsGraph { } } } HashSet<Integer> hs = new HashSet<Integer>(); for (int i:groups) { hs.add(i); } pairs = multi? getPairsIndicesMulti():getPairsIndicesSingle(); if (debugLevel > 0) { if (debugLevel > -1) { System.out.println("Number of scenes - "+indices.length); System.out.println("Number of defined pairs - "+num_defined); System.out.println("Number of undefined pairs - "+num_undefined); System.out.println("Number of disconnected groups - "+hs.size()); System.out.println("Number of low overlap pairs ("+min_overlap_frac+") - "+num_low_overlap); System.out.println("Number of bad rms pairs ("+max_rmse_reuse+") - "+num_bad); System.out.println("Number of disconnected groups - "+getNumberOfGroups()); } } public int getNumberOfGroups() { HashSet<Integer> hs = new HashSet<Integer>(); for (int i:groups) { hs.add(i); } return hs.size(); } public int [] getIndices() { return indices; } public boolean useMultiThreaded() { return multi; } public double getOverlap( int [] pair) { return overlaps[Math.min(pair[0],pair[1])][Math.max(pair[0],pair[1])]; } public boolean dryRun( int heur, int debugLevel) { Loading