Loading src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +301 −25 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ public class ComboMatch { public static boolean openTestPairGps( CLTParameters clt_parameters, GPUTileProcessor gpu_tile_processor, // initialized by the caller boolean extract_mines, boolean extract_objects, int debugLevel) { GPU_TILE_PROCESSOR = gpu_tile_processor; PairwiseOrthoMatch pairwiseOrthoMatch = null; Loading @@ -55,6 +55,19 @@ public class ComboMatch { String [] gpu_spair = null; boolean use_marked_image = false; // will be set if found String [] all_scenes = null; ArrayList<ObjectLocation> object_list = null; int zool_lev_objects = 0; if (extract_objects) { if (imp_sel == null) { System.out.println("Need multi-sliced image with marked objects as points"); return false; } int [] zoom_lev_objectsp = new int [1]; object_list = getObjectsFromSelectedImage( imp_sel, zoom_lev_objectsp); // ImagePlus imp) zool_lev_objects = zoom_lev_objectsp[0]; } else { if (imp_sel != null) { pair_names = new String[2]; String [][] all_scenes1=new String[1][]; Loading @@ -68,6 +81,7 @@ public class ComboMatch { all_scenes = all_scenes1[0]; } } } // 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"; Loading Loading @@ -254,6 +268,236 @@ public class ComboMatch { maps_collection = new OrthoMapsCollection(files_list_path); // should have ".list" extension } String [] names = maps_collection.getNames(); if (object_list != null) { int corr_size = 128; int extr_size = 200; // 256; int zoomout = 2; // 1; //2; // 1; 2 for simulated,1 - for extracted int patt_choice = 3; double phaseCoeff = 0.98; double min_corr = 0.01; // 0.0025; // real max >0.005 with scale -500000; int radius_search = 32; int radius_centroid = 4; double lim_rad = 80; // 60; // 40; // 50.0; double trans_width = 60; // 40; // 20.0; double reversal_rad = 0; // 26;// 22; // cut at first direction reversal after double frac_outliers = 0.4; int default_kernel = 1; // 0; // 1; // default kernel choice 25-> 50// 1 for simulated, 0 - for extracted boolean only_correlate = true; int sub_pattern_index = 0; // 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={ "patterns_r30.0_e8.0_ir10.0_ie8.0_is-0.1_or45.0_oe30.0_os-1.5_h8_w0.6_s-40.0_200x200.tif", "old_02.tiff", "patterns_r30.0_e24.0_ir10.0_ie8.0_is-0.1_or62.0_oe40.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e8.0_ir10.0_ie8.0_is-0.1_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e8.0_ir10.0_ie8.0_is0.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e6.0_ir10.0_ie8.0_is0.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e6.0_ir10.0_ie6.0_is-1.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e6.0_ir10.0_ie6.0_is-0.8_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e4.0_ir10.0_ie4.0_is-1.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or45.0_oe20.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or50.0_oe40.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", // best "patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or55.0_oe50.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e5.0_ir12.0_ie5.0_is0.0_or50.0_oe40.0_os-1.0_h8_w0.6_s-60.0_200x200.tif" }; GenericJTabbedDialog gdo = new GenericJTabbedDialog("Set image pair",1200,900); gdo.addNumericField("Correlation size", corr_size, 0,4,"", "Correlation size, power of 2"); gdo.addNumericField("Extracted size", extr_size, 0,4,"", "size of a square output size"); // gdo.addStringField ("Pattern directory", OrthoMap.pattern_dir, 180, "Absolute path including trailing \"/\"."); // gdo.addChoice ("Pattern filename:", OrthoMap.pattern_files, OrthoMap.pattern_files[patt_choice]); gdo.addStringField ("Pattern directory", pattern_dir, 180, "Absolute path including trailing \"/\"."); gdo.addChoice ("Pattern filename:", pattern_files, OrthoMap.pattern_files[patt_choice]); gdo.addNumericField("Zoom-out factor", zoomout, 0,4,"x", "Reduce pattern resolution to match image."); gdo.addNumericField("Phase correlation coefficient", phaseCoeff, 3,7,"","1.0 - pure phase correlation, 0.0 - regular correlation."); gdo.addNumericField("Minimal correlation", min_corr, 5,7,"","Minimal correlation value to keep."); gdo.addNumericField("Search radius", radius_search, 0,4,"pix", "Radius to search for the object center."); gdo.addNumericField("Centroid radius", radius_centroid, 0,4,"pix", "Limit centroid radius."); gdo.addMessage("Clean-up circular pattern:"); gdo.addNumericField("Limit output patter radius", lim_rad, 0,4,"pix", "All zero outside this radius."); gdo.addNumericField("Transition width", trans_width, 0,4,"pix", "cosine transition width."); gdo.addNumericField("Last reversal radius", reversal_rad, 0,4,"pix", "Cut at first derivative reversal after this."); gdo.addNumericField("Outlier fraction", frac_outliers, 3,7,"", "Remove outliers when averaging different directions."); gdo.addCheckbox ("Only correlate", only_correlate, "do not generate circular kernel."); gdo.addNumericField("subpattern index", sub_pattern_index,0,4,"", "0 - full pattern, 1-8 - half-pattern."); //only_correlate gdo.showDialog(); 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(); phaseCoeff= gdo.getNextNumber(); min_corr= gdo.getNextNumber(); radius_search= (int) gdo.getNextNumber(); radius_centroid= (int) gdo.getNextNumber(); lim_rad= gdo.getNextNumber(); trans_width= gdo.getNextNumber(); reversal_rad= gdo.getNextNumber(); frac_outliers= gdo.getNextNumber(); only_correlate = gdo.getNextBoolean(); sub_pattern_index= (int) gdo.getNextNumber(); System.out.println("Will extract objects here, image zoom_level="+zool_lev_objects); for (ObjectLocation ol: object_list) { System.out.println(ol.name+": "+ol.xy_meters[0]+"/"+ol.xy_meters[1]); } maps_collection.reverseRender( object_list, // ArrayList<ObjectLocation> objects, zool_lev_objects); // int zoom_level){ System.out.println("Object coordinates in source images: "); for (ObjectLocation ol: object_list) { System.out.println(ol.name+": "+ol.getPixels()[0]+"/"+ol.getPixels()[1]); } double [][] object_stack = new double [object_list.size()][]; String [] object_titles = new String [object_stack.length]; for (int i = 0; i < object_stack.length; i++) { ObjectLocation ol = object_list.get(i); object_titles[i] = ol.getName(); object_stack[i] = ol.extractObjectImage( maps_collection, extr_size); } ImagePlus imp_obj = ShowDoubleFloatArrays.makeArrays( object_stack, extr_size, extr_size, OrthoMap.removeKnownExtension(imp_sel.getTitle())+"-OBJECT_"+extr_size+"x"+extr_size+".tiff", object_titles); // test_titles, imp_obj.show(); // get pattern(s) // String pattern_path=OrthoMap.pattern_dir+pattern_file; String pattern_path=pattern_dir+pattern_file; ImagePlus imp_pattern = new ImagePlus(pattern_path); int pattern_size = imp_pattern.getWidth(); if (pattern_size == 0) { System.out.println("testPatternCorrelate(): pattern \""+pattern_path+"\" is not found."); return false; } System.out.println("Using pattern file: "+pattern_path+", subpattern="+sub_pattern_index); ImageStack stack_pattern = imp_pattern.getStack(); int nSlices = stack_pattern.getSize(); double [][] patterns = new double[nSlices][]; String [] pattern_labels = new String[nSlices]; for (int n = 0; n < patterns.length; n++) { pattern_labels[n]=stack_pattern.getShortSliceLabel(n+1); float [] fpixels_pattern = (float[]) stack_pattern.getPixels(n+1); patterns[n]=new double[fpixels_pattern.length]; for (int i = 0; i < fpixels_pattern.length; i++) { patterns[n][i] = fpixels_pattern[i]; } } double [] kernel = OrthoMap.getConvolutionKernel(default_kernel); double [][] centers = new double [object_stack.length][]; for (int i = 0; i < object_stack.length; i++) { String dbg_prefix = "corr_patt_"+i; ObjectLocation ol = object_list.get(i); centers[i] = ObjectLocation.getPatternCenter( object_stack[i], // double [] data, patterns[sub_pattern_index], // double [] pattern, kernel, // double [] kernel, zoomout, // int zoomout, phaseCoeff, // double phaseCoeff, min_corr, // double min_corr, radius_search, // int radius_search, radius_centroid, // int radius_centroid, dbg_prefix, // String dbg_prefix, debugLevel); // int debugLevel) System.out.println(i+": center at "+centers[i][0]+"/"+centers[i][1]+", strength="+centers[i][2]); } PointRoi roi = new PointRoi(); roi.setOptions("label"); for (int i = 0; i < centers.length; i++) { roi.addPoint(centers[i][0]+extr_size/2, centers[i][1]+extr_size/2, i+1); // ,1); } imp_obj.setRoi(roi); if (only_correlate) { System.out.println("testPatternCorrelate(): correlation DONE, only_correlate is set to true, exiting"); return true; } // imp_obj.show(); // First process each captured object separately, then compare and average? // TODO: use finer grid, deconvolve with altitude kernel, calculate effective width of the pattern double [][] output_patterns = new double [object_stack.length+1][]; String [] output_patt_titles = new String[output_patterns.length]; output_patt_titles[output_patt_titles.length-1]= "average"; output_patterns[object_stack.length] = new double [corr_size*corr_size]; //object_titles boolean debug_good = debugLevel > -4; boolean [][] good_pix = debug_good ? (new boolean[object_stack.length][extr_size*extr_size]) : null; // debugging String settings_str = "_fo"+frac_outliers+"_lr"+lim_rad+"_tw"+trans_width+"_rr"+reversal_rad; for (int i = 0; i < object_stack.length; i++) { output_patterns[i] = ObjectLocation.getRadialPattern( object_stack[i], // double [] data, centers[i], // double [] xy_offs, corr_size, // int corr_size, lim_rad, // double lim_rad, // outside all 0 trans_width, //double trans_width, // lim_rad-trans_width - start reducing frac_outliers, // double frac_outliers, reversal_rad, // double reversal_rad, ((good_pix != null)? good_pix[i] : null), // boolean [] good, // null or same size as data debugLevel); // int debugLevel) output_patt_titles[i] = object_titles[i]; for (int j = 0; j < output_patterns[i].length; j++) { output_patterns[object_stack.length][j] += output_patterns[i][j]; } } for (int j = 0; j < output_patterns[0].length; j++) { output_patterns[object_stack.length][j] /= object_stack.length; } ImagePlus imp_out_patt = ShowDoubleFloatArrays.makeArrays( output_patterns, corr_size, corr_size, OrthoMap.removeKnownExtension(imp_sel.getTitle())+"-PATTERN"+settings_str+"_"+corr_size+"x"+corr_size+".tiff", output_patt_titles); // test_titles, imp_out_patt.show(); if (good_pix != null) { double [][] object_stack_masked = new double [2 * object_stack.length][]; String [] object_titles_masked = new String [2 * object_stack.length]; PointRoi roi_masked = new PointRoi(); roi_masked.setOptions("label"); for (int i = 0; i < centers.length; i++) { roi_masked.addPoint(centers[i][0]+extr_size/2, centers[i][1]+extr_size/2, 2*i+1); // ,1); roi_masked.addPoint(centers[i][0]+extr_size/2, centers[i][1]+extr_size/2, 2*i+2); // ,1); } for (int i = 0; i < object_stack.length; i++) { object_stack_masked[2*i + 0] = object_stack[i]; object_stack_masked[2*i + 1] = object_stack[i].clone(); for (int j = 0; j < object_stack[i].length; j++) { if (!good_pix[i][j]) { object_stack_masked[2*i + 1][j] = Double.NaN; } } } ImagePlus imp_obj_masked = ShowDoubleFloatArrays.makeArrays( object_stack_masked, extr_size, extr_size, OrthoMap.removeKnownExtension(imp_sel.getTitle())+"-OBJECT_MASKED"+settings_str+"_"+extr_size+"x"+extr_size+".tiff", object_titles_masked); // test_titles, imp_obj_masked.setRoi(roi_masked); imp_obj_masked.show(); } return true; } if (use_marked_image) { // verify matching names //all_scenes Loading Loading @@ -691,6 +935,50 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341 return null; } public static ArrayList<ObjectLocation> getObjectsFromSelectedImage( ImagePlus imp, int [] zoom_levp) { // get zoom from the name and list of the slice names prefixes (before second "_" String title = imp.getTitle(); String[] tokens = title.replace(".","_").split("_"); for (int i = 0; i < tokens.length; i++) { if (tokens[i].startsWith("zoom")) { int zoom_level = Integer.parseInt(tokens[i].substring(4)); System.out.println("zoom level = "+zoom_level); double pix_size = OrthoMap.getPixelSizeMeters (zoom_level); // meters ImageStack stack_scenes = imp.getStack(); int nSlices = stack_scenes.getSize(); String [] scene_names = new String [nSlices]; for (int n = 0; n < scene_names.length; n++) { scene_names[n] = stack_scenes.getSliceLabel(n+1).substring(0,17); } PointRoi pRoi = (PointRoi) imp.getRoi(); FloatPolygon fp = pRoi.getContainedFloatPoints(); // Use only 2 last markers if (fp == null) { System.out.println("getPairFromSelectedImage(): no markers found"); return null; } ArrayList<ObjectLocation> list = new ArrayList<ObjectLocation>(); for (int np = 0; np < fp.npoints; np++) { String name = scene_names[pRoi.getPointPosition(np) -1]; double [] xy_meters = { fp.xpoints[np] * pix_size, fp.ypoints[np] * pix_size}; list.add(new ObjectLocation ( name, // String name, xy_meters)); // double [] xy_meters) } if (zoom_levp != null) { zoom_levp[0] = zoom_level; } return list; } } return null; } public static String [] getPairChoices( int [][] pairs, String [] names) { Loading @@ -703,18 +991,6 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341 /* public static TDCorrTile [] rectilinearCorrelate_TD( // scene0/scene1 final CLTParameters clt_parameters, final float [][] fpixels, // to check for empty final int img_width, Rectangle woi, // if null, use full GPU window final double [][][] affine, // [2][2][3] affine coefficients to translate common to 2 images final boolean batch_mode, final int debugLevel) { */ public static double [][][] rectilinearVectorField( // scene0/scene1 final CLTParameters clt_parameters, final float [][] fpixels, // to check for empty Loading src/main/java/com/elphel/imagej/orthomosaic/ObjectLocation.java +388 −0 File changed.Preview size limit exceeded, changes collapsed. Show changes src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java +39 −40 Original line number Diff line number Diff line Loading @@ -67,6 +67,20 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ "/media/elphel/NVME/lwir16-proc/ortho_videos/kernel_50_100.tiff" }; public static String pattern_dir= "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/debug/mines/pattern_25m_zoom1/synthetic/"; public static String [] pattern_files= {"patterns_50m_zoom1_200x200.tiff", "patterns_50m_evening_zoom1_200x200.tiff", "patterns_50m_evening_01_zoom1_200x200_00.tiff", "patterns_50m_evening_02_zoom1_200x200_00.tiff", "patterns_50m_evening_03_zoom1_200x200_00.tiff", "patterns_50m_evening_04_zoom1_200x200_00.tiff", "patterns_50m_evening_05_zoom1_200x200_00.tiff", "mine1_zoom0.tiff", "mine2_zoom0.tiff", "mine3_zoom0.tiff", "mine4_zoom0.tiff", "mine6_zoom0.tiff"}; public static final String ALT_SUFFIX = "-ALT"; Loading Loading @@ -1095,9 +1109,12 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ * @return square kernel as a 1-d double array or null */ public static double [] getConvolutionKernel() { return getConvolutionKernel(kernel_paths.length-1); } public static double [] getConvolutionKernel(int choice) { String kernel_path = null; GenericJTabbedDialog gds = new GenericJTabbedDialog("Select kernel path",1200,400); gds.addChoice("Kernel path:", kernel_paths, kernel_paths[kernel_paths.length-1]); gds.addChoice("Kernel path:", kernel_paths, kernel_paths[choice]); gds.showDialog(); if (gds.wasCanceled()) return null; int kernel_index = gds.getNextChoiceIndex(); Loading Loading @@ -3038,6 +3055,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ double [] wnd_in, double phaseCoeff) { // phaseCoeff = 0.5; boolean dbg=false; double [] data = data_in.clone(); double [] pattern = pattern_in.clone(); double [] wnd = wnd_in.clone(); Loading @@ -3047,7 +3065,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ for (int i = 0; i < data.length; i++) { data[i] *= wnd[i]; } { if (dbg) { String [] rslt_titles= {"original","window","windowed","pattern"}; ShowDoubleFloatArrays.showArrays( new double[][] {data_orig, wnd, data, pattern}, Loading Loading @@ -3096,7 +3114,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ } } { if (dbg) { String [] rslt_titles= {"corr", "original","window","windowed","pattern"}; ShowDoubleFloatArrays.showArrays( new double[][] {corr_out, data_orig, wnd, data_orig2, pattern_orig}, Loading @@ -3106,7 +3124,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ convolve?"output_conv":("output_corr"+phaseCoeff), rslt_titles); } System.out.println("testPhaseCorr() done"); if (dbg) System.out.println("testPhaseCorr() done"); return corr_out; } Loading Loading @@ -3192,8 +3210,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public static void testPatternCorrelate( ImagePlus imp_src) { /* String pattern_dir= "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/debug/mines/pattern_25m_zoom1/synthetic/"; // String pattern_file= "patterns_50m_zoom1_200x200.tiff"; String [] pattern_files= {"patterns_50m_zoom1_200x200.tiff", "patterns_50m_evening_zoom1_200x200.tiff", Loading @@ -3202,6 +3220,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ "patterns_50m_evening_03_zoom1_200x200_00.tiff", "patterns_50m_evening_04_zoom1_200x200_00.tiff", "patterns_50m_evening_05_zoom1_200x200_00.tiff"}; */ int zoomout = 2; // 1; int corr_size = 128; // 256; double phaseCoeff = 0.5; Loading Loading @@ -3297,7 +3316,6 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ double [][] corrs_out = new double[patterns.length][]; double [][] convolve_out = new double[patterns.length][]; // double [][] lim_corr = new double[patterns.length][]; double [][] corr_patterns = new double[patterns.length][]; for (int n = 0; n < patterns.length; n++) { corr_patterns[n] = patternZoomCropPad( Loading Loading @@ -3331,6 +3349,11 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ height, removeKnownExtension(imp_src.getTitle())+"-PATTERN_CORRS", patt_titles); // test_titles, if (src_marks != null) { PointRoi roi = new PointRoi(); roi.setOptions("label"); Loading Loading @@ -3881,40 +3904,16 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public static void testPatternGenerate() { int half_size = 100; boolean half_pix = false; // center between pixels boolean evening_mode = false; // glare around object, use radius double radius_out= 42; double edge_out = 6; double scale_out = 1.5; boolean evening_mode = true; // false; // glare around object, use radius double radius = 30; // 32; // 32; double edge= 15; // 4; double radius_in= 15; // if 0 - skip double edge_in = 8; double scale_in = -0.05; double radius_out= 42; double edge_out = 6; double scale_out = 1.5; double scale = -200; // black 200 if (evening_mode) { radius_out= 42; edge_out = 8; scale_out =-1.5; // relative to scale radius = 30; // 32; // 32; edge= 15; // 4; radius_in= 10; // if 0 - skip edge_in = 8; scale_in = -0.7; scale = -40; // black 200 } else { radius_out= 42; edge_out = 6; scale_out =.08; radius = 30; // 32; // 32; edge= 15; // 4; radius_in= 15; // if 0 - skip edge_in = 8; scale_in = -0.05; scale = -170; // black 200 } boolean normalize = false; int halves_number = 8; // hidden mines - number of diameter cuts Loading @@ -3930,15 +3929,15 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ if (gd0.wasCanceled()) return; evening_mode= gd0.getNextBoolean(); if (evening_mode) { radius_out= 62; // 42; edge_out = 40; // 8; scale_out =-1.5; // relative to scale radius = 30; // 32; // 32; edge= 24; // 8; // 4; edge= 8; // 8; // 4; radius_in= 10; // if 0 - skip edge_in = 8; scale_in = -0.1; // 7; scale = -40; // black 200 scale_in = 0; // -0.1; // 7; radius_out= 45; // 42; edge_out = 30; // 8; scale_out =-1.0; // relative to scale scale = -60; // black 200 } else { radius_out= 42; edge_out = 6; Loading src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java +58 −0 Original line number Diff line number Diff line Loading @@ -396,6 +396,64 @@ public class OrthoMapsCollection implements Serializable{ return bounds; } /** * Use object coordinates (now metric) on the composite image to * determine corresponding pixel coordinates of the source images * @param objects ArrayList of objects with the scene name and xy coordinates * in the composite image. Will fill in pixel coordinates of the objects * @param zoom_level zoom level of the composite image */ public void reverseRender( ArrayList<ObjectLocation> objects, int zoom_level){ int [][] bounds = getBoundsPixels( // should be for rectified, {-bounds[0][0], -bounds[0][1]} - exact center zoom_level, null); int width = bounds[0][1] - bounds[0][0]; // bounds[x][0] - negative int height = bounds[1][1] - bounds[1][0]; /* int [] indices = new int [ortho_maps.length]; //maybe will get rid of for (int i = 0; i < indices.length; i++) { indices[i] = i; } */ final int reference_index = 0; for (ObjectLocation ol: objects) { int nmap =getIndex(ol.getName()); final double scale = 1.0/OrthoMap.getPixelSizeMeters(zoom_level); final double src_scale = 1.0/OrthoMap.getPixelSizeMeters(ortho_maps[nmap].orig_zoom_level); // pix per meter double [][] mbounds = ortho_maps[nmap].getBoundsMeters(true); // keep original bounds double [] enu_offset = ortho_maps[reference_index].enuOffsetTo(ortho_maps[nmap]); double [] scaled_out_center = { // xy center to apply affine to -bounds[0][0] + scale * enu_offset[0], -bounds[1][0] - scale * enu_offset[1]}; double [] metric_center = { // back to meters to match objects scaled_out_center[0]/scale, scaled_out_center[1]/scale}; double dX = ol.getMetric()[0]-metric_center[0]; // matching dX, dY in renderMulti() double dY = ol.getMetric()[1]-metric_center[1]; // final int [][] obounds = new int [2][2]; // output (rectified, combined) image bounds, relative to thje top-left // for (int n = 0; n< 2; n++) { // obounds[n][0] = (int) Math.floor(scaled_out_center[n] + scale*mbounds[n][0]); // obounds[n][1] = (int) Math.ceil (scaled_out_center[n] + scale*mbounds[n][1]); // } // Output window size (keep original affine - OK if will not exactly fit) // final int ownd_width = obounds[0][1] - obounds[0][0]; // final int ownd_height = obounds[1][1] - obounds[1][0]; // final int ownd_len = ownd_width * ownd_height; double [][] src_bounds=ortho_maps[nmap].getBoundsMeters (true); // using original affines final double [] src_center = {-src_bounds[0][0],-src_bounds[1][0]}; // x,y center offset in the source image final double [][] affine = ortho_maps[nmap].affine; // only here use provided // final int src_width = ortho_maps[nmap].getImageData().width; // final int src_height = ortho_maps[nmap].getImageData().height; // final float [] src_img = ortho_maps[nmap].getImageData().data; // FIXME: will not use double [] xy_src = { // pixels of the source image src_scale * (affine[0][0]*dX + affine[0][1]*dY + affine[0][2] + src_center[0]), src_scale * (affine[1][0]*dX + affine[1][1]*dY + affine[1][2] + src_center[1])}; ol.setPixels(xy_src); } } public ImagePlus renderMulti ( Loading Loading
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +301 −25 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ public class ComboMatch { public static boolean openTestPairGps( CLTParameters clt_parameters, GPUTileProcessor gpu_tile_processor, // initialized by the caller boolean extract_mines, boolean extract_objects, int debugLevel) { GPU_TILE_PROCESSOR = gpu_tile_processor; PairwiseOrthoMatch pairwiseOrthoMatch = null; Loading @@ -55,6 +55,19 @@ public class ComboMatch { String [] gpu_spair = null; boolean use_marked_image = false; // will be set if found String [] all_scenes = null; ArrayList<ObjectLocation> object_list = null; int zool_lev_objects = 0; if (extract_objects) { if (imp_sel == null) { System.out.println("Need multi-sliced image with marked objects as points"); return false; } int [] zoom_lev_objectsp = new int [1]; object_list = getObjectsFromSelectedImage( imp_sel, zoom_lev_objectsp); // ImagePlus imp) zool_lev_objects = zoom_lev_objectsp[0]; } else { if (imp_sel != null) { pair_names = new String[2]; String [][] all_scenes1=new String[1][]; Loading @@ -68,6 +81,7 @@ public class ComboMatch { all_scenes = all_scenes1[0]; } } } // 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"; Loading Loading @@ -254,6 +268,236 @@ public class ComboMatch { maps_collection = new OrthoMapsCollection(files_list_path); // should have ".list" extension } String [] names = maps_collection.getNames(); if (object_list != null) { int corr_size = 128; int extr_size = 200; // 256; int zoomout = 2; // 1; //2; // 1; 2 for simulated,1 - for extracted int patt_choice = 3; double phaseCoeff = 0.98; double min_corr = 0.01; // 0.0025; // real max >0.005 with scale -500000; int radius_search = 32; int radius_centroid = 4; double lim_rad = 80; // 60; // 40; // 50.0; double trans_width = 60; // 40; // 20.0; double reversal_rad = 0; // 26;// 22; // cut at first direction reversal after double frac_outliers = 0.4; int default_kernel = 1; // 0; // 1; // default kernel choice 25-> 50// 1 for simulated, 0 - for extracted boolean only_correlate = true; int sub_pattern_index = 0; // 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={ "patterns_r30.0_e8.0_ir10.0_ie8.0_is-0.1_or45.0_oe30.0_os-1.5_h8_w0.6_s-40.0_200x200.tif", "old_02.tiff", "patterns_r30.0_e24.0_ir10.0_ie8.0_is-0.1_or62.0_oe40.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e8.0_ir10.0_ie8.0_is-0.1_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e8.0_ir10.0_ie8.0_is0.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e6.0_ir10.0_ie8.0_is0.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e6.0_ir10.0_ie6.0_is-1.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e6.0_ir10.0_ie6.0_is-0.8_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e4.0_ir10.0_ie4.0_is-1.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or45.0_oe20.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or50.0_oe40.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", // best "patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or55.0_oe50.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", "patterns_r30.0_e5.0_ir12.0_ie5.0_is0.0_or50.0_oe40.0_os-1.0_h8_w0.6_s-60.0_200x200.tif" }; GenericJTabbedDialog gdo = new GenericJTabbedDialog("Set image pair",1200,900); gdo.addNumericField("Correlation size", corr_size, 0,4,"", "Correlation size, power of 2"); gdo.addNumericField("Extracted size", extr_size, 0,4,"", "size of a square output size"); // gdo.addStringField ("Pattern directory", OrthoMap.pattern_dir, 180, "Absolute path including trailing \"/\"."); // gdo.addChoice ("Pattern filename:", OrthoMap.pattern_files, OrthoMap.pattern_files[patt_choice]); gdo.addStringField ("Pattern directory", pattern_dir, 180, "Absolute path including trailing \"/\"."); gdo.addChoice ("Pattern filename:", pattern_files, OrthoMap.pattern_files[patt_choice]); gdo.addNumericField("Zoom-out factor", zoomout, 0,4,"x", "Reduce pattern resolution to match image."); gdo.addNumericField("Phase correlation coefficient", phaseCoeff, 3,7,"","1.0 - pure phase correlation, 0.0 - regular correlation."); gdo.addNumericField("Minimal correlation", min_corr, 5,7,"","Minimal correlation value to keep."); gdo.addNumericField("Search radius", radius_search, 0,4,"pix", "Radius to search for the object center."); gdo.addNumericField("Centroid radius", radius_centroid, 0,4,"pix", "Limit centroid radius."); gdo.addMessage("Clean-up circular pattern:"); gdo.addNumericField("Limit output patter radius", lim_rad, 0,4,"pix", "All zero outside this radius."); gdo.addNumericField("Transition width", trans_width, 0,4,"pix", "cosine transition width."); gdo.addNumericField("Last reversal radius", reversal_rad, 0,4,"pix", "Cut at first derivative reversal after this."); gdo.addNumericField("Outlier fraction", frac_outliers, 3,7,"", "Remove outliers when averaging different directions."); gdo.addCheckbox ("Only correlate", only_correlate, "do not generate circular kernel."); gdo.addNumericField("subpattern index", sub_pattern_index,0,4,"", "0 - full pattern, 1-8 - half-pattern."); //only_correlate gdo.showDialog(); 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(); phaseCoeff= gdo.getNextNumber(); min_corr= gdo.getNextNumber(); radius_search= (int) gdo.getNextNumber(); radius_centroid= (int) gdo.getNextNumber(); lim_rad= gdo.getNextNumber(); trans_width= gdo.getNextNumber(); reversal_rad= gdo.getNextNumber(); frac_outliers= gdo.getNextNumber(); only_correlate = gdo.getNextBoolean(); sub_pattern_index= (int) gdo.getNextNumber(); System.out.println("Will extract objects here, image zoom_level="+zool_lev_objects); for (ObjectLocation ol: object_list) { System.out.println(ol.name+": "+ol.xy_meters[0]+"/"+ol.xy_meters[1]); } maps_collection.reverseRender( object_list, // ArrayList<ObjectLocation> objects, zool_lev_objects); // int zoom_level){ System.out.println("Object coordinates in source images: "); for (ObjectLocation ol: object_list) { System.out.println(ol.name+": "+ol.getPixels()[0]+"/"+ol.getPixels()[1]); } double [][] object_stack = new double [object_list.size()][]; String [] object_titles = new String [object_stack.length]; for (int i = 0; i < object_stack.length; i++) { ObjectLocation ol = object_list.get(i); object_titles[i] = ol.getName(); object_stack[i] = ol.extractObjectImage( maps_collection, extr_size); } ImagePlus imp_obj = ShowDoubleFloatArrays.makeArrays( object_stack, extr_size, extr_size, OrthoMap.removeKnownExtension(imp_sel.getTitle())+"-OBJECT_"+extr_size+"x"+extr_size+".tiff", object_titles); // test_titles, imp_obj.show(); // get pattern(s) // String pattern_path=OrthoMap.pattern_dir+pattern_file; String pattern_path=pattern_dir+pattern_file; ImagePlus imp_pattern = new ImagePlus(pattern_path); int pattern_size = imp_pattern.getWidth(); if (pattern_size == 0) { System.out.println("testPatternCorrelate(): pattern \""+pattern_path+"\" is not found."); return false; } System.out.println("Using pattern file: "+pattern_path+", subpattern="+sub_pattern_index); ImageStack stack_pattern = imp_pattern.getStack(); int nSlices = stack_pattern.getSize(); double [][] patterns = new double[nSlices][]; String [] pattern_labels = new String[nSlices]; for (int n = 0; n < patterns.length; n++) { pattern_labels[n]=stack_pattern.getShortSliceLabel(n+1); float [] fpixels_pattern = (float[]) stack_pattern.getPixels(n+1); patterns[n]=new double[fpixels_pattern.length]; for (int i = 0; i < fpixels_pattern.length; i++) { patterns[n][i] = fpixels_pattern[i]; } } double [] kernel = OrthoMap.getConvolutionKernel(default_kernel); double [][] centers = new double [object_stack.length][]; for (int i = 0; i < object_stack.length; i++) { String dbg_prefix = "corr_patt_"+i; ObjectLocation ol = object_list.get(i); centers[i] = ObjectLocation.getPatternCenter( object_stack[i], // double [] data, patterns[sub_pattern_index], // double [] pattern, kernel, // double [] kernel, zoomout, // int zoomout, phaseCoeff, // double phaseCoeff, min_corr, // double min_corr, radius_search, // int radius_search, radius_centroid, // int radius_centroid, dbg_prefix, // String dbg_prefix, debugLevel); // int debugLevel) System.out.println(i+": center at "+centers[i][0]+"/"+centers[i][1]+", strength="+centers[i][2]); } PointRoi roi = new PointRoi(); roi.setOptions("label"); for (int i = 0; i < centers.length; i++) { roi.addPoint(centers[i][0]+extr_size/2, centers[i][1]+extr_size/2, i+1); // ,1); } imp_obj.setRoi(roi); if (only_correlate) { System.out.println("testPatternCorrelate(): correlation DONE, only_correlate is set to true, exiting"); return true; } // imp_obj.show(); // First process each captured object separately, then compare and average? // TODO: use finer grid, deconvolve with altitude kernel, calculate effective width of the pattern double [][] output_patterns = new double [object_stack.length+1][]; String [] output_patt_titles = new String[output_patterns.length]; output_patt_titles[output_patt_titles.length-1]= "average"; output_patterns[object_stack.length] = new double [corr_size*corr_size]; //object_titles boolean debug_good = debugLevel > -4; boolean [][] good_pix = debug_good ? (new boolean[object_stack.length][extr_size*extr_size]) : null; // debugging String settings_str = "_fo"+frac_outliers+"_lr"+lim_rad+"_tw"+trans_width+"_rr"+reversal_rad; for (int i = 0; i < object_stack.length; i++) { output_patterns[i] = ObjectLocation.getRadialPattern( object_stack[i], // double [] data, centers[i], // double [] xy_offs, corr_size, // int corr_size, lim_rad, // double lim_rad, // outside all 0 trans_width, //double trans_width, // lim_rad-trans_width - start reducing frac_outliers, // double frac_outliers, reversal_rad, // double reversal_rad, ((good_pix != null)? good_pix[i] : null), // boolean [] good, // null or same size as data debugLevel); // int debugLevel) output_patt_titles[i] = object_titles[i]; for (int j = 0; j < output_patterns[i].length; j++) { output_patterns[object_stack.length][j] += output_patterns[i][j]; } } for (int j = 0; j < output_patterns[0].length; j++) { output_patterns[object_stack.length][j] /= object_stack.length; } ImagePlus imp_out_patt = ShowDoubleFloatArrays.makeArrays( output_patterns, corr_size, corr_size, OrthoMap.removeKnownExtension(imp_sel.getTitle())+"-PATTERN"+settings_str+"_"+corr_size+"x"+corr_size+".tiff", output_patt_titles); // test_titles, imp_out_patt.show(); if (good_pix != null) { double [][] object_stack_masked = new double [2 * object_stack.length][]; String [] object_titles_masked = new String [2 * object_stack.length]; PointRoi roi_masked = new PointRoi(); roi_masked.setOptions("label"); for (int i = 0; i < centers.length; i++) { roi_masked.addPoint(centers[i][0]+extr_size/2, centers[i][1]+extr_size/2, 2*i+1); // ,1); roi_masked.addPoint(centers[i][0]+extr_size/2, centers[i][1]+extr_size/2, 2*i+2); // ,1); } for (int i = 0; i < object_stack.length; i++) { object_stack_masked[2*i + 0] = object_stack[i]; object_stack_masked[2*i + 1] = object_stack[i].clone(); for (int j = 0; j < object_stack[i].length; j++) { if (!good_pix[i][j]) { object_stack_masked[2*i + 1][j] = Double.NaN; } } } ImagePlus imp_obj_masked = ShowDoubleFloatArrays.makeArrays( object_stack_masked, extr_size, extr_size, OrthoMap.removeKnownExtension(imp_sel.getTitle())+"-OBJECT_MASKED"+settings_str+"_"+extr_size+"x"+extr_size+".tiff", object_titles_masked); // test_titles, imp_obj_masked.setRoi(roi_masked); imp_obj_masked.show(); } return true; } if (use_marked_image) { // verify matching names //all_scenes Loading Loading @@ -691,6 +935,50 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341 return null; } public static ArrayList<ObjectLocation> getObjectsFromSelectedImage( ImagePlus imp, int [] zoom_levp) { // get zoom from the name and list of the slice names prefixes (before second "_" String title = imp.getTitle(); String[] tokens = title.replace(".","_").split("_"); for (int i = 0; i < tokens.length; i++) { if (tokens[i].startsWith("zoom")) { int zoom_level = Integer.parseInt(tokens[i].substring(4)); System.out.println("zoom level = "+zoom_level); double pix_size = OrthoMap.getPixelSizeMeters (zoom_level); // meters ImageStack stack_scenes = imp.getStack(); int nSlices = stack_scenes.getSize(); String [] scene_names = new String [nSlices]; for (int n = 0; n < scene_names.length; n++) { scene_names[n] = stack_scenes.getSliceLabel(n+1).substring(0,17); } PointRoi pRoi = (PointRoi) imp.getRoi(); FloatPolygon fp = pRoi.getContainedFloatPoints(); // Use only 2 last markers if (fp == null) { System.out.println("getPairFromSelectedImage(): no markers found"); return null; } ArrayList<ObjectLocation> list = new ArrayList<ObjectLocation>(); for (int np = 0; np < fp.npoints; np++) { String name = scene_names[pRoi.getPointPosition(np) -1]; double [] xy_meters = { fp.xpoints[np] * pix_size, fp.ypoints[np] * pix_size}; list.add(new ObjectLocation ( name, // String name, xy_meters)); // double [] xy_meters) } if (zoom_levp != null) { zoom_levp[0] = zoom_level; } return list; } } return null; } public static String [] getPairChoices( int [][] pairs, String [] names) { Loading @@ -703,18 +991,6 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341 /* public static TDCorrTile [] rectilinearCorrelate_TD( // scene0/scene1 final CLTParameters clt_parameters, final float [][] fpixels, // to check for empty final int img_width, Rectangle woi, // if null, use full GPU window final double [][][] affine, // [2][2][3] affine coefficients to translate common to 2 images final boolean batch_mode, final int debugLevel) { */ public static double [][][] rectilinearVectorField( // scene0/scene1 final CLTParameters clt_parameters, final float [][] fpixels, // to check for empty Loading
src/main/java/com/elphel/imagej/orthomosaic/ObjectLocation.java +388 −0 File changed.Preview size limit exceeded, changes collapsed. Show changes
src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java +39 −40 Original line number Diff line number Diff line Loading @@ -67,6 +67,20 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ "/media/elphel/NVME/lwir16-proc/ortho_videos/kernel_50_100.tiff" }; public static String pattern_dir= "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/debug/mines/pattern_25m_zoom1/synthetic/"; public static String [] pattern_files= {"patterns_50m_zoom1_200x200.tiff", "patterns_50m_evening_zoom1_200x200.tiff", "patterns_50m_evening_01_zoom1_200x200_00.tiff", "patterns_50m_evening_02_zoom1_200x200_00.tiff", "patterns_50m_evening_03_zoom1_200x200_00.tiff", "patterns_50m_evening_04_zoom1_200x200_00.tiff", "patterns_50m_evening_05_zoom1_200x200_00.tiff", "mine1_zoom0.tiff", "mine2_zoom0.tiff", "mine3_zoom0.tiff", "mine4_zoom0.tiff", "mine6_zoom0.tiff"}; public static final String ALT_SUFFIX = "-ALT"; Loading Loading @@ -1095,9 +1109,12 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ * @return square kernel as a 1-d double array or null */ public static double [] getConvolutionKernel() { return getConvolutionKernel(kernel_paths.length-1); } public static double [] getConvolutionKernel(int choice) { String kernel_path = null; GenericJTabbedDialog gds = new GenericJTabbedDialog("Select kernel path",1200,400); gds.addChoice("Kernel path:", kernel_paths, kernel_paths[kernel_paths.length-1]); gds.addChoice("Kernel path:", kernel_paths, kernel_paths[choice]); gds.showDialog(); if (gds.wasCanceled()) return null; int kernel_index = gds.getNextChoiceIndex(); Loading Loading @@ -3038,6 +3055,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ double [] wnd_in, double phaseCoeff) { // phaseCoeff = 0.5; boolean dbg=false; double [] data = data_in.clone(); double [] pattern = pattern_in.clone(); double [] wnd = wnd_in.clone(); Loading @@ -3047,7 +3065,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ for (int i = 0; i < data.length; i++) { data[i] *= wnd[i]; } { if (dbg) { String [] rslt_titles= {"original","window","windowed","pattern"}; ShowDoubleFloatArrays.showArrays( new double[][] {data_orig, wnd, data, pattern}, Loading Loading @@ -3096,7 +3114,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ } } { if (dbg) { String [] rslt_titles= {"corr", "original","window","windowed","pattern"}; ShowDoubleFloatArrays.showArrays( new double[][] {corr_out, data_orig, wnd, data_orig2, pattern_orig}, Loading @@ -3106,7 +3124,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ convolve?"output_conv":("output_corr"+phaseCoeff), rslt_titles); } System.out.println("testPhaseCorr() done"); if (dbg) System.out.println("testPhaseCorr() done"); return corr_out; } Loading Loading @@ -3192,8 +3210,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public static void testPatternCorrelate( ImagePlus imp_src) { /* String pattern_dir= "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/debug/mines/pattern_25m_zoom1/synthetic/"; // String pattern_file= "patterns_50m_zoom1_200x200.tiff"; String [] pattern_files= {"patterns_50m_zoom1_200x200.tiff", "patterns_50m_evening_zoom1_200x200.tiff", Loading @@ -3202,6 +3220,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ "patterns_50m_evening_03_zoom1_200x200_00.tiff", "patterns_50m_evening_04_zoom1_200x200_00.tiff", "patterns_50m_evening_05_zoom1_200x200_00.tiff"}; */ int zoomout = 2; // 1; int corr_size = 128; // 256; double phaseCoeff = 0.5; Loading Loading @@ -3297,7 +3316,6 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ double [][] corrs_out = new double[patterns.length][]; double [][] convolve_out = new double[patterns.length][]; // double [][] lim_corr = new double[patterns.length][]; double [][] corr_patterns = new double[patterns.length][]; for (int n = 0; n < patterns.length; n++) { corr_patterns[n] = patternZoomCropPad( Loading Loading @@ -3331,6 +3349,11 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ height, removeKnownExtension(imp_src.getTitle())+"-PATTERN_CORRS", patt_titles); // test_titles, if (src_marks != null) { PointRoi roi = new PointRoi(); roi.setOptions("label"); Loading Loading @@ -3881,40 +3904,16 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public static void testPatternGenerate() { int half_size = 100; boolean half_pix = false; // center between pixels boolean evening_mode = false; // glare around object, use radius double radius_out= 42; double edge_out = 6; double scale_out = 1.5; boolean evening_mode = true; // false; // glare around object, use radius double radius = 30; // 32; // 32; double edge= 15; // 4; double radius_in= 15; // if 0 - skip double edge_in = 8; double scale_in = -0.05; double radius_out= 42; double edge_out = 6; double scale_out = 1.5; double scale = -200; // black 200 if (evening_mode) { radius_out= 42; edge_out = 8; scale_out =-1.5; // relative to scale radius = 30; // 32; // 32; edge= 15; // 4; radius_in= 10; // if 0 - skip edge_in = 8; scale_in = -0.7; scale = -40; // black 200 } else { radius_out= 42; edge_out = 6; scale_out =.08; radius = 30; // 32; // 32; edge= 15; // 4; radius_in= 15; // if 0 - skip edge_in = 8; scale_in = -0.05; scale = -170; // black 200 } boolean normalize = false; int halves_number = 8; // hidden mines - number of diameter cuts Loading @@ -3930,15 +3929,15 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ if (gd0.wasCanceled()) return; evening_mode= gd0.getNextBoolean(); if (evening_mode) { radius_out= 62; // 42; edge_out = 40; // 8; scale_out =-1.5; // relative to scale radius = 30; // 32; // 32; edge= 24; // 8; // 4; edge= 8; // 8; // 4; radius_in= 10; // if 0 - skip edge_in = 8; scale_in = -0.1; // 7; scale = -40; // black 200 scale_in = 0; // -0.1; // 7; radius_out= 45; // 42; edge_out = 30; // 8; scale_out =-1.0; // relative to scale scale = -60; // black 200 } else { radius_out= 42; edge_out = 6; Loading
src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java +58 −0 Original line number Diff line number Diff line Loading @@ -396,6 +396,64 @@ public class OrthoMapsCollection implements Serializable{ return bounds; } /** * Use object coordinates (now metric) on the composite image to * determine corresponding pixel coordinates of the source images * @param objects ArrayList of objects with the scene name and xy coordinates * in the composite image. Will fill in pixel coordinates of the objects * @param zoom_level zoom level of the composite image */ public void reverseRender( ArrayList<ObjectLocation> objects, int zoom_level){ int [][] bounds = getBoundsPixels( // should be for rectified, {-bounds[0][0], -bounds[0][1]} - exact center zoom_level, null); int width = bounds[0][1] - bounds[0][0]; // bounds[x][0] - negative int height = bounds[1][1] - bounds[1][0]; /* int [] indices = new int [ortho_maps.length]; //maybe will get rid of for (int i = 0; i < indices.length; i++) { indices[i] = i; } */ final int reference_index = 0; for (ObjectLocation ol: objects) { int nmap =getIndex(ol.getName()); final double scale = 1.0/OrthoMap.getPixelSizeMeters(zoom_level); final double src_scale = 1.0/OrthoMap.getPixelSizeMeters(ortho_maps[nmap].orig_zoom_level); // pix per meter double [][] mbounds = ortho_maps[nmap].getBoundsMeters(true); // keep original bounds double [] enu_offset = ortho_maps[reference_index].enuOffsetTo(ortho_maps[nmap]); double [] scaled_out_center = { // xy center to apply affine to -bounds[0][0] + scale * enu_offset[0], -bounds[1][0] - scale * enu_offset[1]}; double [] metric_center = { // back to meters to match objects scaled_out_center[0]/scale, scaled_out_center[1]/scale}; double dX = ol.getMetric()[0]-metric_center[0]; // matching dX, dY in renderMulti() double dY = ol.getMetric()[1]-metric_center[1]; // final int [][] obounds = new int [2][2]; // output (rectified, combined) image bounds, relative to thje top-left // for (int n = 0; n< 2; n++) { // obounds[n][0] = (int) Math.floor(scaled_out_center[n] + scale*mbounds[n][0]); // obounds[n][1] = (int) Math.ceil (scaled_out_center[n] + scale*mbounds[n][1]); // } // Output window size (keep original affine - OK if will not exactly fit) // final int ownd_width = obounds[0][1] - obounds[0][0]; // final int ownd_height = obounds[1][1] - obounds[1][0]; // final int ownd_len = ownd_width * ownd_height; double [][] src_bounds=ortho_maps[nmap].getBoundsMeters (true); // using original affines final double [] src_center = {-src_bounds[0][0],-src_bounds[1][0]}; // x,y center offset in the source image final double [][] affine = ortho_maps[nmap].affine; // only here use provided // final int src_width = ortho_maps[nmap].getImageData().width; // final int src_height = ortho_maps[nmap].getImageData().height; // final float [] src_img = ortho_maps[nmap].getImageData().data; // FIXME: will not use double [] xy_src = { // pixels of the source image src_scale * (affine[0][0]*dX + affine[0][1]*dY + affine[0][2] + src_center[0]), src_scale * (affine[1][0]*dX + affine[1][1]*dY + affine[1][2] + src_center[1])}; ol.setPixels(xy_src); } } public ImagePlus renderMulti ( Loading