Loading src/main/java/com/elphel/imagej/common/ShowDoubleFloatArrays.java +16 −0 Original line number Diff line number Diff line Loading @@ -268,6 +268,22 @@ import ij.process.ImageProcessor; return array_stack; } public static ImageStack makeStack(byte[][] pixels, int width, int height, String [] titles) { ImageStack array_stack=new ImageStack(width,height); for (int i=0;i<pixels.length;i++) if (pixels[i]!=null) { if (pixels[i].length!=(width*height)){ System.out.println("showArrays(): pixels["+i+"].length="+pixels[i].length+" != width (+"+width+") * height("+height+")="+(width*height)); return null; } if (titles!=null){ array_stack.addSlice(titles[i], pixels[i]); } else { array_stack.addSlice("chn-"+i, pixels[i]); } } return array_stack; } public static ImagePlus [] makeArrays(double[][] pixels, int width, int height, String title) { int i,j; Loading src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +49 −19 Original line number Diff line number Diff line Loading @@ -103,7 +103,8 @@ public class ComboMatch { "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-13_50-25-50-75-100m", "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_19_sep13_25-50-75-100m", "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75", "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-50m"}; "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-50m", "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-13_50-25-50-75-100m-SUBSET"}; int default_list_choice = 0; // files_lists_paths.length-1; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75.data"; Loading Loading @@ -142,7 +143,9 @@ public class ComboMatch { int gpu_width= clt_parameters.imp.rln_gpu_width; // 3008; int gpu_height= clt_parameters.imp.rln_gpu_height; // 3008; int zoom_lev = -3; // 0; // +1 - zoom in twice, -1 - zoom out twice boolean show_map_stats = false; boolean show_combo_map = false; // true; boolean show_combo_mask = false; // generate image mas (where it is defined)_ boolean use_alt = false; boolean show_centers = true; boolean use_saved_collection = true; // false; Loading @@ -164,6 +167,10 @@ public class ComboMatch { if (!use_marked_image) { process_correlation=false; // use already adjusted by default } if (process_correlation) { render_match = true; // default pattern_match = false; } GenericJTabbedDialog gd = new GenericJTabbedDialog("Set image pair",1200,900); Loading Loading @@ -201,7 +208,9 @@ public class ComboMatch { gd.addNumericField("GPU image height", gpu_height, 0,4,"", "GPU image height"); gd.addCheckbox ("Show transformation centers", show_centers, "Mark verticals from the UAS on the ground."); gd.addCheckbox ("Show statistics for ortho images", show_map_stats, "Generate and show statistics for ortho maps."); gd.addCheckbox ("Show combo image map", show_combo_map, "Load and process altitude maps."); gd.addCheckbox ("Show combo image mask", show_combo_mask, "Display combo binary image."); gd.addCheckbox ("Show altitude combo image", use_alt, "Load and process altitude maps."); gd.addNumericField("Remove fraction of worst matches", frac_remove, 3,7,"", "When fitting scenes remove this fraction of worst match."); gd.addNumericField("Maximal metric error", metric_error, 3,7,"m", "Maximal tolerable fitting error caused by elevation variations."); Loading Loading @@ -244,7 +253,9 @@ public class ComboMatch { OrthoMap.setGPUWidthHeight(gpu_width,gpu_height); show_centers = gd.getNextBoolean(); show_map_stats = gd.getNextBoolean(); show_combo_map = gd.getNextBoolean(); show_combo_mask = gd.getNextBoolean(); use_alt = gd.getNextBoolean(); // gpu_spair[0] = gd.getNextString(); Loading @@ -271,8 +282,10 @@ public class ComboMatch { } } else { maps_collection = new OrthoMapsCollection(files_list_path); // should have ".list" extension maps_collection.updateNumberScenes(); maps_collection.updateSfmGain(); } String [] names = maps_collection.getNames(); String [] names = maps_collection.getNames(); // null if (object_list != null) { int corr_size = 128; int extr_size = 200; // 256; Loading Loading @@ -300,7 +313,6 @@ public class ComboMatch { double inv_blur_rate = 0.2; // blur increase outside of blur_radius // String pattern_dir= "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/debug/mines/pattern_25m_zoom1/synthetic/"; String pattern_dir= "/media/elphel/NVME/lwir16-proc/ortho_videos/mines_extract/evening_50m_sept12/debug_cross/new_synth/"; String [] pattern_files={ Loading Loading @@ -392,8 +404,6 @@ public class ComboMatch { if (gdo.wasCanceled()) return false; corr_size = (int) gdo.getNextNumber(); extr_size = (int) gdo.getNextNumber(); // OrthoMap.pattern_dir= gdo.getNextString(); // String pattern_file = OrthoMap.pattern_files[gdo.getNextChoiceIndex()]; pattern_dir= gdo.getNextString(); String pattern_file = pattern_files[gdo.getNextChoiceIndex()]; zoomout= (int) gdo.getNextNumber(); Loading Loading @@ -718,16 +728,27 @@ public class ComboMatch { if (update_lla) { System.out.println("Updating map files metadata"); maps_collection.updateLLa(); maps_collection.updateNumberScenes(); maps_collection.updateSfmGain(); } // which pair to compare // String [] gpu_spair = {names[gpu_ipair[0]],names[gpu_ipair[1]]}; int [] origin = new int[2]; ImagePlus imp_img = null; if (show_map_stats) { boolean ok = maps_collection.showScenesStats(false); // boolean select_all) if (!ok) { return false; } // System.out.println("Exiting after generating stats"); // return true; // do not process anything else } if (show_combo_map) { imp_img = maps_collection.renderMulti ( "multi_zoom"+zoom_lev, // String title, false, // boolean use_alt, OrthoMapsCollection.MODE_IMAGE, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt, show_centers, // boolean show_centers, zoom_lev, // int zoom_level, temp_mode, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct Loading @@ -738,7 +759,19 @@ public class ComboMatch { if (use_alt) { imp_alt =maps_collection.renderMulti ( "multi_alt_zoom"+zoom_lev, // String title, true, // boolean use_alt, // true, // boolean use_alt, OrthoMapsCollection.MODE_ALT, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt, show_centers, // boolean show_centers, zoom_lev, // int zoom_level, 0, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct origin); // int [] origin){ imp_alt.show(); } if (show_combo_mask) { imp_alt =maps_collection.renderMulti ( "multi_alt_zoom"+zoom_lev, // String title, // true, // boolean use_alt, OrthoMapsCollection.MODE_MASK, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt, show_centers, // boolean show_centers, zoom_lev, // int zoom_level, 0, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct Loading Loading @@ -886,7 +919,8 @@ public class ComboMatch { 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, // false, // boolean use_alt, 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, temp_mode, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct Loading @@ -910,10 +944,6 @@ public class ComboMatch { System.out.println("Saved data to "+ orthoMapsCollection_path); } return true; } public void printSceneStats() { } Loading src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java +119 −6 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import com.elphel.imagej.readers.ElphelTiffReader; import com.elphel.imagej.readers.ImagejJp4Tiff; import com.elphel.imagej.tileprocessor.ImageDtt; import com.elphel.imagej.tileprocessor.IntersceneMatchParameters; import com.elphel.imagej.tileprocessor.OpticalFlow; import com.elphel.imagej.tileprocessor.QuadCLT; import com.elphel.imagej.tileprocessor.TileNeibs; Loading @@ -54,6 +55,8 @@ import loci.formats.FormatException; public class OrthoMap implements Comparable <OrthoMap>, Serializable{ private static final long serialVersionUID = 1L; public static final String DSI_SUFFIX = "-INTER-INTRA-LMA.tiff"; public static final String MERGED_SUFFIX = "-MERGED.tiff"; public static boolean FIX_VERT_Y = false; // true; // temporarily fix vertical Y coordinate bug (use -GCORR in the filename?) public static int gpu_width = 4096; public static int gpu_height = 4096; Loading Loading @@ -84,12 +87,9 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public static final String ALT_SUFFIX = "-ALT"; // public transient final String name; // timestamp // public transient final double ts; public transient String name; // timestamp public transient double ts; public transient String path; // full path to the model directory (including /vXX?) // public transient String scenes_path; // full path to the model directory (including /vXX?) public double [] lla; // lat/long/alt public LocalDateTime dt; // affine convert (input) rectified coordinates (meters) relative to vert_meters to source image Loading @@ -110,6 +110,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ HashMap <String, PairwiseOrthoMatch> pairwise_matches; public transient SensorTemperatureData[] temp_data; public transient double agl = Double.NaN; public transient int num_scenes = -1;; // number of scenes that made up this image public transient double sfm_gain = Double.NaN; // maximal SfM gain of this map private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); oos.writeObject(path); Loading @@ -130,9 +132,13 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ // pairwise_matches is not transient oos.writeObject(temp_data); // temporary, while transient oos.writeObject(agl); oos.writeObject(num_scenes); oos.writeObject(sfm_gain); } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { // sfm_gain = Double.NaN; // num_scenes = -1; ois.defaultReadObject(); path = (String) ois.readObject(); name = getNameFromPath(path); Loading @@ -149,8 +155,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ // alt_image was not saved temp_data = (SensorTemperatureData[]) ois.readObject(); agl = (double) ois.readObject(); num_scenes = (int) ois.readObject(); sfm_gain = (double) ois.readObject(); images = new HashMap <Integer, FloatImageData>(); // field images was not saved averageImagePixel = Double.NaN; // average image pixel value (to combine with raw) Loading Loading @@ -211,6 +217,78 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ return getModelPathFromPath(this.path)+"/jp4"; } /** * Get number of scenes used to generate this ortho image. Looks in subdirectories of the directory * where the image file is stored (currently they are v01, vo2, ...) and in subdirectories finds the * latest *-MERGED.tiff file. Each scene has a slice in this file * @return number of scenes that made this ortho image, also sets the num_scenes (saved in database) * so next time reading files will not be needed */ public int getNumberScenes() { if (num_scenes < 0) { String merged_path = getLatestFilePath(MERGED_SUFFIX); if (merged_path != null) { ImagePlus imp_merged = new ImagePlus(merged_path); if (imp_merged.getWidth() > 0) { num_scenes = imp_merged.getImageStack().getSize(); } } } return num_scenes; } /** * Get maximal "SfM gain" - ratio between used interscene offset and the camera baseline. * Looks in subdirectories of the directory where the image file is stored (currently they are * v01, vo2, ...) and in subdirectories finds the latest *-INTER-INTRA-LMA.tiff file. * Those files have a slice (OpticalFlow.COMBO_DSN_INDX_SFM_GAIN + 1 as slices a numbered from 1) * that contains per-tile SfM gain. * @return Maximal SfM gain */ public double getSfmGain() { if (Double.isNaN(sfm_gain)) { String dsi_path = getLatestFilePath(DSI_SUFFIX); if (dsi_path != null) { ImagePlus imp_dsi = new ImagePlus(dsi_path); if (imp_dsi.getWidth() > 0) { float [] pixels = (float[]) imp_dsi.getImageStack().getPixels(OpticalFlow.COMBO_DSN_INDX_SFM_GAIN + 1); sfm_gain = 0; for (int i = 0; i < pixels.length; i++) { if (pixels[i] > sfm_gain) { sfm_gain = pixels[i]; } } } } } return sfm_gain; } public String getLatestFilePath(String suffix) { String model_dir = getModelPathFromPath(this.path); File [] subdirs = (new File(model_dir)).listFiles(); long latest_ms = 0; File latest_file = null; for (File subdir:subdirs) if (subdir.isDirectory()) { File [] file_vers = subdir.listFiles(); for (File file:file_vers) if (file.isFile() && file.toString().endsWith(suffix)){ long modified = file.lastModified(); if (modified > latest_ms) { latest_ms = modified; latest_file = file; } } } if (latest_file != null) { return latest_file.getPath(); } return null; } public void updateLLA() { Properties imp_prop = null; try { Loading Loading @@ -520,6 +598,41 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ return agl; } /** * Get coordinates and altitude * @return {latitude(deg), longitude(deg), altitude(m)} */ public double [] getLLA() { return lla; } /** * Get original image resolution as pixel size in meters * @return image pixel size in meters */ public double getOrigPixMeters() { return orig_pix_meters; } /** * Get vertical point offset from the top-left corner of the original orthoimage in meters * @return vertical point X,Y offset in meters from the top-left image corner */ public double [] getVertMeters() { return vert_meters; } /** * Get vertical point offset from the top-left corner of the original orthoimage in pixels * of the original resolution * @return vertical point X,Y offset in pixels from the top-left image corner in original resolution */ public int [] getVertPixels() { return new int [] { (int) Math.round(vert_meters[0]/orig_pix_meters), (int) Math.round(vert_meters[0]/orig_pix_meters)}; } public ImagePlus getOriginalImage(boolean show_markers) { FloatImageData orig_image = getImageData(); Loading Loading
src/main/java/com/elphel/imagej/common/ShowDoubleFloatArrays.java +16 −0 Original line number Diff line number Diff line Loading @@ -268,6 +268,22 @@ import ij.process.ImageProcessor; return array_stack; } public static ImageStack makeStack(byte[][] pixels, int width, int height, String [] titles) { ImageStack array_stack=new ImageStack(width,height); for (int i=0;i<pixels.length;i++) if (pixels[i]!=null) { if (pixels[i].length!=(width*height)){ System.out.println("showArrays(): pixels["+i+"].length="+pixels[i].length+" != width (+"+width+") * height("+height+")="+(width*height)); return null; } if (titles!=null){ array_stack.addSlice(titles[i], pixels[i]); } else { array_stack.addSlice("chn-"+i, pixels[i]); } } return array_stack; } public static ImagePlus [] makeArrays(double[][] pixels, int width, int height, String title) { int i,j; Loading
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +49 −19 Original line number Diff line number Diff line Loading @@ -103,7 +103,8 @@ public class ComboMatch { "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-13_50-25-50-75-100m", "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_19_sep13_25-50-75-100m", "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75", "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-50m"}; "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-50m", "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-13_50-25-50-75-100m-SUBSET"}; int default_list_choice = 0; // files_lists_paths.length-1; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75.data"; Loading Loading @@ -142,7 +143,9 @@ public class ComboMatch { int gpu_width= clt_parameters.imp.rln_gpu_width; // 3008; int gpu_height= clt_parameters.imp.rln_gpu_height; // 3008; int zoom_lev = -3; // 0; // +1 - zoom in twice, -1 - zoom out twice boolean show_map_stats = false; boolean show_combo_map = false; // true; boolean show_combo_mask = false; // generate image mas (where it is defined)_ boolean use_alt = false; boolean show_centers = true; boolean use_saved_collection = true; // false; Loading @@ -164,6 +167,10 @@ public class ComboMatch { if (!use_marked_image) { process_correlation=false; // use already adjusted by default } if (process_correlation) { render_match = true; // default pattern_match = false; } GenericJTabbedDialog gd = new GenericJTabbedDialog("Set image pair",1200,900); Loading Loading @@ -201,7 +208,9 @@ public class ComboMatch { gd.addNumericField("GPU image height", gpu_height, 0,4,"", "GPU image height"); gd.addCheckbox ("Show transformation centers", show_centers, "Mark verticals from the UAS on the ground."); gd.addCheckbox ("Show statistics for ortho images", show_map_stats, "Generate and show statistics for ortho maps."); gd.addCheckbox ("Show combo image map", show_combo_map, "Load and process altitude maps."); gd.addCheckbox ("Show combo image mask", show_combo_mask, "Display combo binary image."); gd.addCheckbox ("Show altitude combo image", use_alt, "Load and process altitude maps."); gd.addNumericField("Remove fraction of worst matches", frac_remove, 3,7,"", "When fitting scenes remove this fraction of worst match."); gd.addNumericField("Maximal metric error", metric_error, 3,7,"m", "Maximal tolerable fitting error caused by elevation variations."); Loading Loading @@ -244,7 +253,9 @@ public class ComboMatch { OrthoMap.setGPUWidthHeight(gpu_width,gpu_height); show_centers = gd.getNextBoolean(); show_map_stats = gd.getNextBoolean(); show_combo_map = gd.getNextBoolean(); show_combo_mask = gd.getNextBoolean(); use_alt = gd.getNextBoolean(); // gpu_spair[0] = gd.getNextString(); Loading @@ -271,8 +282,10 @@ public class ComboMatch { } } else { maps_collection = new OrthoMapsCollection(files_list_path); // should have ".list" extension maps_collection.updateNumberScenes(); maps_collection.updateSfmGain(); } String [] names = maps_collection.getNames(); String [] names = maps_collection.getNames(); // null if (object_list != null) { int corr_size = 128; int extr_size = 200; // 256; Loading Loading @@ -300,7 +313,6 @@ public class ComboMatch { double inv_blur_rate = 0.2; // blur increase outside of blur_radius // String pattern_dir= "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/debug/mines/pattern_25m_zoom1/synthetic/"; String pattern_dir= "/media/elphel/NVME/lwir16-proc/ortho_videos/mines_extract/evening_50m_sept12/debug_cross/new_synth/"; String [] pattern_files={ Loading Loading @@ -392,8 +404,6 @@ public class ComboMatch { if (gdo.wasCanceled()) return false; corr_size = (int) gdo.getNextNumber(); extr_size = (int) gdo.getNextNumber(); // OrthoMap.pattern_dir= gdo.getNextString(); // String pattern_file = OrthoMap.pattern_files[gdo.getNextChoiceIndex()]; pattern_dir= gdo.getNextString(); String pattern_file = pattern_files[gdo.getNextChoiceIndex()]; zoomout= (int) gdo.getNextNumber(); Loading Loading @@ -718,16 +728,27 @@ public class ComboMatch { if (update_lla) { System.out.println("Updating map files metadata"); maps_collection.updateLLa(); maps_collection.updateNumberScenes(); maps_collection.updateSfmGain(); } // which pair to compare // String [] gpu_spair = {names[gpu_ipair[0]],names[gpu_ipair[1]]}; int [] origin = new int[2]; ImagePlus imp_img = null; if (show_map_stats) { boolean ok = maps_collection.showScenesStats(false); // boolean select_all) if (!ok) { return false; } // System.out.println("Exiting after generating stats"); // return true; // do not process anything else } if (show_combo_map) { imp_img = maps_collection.renderMulti ( "multi_zoom"+zoom_lev, // String title, false, // boolean use_alt, OrthoMapsCollection.MODE_IMAGE, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt, show_centers, // boolean show_centers, zoom_lev, // int zoom_level, temp_mode, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct Loading @@ -738,7 +759,19 @@ public class ComboMatch { if (use_alt) { imp_alt =maps_collection.renderMulti ( "multi_alt_zoom"+zoom_lev, // String title, true, // boolean use_alt, // true, // boolean use_alt, OrthoMapsCollection.MODE_ALT, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt, show_centers, // boolean show_centers, zoom_lev, // int zoom_level, 0, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct origin); // int [] origin){ imp_alt.show(); } if (show_combo_mask) { imp_alt =maps_collection.renderMulti ( "multi_alt_zoom"+zoom_lev, // String title, // true, // boolean use_alt, OrthoMapsCollection.MODE_MASK, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt, show_centers, // boolean show_centers, zoom_lev, // int zoom_level, 0, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct Loading Loading @@ -886,7 +919,8 @@ public class ComboMatch { 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, // false, // boolean use_alt, 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, temp_mode, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct Loading @@ -910,10 +944,6 @@ public class ComboMatch { System.out.println("Saved data to "+ orthoMapsCollection_path); } return true; } public void printSceneStats() { } Loading
src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java +119 −6 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import com.elphel.imagej.readers.ElphelTiffReader; import com.elphel.imagej.readers.ImagejJp4Tiff; import com.elphel.imagej.tileprocessor.ImageDtt; import com.elphel.imagej.tileprocessor.IntersceneMatchParameters; import com.elphel.imagej.tileprocessor.OpticalFlow; import com.elphel.imagej.tileprocessor.QuadCLT; import com.elphel.imagej.tileprocessor.TileNeibs; Loading @@ -54,6 +55,8 @@ import loci.formats.FormatException; public class OrthoMap implements Comparable <OrthoMap>, Serializable{ private static final long serialVersionUID = 1L; public static final String DSI_SUFFIX = "-INTER-INTRA-LMA.tiff"; public static final String MERGED_SUFFIX = "-MERGED.tiff"; public static boolean FIX_VERT_Y = false; // true; // temporarily fix vertical Y coordinate bug (use -GCORR in the filename?) public static int gpu_width = 4096; public static int gpu_height = 4096; Loading Loading @@ -84,12 +87,9 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public static final String ALT_SUFFIX = "-ALT"; // public transient final String name; // timestamp // public transient final double ts; public transient String name; // timestamp public transient double ts; public transient String path; // full path to the model directory (including /vXX?) // public transient String scenes_path; // full path to the model directory (including /vXX?) public double [] lla; // lat/long/alt public LocalDateTime dt; // affine convert (input) rectified coordinates (meters) relative to vert_meters to source image Loading @@ -110,6 +110,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ HashMap <String, PairwiseOrthoMatch> pairwise_matches; public transient SensorTemperatureData[] temp_data; public transient double agl = Double.NaN; public transient int num_scenes = -1;; // number of scenes that made up this image public transient double sfm_gain = Double.NaN; // maximal SfM gain of this map private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); oos.writeObject(path); Loading @@ -130,9 +132,13 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ // pairwise_matches is not transient oos.writeObject(temp_data); // temporary, while transient oos.writeObject(agl); oos.writeObject(num_scenes); oos.writeObject(sfm_gain); } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { // sfm_gain = Double.NaN; // num_scenes = -1; ois.defaultReadObject(); path = (String) ois.readObject(); name = getNameFromPath(path); Loading @@ -149,8 +155,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ // alt_image was not saved temp_data = (SensorTemperatureData[]) ois.readObject(); agl = (double) ois.readObject(); num_scenes = (int) ois.readObject(); sfm_gain = (double) ois.readObject(); images = new HashMap <Integer, FloatImageData>(); // field images was not saved averageImagePixel = Double.NaN; // average image pixel value (to combine with raw) Loading Loading @@ -211,6 +217,78 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ return getModelPathFromPath(this.path)+"/jp4"; } /** * Get number of scenes used to generate this ortho image. Looks in subdirectories of the directory * where the image file is stored (currently they are v01, vo2, ...) and in subdirectories finds the * latest *-MERGED.tiff file. Each scene has a slice in this file * @return number of scenes that made this ortho image, also sets the num_scenes (saved in database) * so next time reading files will not be needed */ public int getNumberScenes() { if (num_scenes < 0) { String merged_path = getLatestFilePath(MERGED_SUFFIX); if (merged_path != null) { ImagePlus imp_merged = new ImagePlus(merged_path); if (imp_merged.getWidth() > 0) { num_scenes = imp_merged.getImageStack().getSize(); } } } return num_scenes; } /** * Get maximal "SfM gain" - ratio between used interscene offset and the camera baseline. * Looks in subdirectories of the directory where the image file is stored (currently they are * v01, vo2, ...) and in subdirectories finds the latest *-INTER-INTRA-LMA.tiff file. * Those files have a slice (OpticalFlow.COMBO_DSN_INDX_SFM_GAIN + 1 as slices a numbered from 1) * that contains per-tile SfM gain. * @return Maximal SfM gain */ public double getSfmGain() { if (Double.isNaN(sfm_gain)) { String dsi_path = getLatestFilePath(DSI_SUFFIX); if (dsi_path != null) { ImagePlus imp_dsi = new ImagePlus(dsi_path); if (imp_dsi.getWidth() > 0) { float [] pixels = (float[]) imp_dsi.getImageStack().getPixels(OpticalFlow.COMBO_DSN_INDX_SFM_GAIN + 1); sfm_gain = 0; for (int i = 0; i < pixels.length; i++) { if (pixels[i] > sfm_gain) { sfm_gain = pixels[i]; } } } } } return sfm_gain; } public String getLatestFilePath(String suffix) { String model_dir = getModelPathFromPath(this.path); File [] subdirs = (new File(model_dir)).listFiles(); long latest_ms = 0; File latest_file = null; for (File subdir:subdirs) if (subdir.isDirectory()) { File [] file_vers = subdir.listFiles(); for (File file:file_vers) if (file.isFile() && file.toString().endsWith(suffix)){ long modified = file.lastModified(); if (modified > latest_ms) { latest_ms = modified; latest_file = file; } } } if (latest_file != null) { return latest_file.getPath(); } return null; } public void updateLLA() { Properties imp_prop = null; try { Loading Loading @@ -520,6 +598,41 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ return agl; } /** * Get coordinates and altitude * @return {latitude(deg), longitude(deg), altitude(m)} */ public double [] getLLA() { return lla; } /** * Get original image resolution as pixel size in meters * @return image pixel size in meters */ public double getOrigPixMeters() { return orig_pix_meters; } /** * Get vertical point offset from the top-left corner of the original orthoimage in meters * @return vertical point X,Y offset in meters from the top-left image corner */ public double [] getVertMeters() { return vert_meters; } /** * Get vertical point offset from the top-left corner of the original orthoimage in pixels * of the original resolution * @return vertical point X,Y offset in pixels from the top-left image corner in original resolution */ public int [] getVertPixels() { return new int [] { (int) Math.round(vert_meters[0]/orig_pix_meters), (int) Math.round(vert_meters[0]/orig_pix_meters)}; } public ImagePlus getOriginalImage(boolean show_markers) { FloatImageData orig_image = getImageData(); Loading