Loading src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +133 −18 Original line number Diff line number Diff line Loading @@ -42,12 +42,43 @@ public class ComboMatch { public static boolean openTestPairGps( CLTParameters clt_parameters, GPUTileProcessor gpu_tile_processor, // initialized by the caller final int debugLevel) { int debugLevel) { GPU_TILE_PROCESSOR = gpu_tile_processor; // find -L /media/elphel/SSD3-4GB/lwir16-proc/berdich3/linked/linked_1697875868-1697879449-b/ -type f -name "*-GCORR-GEO.tiff" | sort > GCORR-GEO.list String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_03_short.list"; String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/ortho_maps_collection.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_03_short.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/ortho_maps_collection.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_04_short_20min.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_04_short_20min.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_05_short_27.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_05_short_27.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_07_short_27.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_07_short_27.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_08_november.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_08_november.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_10_short.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_10_short.data"; String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_19_sep13.list"; String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_19_sep13.data"; //maps_19_sep13.list //maps_09_short.list //maps_08_november.list // int [] gpu_ipair = {1,2}; // int [] gpu_ipair = {4,9}; //-> {4,24} // int [] gpu_ipair = {4,18}; // String [] gpu_spair = {"1697877420_556997", "1697877527_942766"}; // 1697877564_888405"}; //58, 220 // String [] gpu_spair = {"1697877419_940125", "1697877527_942766"}; // 1697877564_888405"}; //58, 220 // String [] gpu_spair = {"1697877412_004148", "1697877522_274211"}; // 1697877564_888405"}; //58, 220 // String [] gpu_spair = {"1697877409_353265", "1697877518_773045"}; // String [] gpu_spair = {"1697877465_672024", "1697877563_587972"}; // String [] gpu_spair = {"1697877465_672024", "1697878995_797332"}; // String [] gpu_spair = {"1697877465_672024", "1697877528_776377"}; // String [] gpu_spair = {"1694564245_111645", "1694564701_230240"}; // Morning Sep, 13 // String [] gpu_spair = {"1694564245_111645", "1694564822_637346"}; // Morning Sep, 13 String [] gpu_spair = {"1694564248_145989", "1694564819_336247"}; // Morning Sep, 13 // double [][][] image_enuatr = {{{0,0,0},{0,0,0}},{{0,0,0},{0,0,0}}}; int gpu_width= clt_parameters.imp.rln_gpu_width; // 3008; Loading @@ -58,6 +89,7 @@ public class ComboMatch { boolean use_saved_collection = true; // false; boolean save_collection = true; boolean process_correlation = true; // use false to save new version of data boolean restore_temp = true; GenericJTabbedDialog gd = new GenericJTabbedDialog("Set image pair",1200,800); gd.addStringField ("Image list full path", files_list_path, 180, "Image list full path."); gd.addStringField ("Maps collection save path", orthoMapsCollection_path, 180, "Save path for serialized map collection data."); Loading Loading @@ -87,6 +119,8 @@ public class ComboMatch { "GPU image height"); gd.addCheckbox ("Show transformation centers", show_centers, "Mark verticals from the UAS on the ground."); gd.addCheckbox ("Process altitude images", use_alt, "Load and process altitude maps."); gd.addStringField ("First matching timestamp", gpu_spair[0], 20, "First GPU-matching timestamp with '_' for decimal point."); gd.addStringField ("Second matching timestamp", gpu_spair[1], 20, "First GPU-matching timestamp with '_' for decimal point."); gd.showDialog(); if (gd.wasCanceled()) return false; Loading @@ -113,6 +147,10 @@ public class ComboMatch { show_centers = gd.getNextBoolean(); use_alt = gd.getNextBoolean(); gpu_spair[0] = gd.getNextString(); gpu_spair[1] = gd.getNextString(); OrthoMapsCollection maps_collection=null; if (use_saved_collection) { try { Loading @@ -125,9 +163,14 @@ public class ComboMatch { maps_collection = new OrthoMapsCollection(files_list_path); // should have ".list" extensiohn } String [] names = maps_collection.getNames(); //getTemperature() // get all temperatures maps_collection. getAllTemperatures(); // which pair to compare int [] gpu_pair = {1,2}; String [] gpu_spair = {names[gpu_pair[0]],names[gpu_pair[1]]}; // String [] gpu_spair = {names[gpu_ipair[0]],names[gpu_ipair[1]]}; int [] origin = new int[2]; ImagePlus imp_img = maps_collection.renderMulti ( "multi_"+zoom_lev, // String title, Loading Loading @@ -165,14 +208,73 @@ public class ComboMatch { } double [][] affine0 = {{1,0,0},{0,1,0}}; // will always stay the same double [][] affine1 = {{1,0,0},{0,1,0}}; // will be variable // here in meters, relative to vertical point // double [][] affine1 = { // {1,0,-1.47336}, // {0,1,-3.46664}}; // will be variable // here in meters, relative to vertical point //1697877414_404948 - 4 (0) //1697879062_336162 - 9 (1) // double [][] affine1 = { // {1.0002226408872814, -0.007965644488589378, -1.512310157498787}, // {0.006494702666097521, 1.0002691922354188, -3.4553628872407023}}; // double [][] affine1 = {{1,0,0},{0,1,0}}; // will always stay the same // [[1.0001698416441531, 0.0035703780078751575, 1.3965061354976767], // [0.005158652079706154, 1.0014361052510927, 1.204551528740014]]] // double [][] affine1 = {{1,0,1.33}, // {0,1,1.227}}; double [][] affine1 = { {1,0,0}, {0,1,0}}; // affine1[0][2] = 0.64; affine1[1][2] = 1.253; // {"1697877412_004148", "1697877522_274211"}; // // (346.250-348.000)/12.5,(277.000-269.250)/12.5 = (-0.14, 0.62) // affine1[0][2] = -0.14; affine1[1][2] = 0.62; // {"1697877409_353265", "1697877518_773045"}; // // affine1[0][2] = -1.44; affine1[1][2] = 1.653; //"1697877465_672024", "1697877563_587972" // affine1[0][2] = -0.25; affine1[1][2] = -1.627; //{"1697877465_672024", "1697878995_797332"}; // affine1[0][2] = -1.08; affine1[1][2] = 3.267; //{"1697877465_672024", "1697877528_776377"}; // affine1[0][2] = -1.2; affine1[1][2] = -0.9066; //{"1694564245_111645", "1694564701_230240"}; // affine1[0][2] = 0.933; affine1[1][2] = -2.2667; //{"1694564245_111645", "1694564822_637346"}; affine1[0][2] = 2.08; affine1[1][2] = -0.093; //{"1694564248_145989", "1694564819_336247"}; double [][][] affines = {affine0,affine1}; 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 [] zooms = {-3,-1,1000,1000}; debugLevel = 0; boolean batch_mode = true; for (int zi = 0; zi < zooms.length; zi++) { zoom_lev = zooms[zi]; if (zoom_lev >=1000) { break; } // will modify affines[1], later add jtj, weight, smth. else? double [][] corr_pair_rslt = maps_collection.correlateOrthoPair( clt_parameters, // CLTParameters clt_parameters, gpu_spair, // String [] gpu_spair, batch_mode, // boolean batch_mode, gpu_pair, // String [] gpu_spair, affines, // double [][][] affines, // on top of GPS offsets zoom_lev, // int zoom_lev, debugLevel); // final int debugLevel) int render_zoom_lev = maps_collection.ortho_maps[gpu_pair[0]].getOriginalZoomLevel(); ImagePlus imp_img_pair = maps_collection.renderMulti ( "multi_"+gpu_spair[0]+"-"+gpu_spair[1]+"-zoom_"+render_zoom_lev+"_"+zoom_lev, // String title, false, // boolean use_alt, gpu_pair, // int [] indices, // null or which indices to use (normally just 2 for pairwise comparison) affines, // double [][][] affines, // null or [indices.length][2][3] show_centers, // boolean show_centers, render_zoom_lev, // int zoom_level, origin); // int [] origin){ imp_img_pair.show(); System.out.println("Done"); if (debugLevel>-4) { System.out.println("adjusted affines[1] for a pair: "+gpu_spair[0]+"/"+gpu_spair[1]); System.out.println("[["+affines[1][0][0]+","+affines[1][0][1]+","+affines[1][0][2]+"],"); System.out.println(" ["+affines[1][1][0]+","+affines[1][1][1]+","+affines[1][1][2]+"]]"); System.out.println(); } } } if (save_collection) { try { Loading @@ -188,6 +290,20 @@ public class ComboMatch { return true; } /* adjusted affines[1] for a pair: 1697877465_672024/1697877563_587972 RMS= 0.14511264718699468 (0.14577676900752629) [[1.0065661054211072,0.009234141675959222,-1.4706666954418992], [-0.004304610680434175,1.0012437786888277,1.6394608778426498]] adjusted affines[1] for a pair: 1694564245_111645/1694564701_230240 [[1.021246208683918,0.006667337255903127,-1.0137566435443375], [-0.010035351748801541,1.0294363088409202,-0.8395952637299295]] adjusted affines[1] for a pair: 1694564245_111645/1694564822_637346 [[1.0148318094351692,0.01611699521114023,1.1534804399270817], [-0.025584298199020607,1.0182605131307008,-2.157143969635918]] * * double [] offset_xy_second = {0,0}; double [][] corr_pair_rslt = maps_collection. correlateOrthoPair( clt_parameters, // CLTParameters clt_parameters, Loading Loading @@ -438,10 +554,10 @@ public class ComboMatch { clt_parameters.gpu_sigma_b, // final double gpu_sigma_b, // 0.9, 1.1 clt_parameters.gpu_sigma_g, // final double gpu_sigma_g, // 0.6, 0.7 clt_parameters.gpu_sigma_m, // final double gpu_sigma_m, // = 0.4; // 0.7; debugLevel); // final int globalDebugLevel) batch_mode? -3: debugLevel); // final int globalDebugLevel) int tilesX = img_width/GPUTileProcessor.DTT_SIZE; int tilesY = wh[1]/GPUTileProcessor.DTT_SIZE; if (debugLevel > 1) { if (!batch_mode && (debugLevel > 1)) { renderFromTD ( true, // boolean use_reference, "ref"); //String suffix Loading @@ -453,6 +569,7 @@ public class ComboMatch { final double gpu_sigma_log_corr = clt_parameters.getGpuCorrLoGSigma(image_dtt.isMonochrome()); image_dtt.interRectilinearCorrTD( clt_parameters.img_dtt, //final ImageDttParameters imgdtt_params, // Now just extra correlation parameters, later will include, most others batch_mode, // final boolean batch_mode, erase_clt, // final int erase_clt, fpixels[1], // final float [] fpixels, wh, // final int [] wh, // null (use sensor dimensions) or pair {width, height} in pixels Loading Loading @@ -518,10 +635,8 @@ public class ComboMatch { rln_cent_radius, // final double centroid_radius, // 0 - all same weight, > 0 cosine(PI/2*sqrt(dx^2+dy^2)/rad) rln_n_recenter); // final int n_recenter); // re-center window around new maximum. 0 -no refines (single-pass) } boolean show_vector_field = true; boolean show_2d_correlations = true; boolean show_vector_field = (debugLevel>100); // true; boolean show_2d_correlations = (debugLevel>0); // true; final int corr_size = 2 * GPUTileProcessor.DTT_SIZE -1; if (show_2d_correlations) { double [][] dbg_2d_corrs = ImageDtt.corr_partial_dbg( // not used in lwir Loading src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java +112 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays; import com.elphel.imagej.gpu.TpTask; import com.elphel.imagej.ims.Imx5; 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.QuadCLT; Loading @@ -41,6 +42,7 @@ import ij.plugin.filter.GaussianBlur; import ij.process.FloatProcessor; import ij.process.ImageConverter; import ij.process.ImageProcessor; import loci.formats.FormatException; public class OrthoMap implements Comparable <OrthoMap>, Serializable{ private static final long serialVersionUID = 1L; Loading @@ -55,6 +57,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ 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 @@ -69,6 +72,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public int orig_zoom_level; public boolean orig_zoom_valid; public double need_extra_zoom; public double averageRawPixel = Double.NaN; // measure of scene temperature public transient double averageImagePixel = Double.NaN; // average image pixel value (to combine with raw) transient HashMap <Integer, FloatImageData> images; HashMap <Double, PairwiseOrthoMatch> pairwise_matches; Loading @@ -76,6 +81,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); oos.writeObject(path); oos.writeObject(scenes_path); // lla is not transient // dt is not transient // affine is not transient Loading @@ -97,6 +103,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ path = (String) ois.readObject(); name = getNameFromPath(path); ts= Double.parseDouble(name.replace("_", ".")); scenes_path= (String) ois.readObject(); // lla is not transient // dt is not transient // affine is not transient Loading @@ -107,6 +114,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ // orig_image was not saved // alt_image was not saved images = new HashMap <Integer, FloatImageData>(); // field images was not saved averageImagePixel = Double.NaN; // average image pixel value (to combine with raw) // pairwise_matches is not transient // pairwise_matches = new HashMap<Double, PairwiseOrthoMatch>(); } Loading @@ -129,11 +138,14 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public int getHeight() { return orig_height; } public int getOriginalZoomLevel() { return orig_zoom_level; } // Generate ALT image path from the GEO public static String getAltPath(String path) { int p1 = path.lastIndexOf("."); return path.substring(0,p1)+ALT_SUFFIX+".tiff"; } public static String getNameFromPath(String path) { int p1 = path.lastIndexOf(Prefs.getFileSeparator()); Loading @@ -143,8 +155,65 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ return path.substring(p1+1, p2); } public OrthoMap (String path) { /** * Gets average pixel value of all sensors of the reference scene * @return */ public double getTemperature() { if (Double.isNaN(averageRawPixel)) { final String TIFF_EXT=".tiff"; final File [] raw_files = (new File(scenes_path)).listFiles(); final Thread[] threads = ImageDtt.newThreadArray(); final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ati = new AtomicInteger(0); final double [] avg_arr = new double [threads.length]; final double [] npix_arr = new double [threads.length]; for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); ImagejJp4Tiff imagejJp4Tiff = new ImagejJp4Tiff(); for (int iFile = ai.getAndIncrement(); iFile < raw_files.length; iFile = ai.getAndIncrement()) { if (raw_files[iFile].getName().endsWith(TIFF_EXT)) { ImagePlus imp = null; String spath = raw_files[iFile].toString(); try { imp= imagejJp4Tiff.readTiffJp4(spath); } catch (IOException e) { System.out.println("getImagesMultithreaded IOException " + spath); } catch (FormatException e) { System.out.println("getImagesMultithreaded FormatException " + spath); } if (imp != null) { npix_arr[thread_num] = imp.getWidth()*imp.getHeight(); float [] fpixels = (float[]) imp.getProcessor().getPixels(); for (int i = 0; i < fpixels.length; i++) { avg_arr[thread_num] += fpixels[i]; } avg_arr[thread_num] /= npix_arr[thread_num]; } } } } }; } ImageDtt.startAndJoin(threads); double avg=0, num=0; for (int i = 0; i < avg_arr.length; i++) { avg+=avg_arr[i]*npix_arr[i]; num+=npix_arr[i]; } averageRawPixel = avg/num; } return averageRawPixel; } public OrthoMap ( String path, String scenes_path) { this.path = path; this.scenes_path = scenes_path; name = getNameFromPath(path); ts= Double.parseDouble(name.replace("_", ".")); Properties imp_prop = null; Loading @@ -171,6 +240,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ need_extra_zoom = FloatImageData.needZoomIn(orig_pix_meters); images = new HashMap <Integer, FloatImageData>(); pairwise_matches = new HashMap<Double, PairwiseOrthoMatch>(); averageRawPixel = Double.NaN; // measure of scene temperature averageImagePixel = Double.NaN; // average image pixel value (to combine with raw) } Loading Loading @@ -221,6 +292,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ if (orig_image == null) { readImageData(); } getAveragePixel(); return orig_image; } public FloatImageData getAltData() { Loading @@ -246,9 +318,47 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ if (orig_zoom_valid) { images.put(orig_zoom_level, orig_image); } averageImagePixel = Double.NaN; return true; } public double getAveragePixel() { if (Double.isNaN(averageImagePixel)) { if (orig_image == null) { readImageData(); } final float [] pixels = orig_image.data; final Thread[] threads = ImageDtt.newThreadArray(); final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ati = new AtomicInteger(0); final double [] avg_arr = new double [threads.length]; final double [] npix_arr = new double [threads.length]; for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); for (int ipix = ai.getAndIncrement(); ipix < pixels.length; ipix = ai.getAndIncrement()) { float p = pixels[ipix]; if (!Float.isNaN(p)) { avg_arr[thread_num] += p; npix_arr[thread_num] +=1; } } } }; } ImageDtt.startAndJoin(threads); double avg=0, num=0; for (int i = 0; i < avg_arr.length; i++) { avg+=avg_arr[i]; // *npix_arr[i]; num+=npix_arr[i]; } averageImagePixel = avg/num; } return averageImagePixel; } private boolean readAltData() { // assuming the same scale as main image ImagePlus imp = new ImagePlus(getAltPath(path)); int width = imp.getWidth(); Loading Loading
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +133 −18 Original line number Diff line number Diff line Loading @@ -42,12 +42,43 @@ public class ComboMatch { public static boolean openTestPairGps( CLTParameters clt_parameters, GPUTileProcessor gpu_tile_processor, // initialized by the caller final int debugLevel) { int debugLevel) { GPU_TILE_PROCESSOR = gpu_tile_processor; // find -L /media/elphel/SSD3-4GB/lwir16-proc/berdich3/linked/linked_1697875868-1697879449-b/ -type f -name "*-GCORR-GEO.tiff" | sort > GCORR-GEO.list String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_03_short.list"; String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/ortho_maps_collection.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_03_short.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/ortho_maps_collection.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_04_short_20min.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_04_short_20min.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_05_short_27.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_05_short_27.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_07_short_27.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_07_short_27.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_08_november.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_08_november.data"; // String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_10_short.list"; // String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_10_short.data"; String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_19_sep13.list"; String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_19_sep13.data"; //maps_19_sep13.list //maps_09_short.list //maps_08_november.list // int [] gpu_ipair = {1,2}; // int [] gpu_ipair = {4,9}; //-> {4,24} // int [] gpu_ipair = {4,18}; // String [] gpu_spair = {"1697877420_556997", "1697877527_942766"}; // 1697877564_888405"}; //58, 220 // String [] gpu_spair = {"1697877419_940125", "1697877527_942766"}; // 1697877564_888405"}; //58, 220 // String [] gpu_spair = {"1697877412_004148", "1697877522_274211"}; // 1697877564_888405"}; //58, 220 // String [] gpu_spair = {"1697877409_353265", "1697877518_773045"}; // String [] gpu_spair = {"1697877465_672024", "1697877563_587972"}; // String [] gpu_spair = {"1697877465_672024", "1697878995_797332"}; // String [] gpu_spair = {"1697877465_672024", "1697877528_776377"}; // String [] gpu_spair = {"1694564245_111645", "1694564701_230240"}; // Morning Sep, 13 // String [] gpu_spair = {"1694564245_111645", "1694564822_637346"}; // Morning Sep, 13 String [] gpu_spair = {"1694564248_145989", "1694564819_336247"}; // Morning Sep, 13 // double [][][] image_enuatr = {{{0,0,0},{0,0,0}},{{0,0,0},{0,0,0}}}; int gpu_width= clt_parameters.imp.rln_gpu_width; // 3008; Loading @@ -58,6 +89,7 @@ public class ComboMatch { boolean use_saved_collection = true; // false; boolean save_collection = true; boolean process_correlation = true; // use false to save new version of data boolean restore_temp = true; GenericJTabbedDialog gd = new GenericJTabbedDialog("Set image pair",1200,800); gd.addStringField ("Image list full path", files_list_path, 180, "Image list full path."); gd.addStringField ("Maps collection save path", orthoMapsCollection_path, 180, "Save path for serialized map collection data."); Loading Loading @@ -87,6 +119,8 @@ public class ComboMatch { "GPU image height"); gd.addCheckbox ("Show transformation centers", show_centers, "Mark verticals from the UAS on the ground."); gd.addCheckbox ("Process altitude images", use_alt, "Load and process altitude maps."); gd.addStringField ("First matching timestamp", gpu_spair[0], 20, "First GPU-matching timestamp with '_' for decimal point."); gd.addStringField ("Second matching timestamp", gpu_spair[1], 20, "First GPU-matching timestamp with '_' for decimal point."); gd.showDialog(); if (gd.wasCanceled()) return false; Loading @@ -113,6 +147,10 @@ public class ComboMatch { show_centers = gd.getNextBoolean(); use_alt = gd.getNextBoolean(); gpu_spair[0] = gd.getNextString(); gpu_spair[1] = gd.getNextString(); OrthoMapsCollection maps_collection=null; if (use_saved_collection) { try { Loading @@ -125,9 +163,14 @@ public class ComboMatch { maps_collection = new OrthoMapsCollection(files_list_path); // should have ".list" extensiohn } String [] names = maps_collection.getNames(); //getTemperature() // get all temperatures maps_collection. getAllTemperatures(); // which pair to compare int [] gpu_pair = {1,2}; String [] gpu_spair = {names[gpu_pair[0]],names[gpu_pair[1]]}; // String [] gpu_spair = {names[gpu_ipair[0]],names[gpu_ipair[1]]}; int [] origin = new int[2]; ImagePlus imp_img = maps_collection.renderMulti ( "multi_"+zoom_lev, // String title, Loading Loading @@ -165,14 +208,73 @@ public class ComboMatch { } double [][] affine0 = {{1,0,0},{0,1,0}}; // will always stay the same double [][] affine1 = {{1,0,0},{0,1,0}}; // will be variable // here in meters, relative to vertical point // double [][] affine1 = { // {1,0,-1.47336}, // {0,1,-3.46664}}; // will be variable // here in meters, relative to vertical point //1697877414_404948 - 4 (0) //1697879062_336162 - 9 (1) // double [][] affine1 = { // {1.0002226408872814, -0.007965644488589378, -1.512310157498787}, // {0.006494702666097521, 1.0002691922354188, -3.4553628872407023}}; // double [][] affine1 = {{1,0,0},{0,1,0}}; // will always stay the same // [[1.0001698416441531, 0.0035703780078751575, 1.3965061354976767], // [0.005158652079706154, 1.0014361052510927, 1.204551528740014]]] // double [][] affine1 = {{1,0,1.33}, // {0,1,1.227}}; double [][] affine1 = { {1,0,0}, {0,1,0}}; // affine1[0][2] = 0.64; affine1[1][2] = 1.253; // {"1697877412_004148", "1697877522_274211"}; // // (346.250-348.000)/12.5,(277.000-269.250)/12.5 = (-0.14, 0.62) // affine1[0][2] = -0.14; affine1[1][2] = 0.62; // {"1697877409_353265", "1697877518_773045"}; // // affine1[0][2] = -1.44; affine1[1][2] = 1.653; //"1697877465_672024", "1697877563_587972" // affine1[0][2] = -0.25; affine1[1][2] = -1.627; //{"1697877465_672024", "1697878995_797332"}; // affine1[0][2] = -1.08; affine1[1][2] = 3.267; //{"1697877465_672024", "1697877528_776377"}; // affine1[0][2] = -1.2; affine1[1][2] = -0.9066; //{"1694564245_111645", "1694564701_230240"}; // affine1[0][2] = 0.933; affine1[1][2] = -2.2667; //{"1694564245_111645", "1694564822_637346"}; affine1[0][2] = 2.08; affine1[1][2] = -0.093; //{"1694564248_145989", "1694564819_336247"}; double [][][] affines = {affine0,affine1}; 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 [] zooms = {-3,-1,1000,1000}; debugLevel = 0; boolean batch_mode = true; for (int zi = 0; zi < zooms.length; zi++) { zoom_lev = zooms[zi]; if (zoom_lev >=1000) { break; } // will modify affines[1], later add jtj, weight, smth. else? double [][] corr_pair_rslt = maps_collection.correlateOrthoPair( clt_parameters, // CLTParameters clt_parameters, gpu_spair, // String [] gpu_spair, batch_mode, // boolean batch_mode, gpu_pair, // String [] gpu_spair, affines, // double [][][] affines, // on top of GPS offsets zoom_lev, // int zoom_lev, debugLevel); // final int debugLevel) int render_zoom_lev = maps_collection.ortho_maps[gpu_pair[0]].getOriginalZoomLevel(); ImagePlus imp_img_pair = maps_collection.renderMulti ( "multi_"+gpu_spair[0]+"-"+gpu_spair[1]+"-zoom_"+render_zoom_lev+"_"+zoom_lev, // String title, false, // boolean use_alt, gpu_pair, // int [] indices, // null or which indices to use (normally just 2 for pairwise comparison) affines, // double [][][] affines, // null or [indices.length][2][3] show_centers, // boolean show_centers, render_zoom_lev, // int zoom_level, origin); // int [] origin){ imp_img_pair.show(); System.out.println("Done"); if (debugLevel>-4) { System.out.println("adjusted affines[1] for a pair: "+gpu_spair[0]+"/"+gpu_spair[1]); System.out.println("[["+affines[1][0][0]+","+affines[1][0][1]+","+affines[1][0][2]+"],"); System.out.println(" ["+affines[1][1][0]+","+affines[1][1][1]+","+affines[1][1][2]+"]]"); System.out.println(); } } } if (save_collection) { try { Loading @@ -188,6 +290,20 @@ public class ComboMatch { return true; } /* adjusted affines[1] for a pair: 1697877465_672024/1697877563_587972 RMS= 0.14511264718699468 (0.14577676900752629) [[1.0065661054211072,0.009234141675959222,-1.4706666954418992], [-0.004304610680434175,1.0012437786888277,1.6394608778426498]] adjusted affines[1] for a pair: 1694564245_111645/1694564701_230240 [[1.021246208683918,0.006667337255903127,-1.0137566435443375], [-0.010035351748801541,1.0294363088409202,-0.8395952637299295]] adjusted affines[1] for a pair: 1694564245_111645/1694564822_637346 [[1.0148318094351692,0.01611699521114023,1.1534804399270817], [-0.025584298199020607,1.0182605131307008,-2.157143969635918]] * * double [] offset_xy_second = {0,0}; double [][] corr_pair_rslt = maps_collection. correlateOrthoPair( clt_parameters, // CLTParameters clt_parameters, Loading Loading @@ -438,10 +554,10 @@ public class ComboMatch { clt_parameters.gpu_sigma_b, // final double gpu_sigma_b, // 0.9, 1.1 clt_parameters.gpu_sigma_g, // final double gpu_sigma_g, // 0.6, 0.7 clt_parameters.gpu_sigma_m, // final double gpu_sigma_m, // = 0.4; // 0.7; debugLevel); // final int globalDebugLevel) batch_mode? -3: debugLevel); // final int globalDebugLevel) int tilesX = img_width/GPUTileProcessor.DTT_SIZE; int tilesY = wh[1]/GPUTileProcessor.DTT_SIZE; if (debugLevel > 1) { if (!batch_mode && (debugLevel > 1)) { renderFromTD ( true, // boolean use_reference, "ref"); //String suffix Loading @@ -453,6 +569,7 @@ public class ComboMatch { final double gpu_sigma_log_corr = clt_parameters.getGpuCorrLoGSigma(image_dtt.isMonochrome()); image_dtt.interRectilinearCorrTD( clt_parameters.img_dtt, //final ImageDttParameters imgdtt_params, // Now just extra correlation parameters, later will include, most others batch_mode, // final boolean batch_mode, erase_clt, // final int erase_clt, fpixels[1], // final float [] fpixels, wh, // final int [] wh, // null (use sensor dimensions) or pair {width, height} in pixels Loading Loading @@ -518,10 +635,8 @@ public class ComboMatch { rln_cent_radius, // final double centroid_radius, // 0 - all same weight, > 0 cosine(PI/2*sqrt(dx^2+dy^2)/rad) rln_n_recenter); // final int n_recenter); // re-center window around new maximum. 0 -no refines (single-pass) } boolean show_vector_field = true; boolean show_2d_correlations = true; boolean show_vector_field = (debugLevel>100); // true; boolean show_2d_correlations = (debugLevel>0); // true; final int corr_size = 2 * GPUTileProcessor.DTT_SIZE -1; if (show_2d_correlations) { double [][] dbg_2d_corrs = ImageDtt.corr_partial_dbg( // not used in lwir Loading
src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java +112 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays; import com.elphel.imagej.gpu.TpTask; import com.elphel.imagej.ims.Imx5; 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.QuadCLT; Loading @@ -41,6 +42,7 @@ import ij.plugin.filter.GaussianBlur; import ij.process.FloatProcessor; import ij.process.ImageConverter; import ij.process.ImageProcessor; import loci.formats.FormatException; public class OrthoMap implements Comparable <OrthoMap>, Serializable{ private static final long serialVersionUID = 1L; Loading @@ -55,6 +57,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ 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 @@ -69,6 +72,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public int orig_zoom_level; public boolean orig_zoom_valid; public double need_extra_zoom; public double averageRawPixel = Double.NaN; // measure of scene temperature public transient double averageImagePixel = Double.NaN; // average image pixel value (to combine with raw) transient HashMap <Integer, FloatImageData> images; HashMap <Double, PairwiseOrthoMatch> pairwise_matches; Loading @@ -76,6 +81,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); oos.writeObject(path); oos.writeObject(scenes_path); // lla is not transient // dt is not transient // affine is not transient Loading @@ -97,6 +103,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ path = (String) ois.readObject(); name = getNameFromPath(path); ts= Double.parseDouble(name.replace("_", ".")); scenes_path= (String) ois.readObject(); // lla is not transient // dt is not transient // affine is not transient Loading @@ -107,6 +114,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ // orig_image was not saved // alt_image was not saved images = new HashMap <Integer, FloatImageData>(); // field images was not saved averageImagePixel = Double.NaN; // average image pixel value (to combine with raw) // pairwise_matches is not transient // pairwise_matches = new HashMap<Double, PairwiseOrthoMatch>(); } Loading @@ -129,11 +138,14 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public int getHeight() { return orig_height; } public int getOriginalZoomLevel() { return orig_zoom_level; } // Generate ALT image path from the GEO public static String getAltPath(String path) { int p1 = path.lastIndexOf("."); return path.substring(0,p1)+ALT_SUFFIX+".tiff"; } public static String getNameFromPath(String path) { int p1 = path.lastIndexOf(Prefs.getFileSeparator()); Loading @@ -143,8 +155,65 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ return path.substring(p1+1, p2); } public OrthoMap (String path) { /** * Gets average pixel value of all sensors of the reference scene * @return */ public double getTemperature() { if (Double.isNaN(averageRawPixel)) { final String TIFF_EXT=".tiff"; final File [] raw_files = (new File(scenes_path)).listFiles(); final Thread[] threads = ImageDtt.newThreadArray(); final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ati = new AtomicInteger(0); final double [] avg_arr = new double [threads.length]; final double [] npix_arr = new double [threads.length]; for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); ImagejJp4Tiff imagejJp4Tiff = new ImagejJp4Tiff(); for (int iFile = ai.getAndIncrement(); iFile < raw_files.length; iFile = ai.getAndIncrement()) { if (raw_files[iFile].getName().endsWith(TIFF_EXT)) { ImagePlus imp = null; String spath = raw_files[iFile].toString(); try { imp= imagejJp4Tiff.readTiffJp4(spath); } catch (IOException e) { System.out.println("getImagesMultithreaded IOException " + spath); } catch (FormatException e) { System.out.println("getImagesMultithreaded FormatException " + spath); } if (imp != null) { npix_arr[thread_num] = imp.getWidth()*imp.getHeight(); float [] fpixels = (float[]) imp.getProcessor().getPixels(); for (int i = 0; i < fpixels.length; i++) { avg_arr[thread_num] += fpixels[i]; } avg_arr[thread_num] /= npix_arr[thread_num]; } } } } }; } ImageDtt.startAndJoin(threads); double avg=0, num=0; for (int i = 0; i < avg_arr.length; i++) { avg+=avg_arr[i]*npix_arr[i]; num+=npix_arr[i]; } averageRawPixel = avg/num; } return averageRawPixel; } public OrthoMap ( String path, String scenes_path) { this.path = path; this.scenes_path = scenes_path; name = getNameFromPath(path); ts= Double.parseDouble(name.replace("_", ".")); Properties imp_prop = null; Loading @@ -171,6 +240,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ need_extra_zoom = FloatImageData.needZoomIn(orig_pix_meters); images = new HashMap <Integer, FloatImageData>(); pairwise_matches = new HashMap<Double, PairwiseOrthoMatch>(); averageRawPixel = Double.NaN; // measure of scene temperature averageImagePixel = Double.NaN; // average image pixel value (to combine with raw) } Loading Loading @@ -221,6 +292,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ if (orig_image == null) { readImageData(); } getAveragePixel(); return orig_image; } public FloatImageData getAltData() { Loading @@ -246,9 +318,47 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ if (orig_zoom_valid) { images.put(orig_zoom_level, orig_image); } averageImagePixel = Double.NaN; return true; } public double getAveragePixel() { if (Double.isNaN(averageImagePixel)) { if (orig_image == null) { readImageData(); } final float [] pixels = orig_image.data; final Thread[] threads = ImageDtt.newThreadArray(); final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ati = new AtomicInteger(0); final double [] avg_arr = new double [threads.length]; final double [] npix_arr = new double [threads.length]; for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); for (int ipix = ai.getAndIncrement(); ipix < pixels.length; ipix = ai.getAndIncrement()) { float p = pixels[ipix]; if (!Float.isNaN(p)) { avg_arr[thread_num] += p; npix_arr[thread_num] +=1; } } } }; } ImageDtt.startAndJoin(threads); double avg=0, num=0; for (int i = 0; i < avg_arr.length; i++) { avg+=avg_arr[i]; // *npix_arr[i]; num+=npix_arr[i]; } averageImagePixel = avg/num; } return averageImagePixel; } private boolean readAltData() { // assuming the same scale as main image ImagePlus imp = new ImagePlus(getAltPath(path)); int width = imp.getWidth(); Loading