Loading src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +8 −4 Original line number Diff line number Diff line Loading @@ -1161,6 +1161,7 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341 return null; } int pair = 0; boolean flip_pair = false; if (fp.npoints > 2) { // select pair int [][] pairs = new int [fp.npoints/2][2]; for (int j = 0; j < pairs.length; j++) { Loading @@ -1174,19 +1175,22 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341 GenericJTabbedDialog gds = new GenericJTabbedDialog("Select image pair from the image",1200,400); gds.addChoice("Image pair in the marked image:", choices, choices[choices.length-1]); gds.addCheckbox ("Flip order", false, "Match first to second."); gds.showDialog(); if (gds.wasCanceled()) return null; pair= gds.getNextChoiceIndex(); flip_pair = gds.getNextBoolean(); } double [][] points_xy= new double [2][2]; int [] pair_slices = new int[2]; for (int n = 0; n < points_xy.length; n++) { for (int nn = 0; nn < points_xy.length; nn++) { int n= flip_pair? (points_xy.length-nn-1) : nn; int p = 2 * pair + n; // fp.npoints-2+n; points_xy[n][0] = fp.xpoints[p]; points_xy[n][1] = fp.ypoints[p]; pair_slices[n] = pRoi.getPointPosition(p); // works points_xy[nn][0] = fp.xpoints[p]; points_xy[nn][1] = fp.ypoints[p]; pair_slices[nn] = pRoi.getPointPosition(p); // works } PairwiseOrthoMatch match= new PairwiseOrthoMatch(); match.affine = new double[][] { Loading src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java +26 −45 Original line number Diff line number Diff line Loading @@ -1787,6 +1787,7 @@ public class OrthoMapsCollection implements Serializable{ // filters boolean filt_keep = false; // list filtered out, but actually keep them boolean filt_keep_pre = false; // Keep pre first filter boolean filt_atonce = false; // apply main/second together, false - first filter main only double filt_frac_max = 0.6; // 0.5; // measure are at fraction of max double [][] filt_max_radius = {{1.0,1.0},{1.2,1.2}}; // {1.0,1.0}}; // [second/main][full/half] - inactive now Loading @@ -1801,7 +1802,7 @@ public class OrthoMapsCollection implements Serializable{ double filt_height = 0.2; // allow extra negative offset parallel to image offset, corresponding to object above ground // double [] filt_full_half_frac = {0.7, 0.5}; // second probably not needed, it is for main double [] filt_full_half_frac = {0.675, 0.5}; // second probably not needed, it is for main double [] filt_roundness = {0.6, 0.0}; // second currently is not calculated/ used double [] filt_roundness = {0.58, 0.0}; //{0.6, 0.0}; // second currently is not calculated/ used 215 mine1 0.059618 double filt_abs_contrast = 80.0; // 50.0; double filt_abs_easepart = 1.0; // 1.0-no ease for low AGL. Allow lower absolute contrast for partial patterns (high AGL) boolean convolve_after = false; // true for old kernel tuning (kernel decimation before convolution) Loading @@ -1816,15 +1817,24 @@ public class OrthoMapsCollection implements Serializable{ filt_abs_contrast = 75; filt_abs_easepart = 0.85; phaseCoeff[0] = 0.9; phaseCoeff[1] = 0.9; // adv_radius = 20; // pix? } else { // 100m defaults min_corrs[0] = 0.009; // 119; min_corrs = new double[]{0.007,0.006}; abs_edge_frac = 0.35; abs_oversize = 2.2; filt_abs_contrast = 60; filt_abs_easepart = 0.85; phaseCoeff[0] = 0.9; phaseCoeff[1] = 0.9; abs_force_round = true; filt_max_radius = new double [][] {{0.6,0.3}, {1.0,1.0}}; // {1.0,1.0}}; // [second/main][full/half] - inactive now filt_elongation = new double [][] {{1.4,1.5}, {1.7,1.7}}; filt_frac_max = 0.7; filt_dist = new double[]{5.0,2.5}; // full offset and perpendicular to images offsets filt_roundness[0] = 0.58; // 0.6;214-213_1694565491_890936-1694565488_589836 is 0.589 filt_other_frac = new double [] {0.75,0.68};// no pixels around max at filt_other_rad should be higher than this fraction of max // adv_radius = 20; // pix? } } Loading Loading @@ -1864,6 +1874,7 @@ public class OrthoMapsCollection implements Serializable{ gd.addTab("Filters","Filtering results to reduce false positives"); gd.addCheckbox ("Keep filtered out", filt_keep, "List filtered out, but actaually keep them."); gd.addCheckbox ("Keep pre-filter", filt_keep_pre, "Keep even before the first scene filter."); gd.addCheckbox ("Apply filters at once", filt_atonce, "If false, first filter by main scene only, do not process secondary scene if main failed."); gd.addNumericField("Peak hight fraction", filt_frac_max, 5,7,"","Fraction of the peak hight for eigenvlues (radius and elongation)."); gd.addNumericField("Max radius, main, full", filt_max_radius[0][0], 5,7,"pix","Maximal peak cross-section average radius at certain height."); Loading Loading @@ -1921,6 +1932,7 @@ public class OrthoMapsCollection implements Serializable{ abs_obscure_frac = gd.getNextNumber(); filt_keep= gd.getNextBoolean(); filt_keep_pre= gd.getNextBoolean(); filt_atonce= gd.getNextBoolean(); filt_frac_max= gd.getNextNumber(); filt_max_radius[0][0]= gd.getNextNumber(); Loading Loading @@ -1972,6 +1984,7 @@ public class OrthoMapsCollection implements Serializable{ abs_obscure_warm, // boolean abs_obscure_warm, // = true; // obscured can only be by warmer objects abs_obscure_frac, // double abs_obscure_frac, // 0.25; // obscured threshold between center and outer filt_keep, // boolean filt_keep, filt_keep_pre, // boolean filt_keep_pre, filt_atonce, // boolean filt_atonce, filt_frac_max, // double frac_max, // measure are at fraction of max filt_max_radius, // double [][] filt_max_radius, Loading Loading @@ -2014,6 +2027,7 @@ public class OrthoMapsCollection implements Serializable{ boolean abs_obscure_warm, // = true; // obscured can only be by warmer objects double abs_obscure_frac, // 0.25; // obscured threshold between center and outer boolean filt_keep, boolean filt_keep_pre, boolean filt_atonce, double frac_max, // measure are at fraction of max double [][] filt_max_radius, Loading Loading @@ -2451,7 +2465,6 @@ public class OrthoMapsCollection implements Serializable{ center_xy, // double [] center_xy, extr_size, // int size, corrs_out[scene_num][best_patt], // double [] src_img, // bestcorr[scene_num], // double [] src_img, width); // int width) // combine from scratch, best[] uses thresholding inside if (combine_full[0]) { Loading @@ -2470,42 +2483,7 @@ public class OrthoMapsCollection implements Serializable{ frac_max, // double frac_max) filt_other_rad, // double other_radius, debugLevel); // final int debugLevel) { /* // extract main scene data, needed for the absolute contrast calculations, no display showExtractedImages( // scene_num == 0 here null, // ortho_maps[indices[scene_num]].getName()+"-prefilter", // String prefix scene_num, //int scene_num, //sort_pattern_index, // int sort_pattern_index, extr_size, // int extr_size, gops[scene_num], // GroundObjectPattern gop, matches_list, // ArrayList <ItemMatch> matches_list, match_sort, // ArrayList<Integer> match_sort, extracted_objects, // double[][][] extracted_objects, // may be null - will not be generated null, // extract_display, // double[][][] extract_display, // may be null - will not be displayed dmulti, // double[][] dmulti, width, // int width, remove_dc, // boolean remove_dc, null, // imps_extracted, //ImagePlus[] imps_extracted, // may be null - will not be displayed debugLevel); // int debugLevel */ } /* // calculate absolute contrasts for all patterns, update best_sub modes: 0 - keep, 1 - keep type, 2 keep type and if half +/-1 setAbsoluteContrasts( abs_force_round, // boolean abs_force_round, abs_mode, // int mode, // 0 - keep, 1 keep type and if half +/-1, 2 - keep type, 3 - any abs_invert, // boolean neg_better, // more negative is difference - stronger result abs_outliers_frac, // double outliers_frac, abs_obscure_warm, // boolean abs_obscure_warm, // = true; // obscured can only be by warmer objects abs_obscure_frac, // double abs_obscure_frac, // 0.25; // obscured threshold between center and outer gops[scene_num], // GroundObjectPattern gop, matches_list, // ArrayList <ItemMatch> matches_list, match_sort, // ArrayList<Integer> match_sort, extracted_objects[scene_num], //double[][] extracted_objects, // for this scene icorr_patterns[scene_num], // int [][] ipatterns, extracted_masked[scene_num], // double [][] masked_src, // if not null, will return masked extracted objects debugLevel); // int debugLevel */ double [] scene_xy_offset = {centers[last_scene][0]-centers[0][0],centers[last_scene][1]-centers[0][1]}; boolean [] removed = null; double scene_agl = gops[last_scene].getAGL(); // second scene agl Loading Loading @@ -2556,14 +2534,14 @@ public class OrthoMapsCollection implements Serializable{ } } if (!filt_atonce) { if (!filt_atonce) { // first filter using scene 1 only boolean[] filt_main_other = new boolean [indices.length]; //{true,false}; filt_main_other[0] = true; //int num_removed = // filt_abs_contrast // filt_abs_easepart removed = filterCandidates( filt_keep, // boolean filt_keep, filt_keep_pre, // boolean filt_keep, filt_main_other, // new boolean [] filt_main_other, min_corrs, // double [] min_corrs, // one per min_corr_full_rel, // double min_corr_full_rel, Loading @@ -2584,7 +2562,7 @@ public class OrthoMapsCollection implements Serializable{ matches_list, // ArrayList <ItemMatch> matches_list, match_sort, // ArrayList<Integer> match_sort, debugLevel); // int debugLevel ) if (!filt_keep && (removed.length > match_sort.size())) { // decimate data arrays if (!filt_keep_pre && (removed.length > match_sort.size())) { // decimate data arrays for (int sn = 0; sn < filter_data.length; sn++) { filter_data[sn] = removeFilteredOut (filter_data[sn], removed); extracted_objects[sn] = removeFilteredOut (extracted_objects[sn], removed); Loading @@ -2592,11 +2570,8 @@ public class OrthoMapsCollection implements Serializable{ extr_corr[sn] = removeFilteredOut (extr_corr[sn], removed); extr_corr_half[sn] = removeFilteredOut (extr_corr_half[sn], removed); } // best_patt_indx = removeFilteredOut(best_patt_indx, removed); removed = new boolean [match_sort.size()]; } // System.out.println(num_removed+ "scenes filtered out, "+match_sort.size()+" candidates remain"); } if (indices.length > 1) { // for a multi-scene show after filtering by the first scene // show extracted scenes after some were optionally removed by the main scene filters Loading Loading @@ -2862,7 +2837,13 @@ public class OrthoMapsCollection implements Serializable{ "(First value is the total offset in pixels, second accounts for parallax.) "+ " filt_height="+filt_height+ " meters."); System.out.println("filt_other_rad="+filt_other_rad+"pix, filt_other_frac=["+filt_other_frac[0]+", "+filt_other_frac[1]+"],"+ " filt_full_half_frac=["+filt_full_half_frac[0]+", "+filt_full_half_frac[1]+"]."); " filt_full_half_frac=["+filt_full_half_frac[0]+", "+filt_full_half_frac[1]+"], filt_roundness="+filt_roundness[0]+"."); System.out.println("filt_abs_contrast="+filt_abs_contrast+", filt_abs_easepart="+filt_abs_easepart); System.out.println("abs_edge_frac="+abs_edge_frac+", abs_oversize="+abs_oversize+ ", abs_force_round="+abs_force_round+", abs_mode="+abs_mode+", abs_invert="+abs_invert); System.out.println("abs_outliers_frac="+abs_outliers_frac+", abs_obscure_warm="+abs_obscure_warm+ ", abs_obscure_frac="+abs_obscure_frac); if (indices.length > 1) { System.out.println("Second image is offset by dx="+scene_xy_offset[0]+", dy="+scene_xy_offset[1]+", dist="+ Math.sqrt(scene_xy_offset[0]*scene_xy_offset[0]+scene_xy_offset[1]*scene_xy_offset[1])+" pix"); Loading Loading
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +8 −4 Original line number Diff line number Diff line Loading @@ -1161,6 +1161,7 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341 return null; } int pair = 0; boolean flip_pair = false; if (fp.npoints > 2) { // select pair int [][] pairs = new int [fp.npoints/2][2]; for (int j = 0; j < pairs.length; j++) { Loading @@ -1174,19 +1175,22 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341 GenericJTabbedDialog gds = new GenericJTabbedDialog("Select image pair from the image",1200,400); gds.addChoice("Image pair in the marked image:", choices, choices[choices.length-1]); gds.addCheckbox ("Flip order", false, "Match first to second."); gds.showDialog(); if (gds.wasCanceled()) return null; pair= gds.getNextChoiceIndex(); flip_pair = gds.getNextBoolean(); } double [][] points_xy= new double [2][2]; int [] pair_slices = new int[2]; for (int n = 0; n < points_xy.length; n++) { for (int nn = 0; nn < points_xy.length; nn++) { int n= flip_pair? (points_xy.length-nn-1) : nn; int p = 2 * pair + n; // fp.npoints-2+n; points_xy[n][0] = fp.xpoints[p]; points_xy[n][1] = fp.ypoints[p]; pair_slices[n] = pRoi.getPointPosition(p); // works points_xy[nn][0] = fp.xpoints[p]; points_xy[nn][1] = fp.ypoints[p]; pair_slices[nn] = pRoi.getPointPosition(p); // works } PairwiseOrthoMatch match= new PairwiseOrthoMatch(); match.affine = new double[][] { Loading
src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java +26 −45 Original line number Diff line number Diff line Loading @@ -1787,6 +1787,7 @@ public class OrthoMapsCollection implements Serializable{ // filters boolean filt_keep = false; // list filtered out, but actually keep them boolean filt_keep_pre = false; // Keep pre first filter boolean filt_atonce = false; // apply main/second together, false - first filter main only double filt_frac_max = 0.6; // 0.5; // measure are at fraction of max double [][] filt_max_radius = {{1.0,1.0},{1.2,1.2}}; // {1.0,1.0}}; // [second/main][full/half] - inactive now Loading @@ -1801,7 +1802,7 @@ public class OrthoMapsCollection implements Serializable{ double filt_height = 0.2; // allow extra negative offset parallel to image offset, corresponding to object above ground // double [] filt_full_half_frac = {0.7, 0.5}; // second probably not needed, it is for main double [] filt_full_half_frac = {0.675, 0.5}; // second probably not needed, it is for main double [] filt_roundness = {0.6, 0.0}; // second currently is not calculated/ used double [] filt_roundness = {0.58, 0.0}; //{0.6, 0.0}; // second currently is not calculated/ used 215 mine1 0.059618 double filt_abs_contrast = 80.0; // 50.0; double filt_abs_easepart = 1.0; // 1.0-no ease for low AGL. Allow lower absolute contrast for partial patterns (high AGL) boolean convolve_after = false; // true for old kernel tuning (kernel decimation before convolution) Loading @@ -1816,15 +1817,24 @@ public class OrthoMapsCollection implements Serializable{ filt_abs_contrast = 75; filt_abs_easepart = 0.85; phaseCoeff[0] = 0.9; phaseCoeff[1] = 0.9; // adv_radius = 20; // pix? } else { // 100m defaults min_corrs[0] = 0.009; // 119; min_corrs = new double[]{0.007,0.006}; abs_edge_frac = 0.35; abs_oversize = 2.2; filt_abs_contrast = 60; filt_abs_easepart = 0.85; phaseCoeff[0] = 0.9; phaseCoeff[1] = 0.9; abs_force_round = true; filt_max_radius = new double [][] {{0.6,0.3}, {1.0,1.0}}; // {1.0,1.0}}; // [second/main][full/half] - inactive now filt_elongation = new double [][] {{1.4,1.5}, {1.7,1.7}}; filt_frac_max = 0.7; filt_dist = new double[]{5.0,2.5}; // full offset and perpendicular to images offsets filt_roundness[0] = 0.58; // 0.6;214-213_1694565491_890936-1694565488_589836 is 0.589 filt_other_frac = new double [] {0.75,0.68};// no pixels around max at filt_other_rad should be higher than this fraction of max // adv_radius = 20; // pix? } } Loading Loading @@ -1864,6 +1874,7 @@ public class OrthoMapsCollection implements Serializable{ gd.addTab("Filters","Filtering results to reduce false positives"); gd.addCheckbox ("Keep filtered out", filt_keep, "List filtered out, but actaually keep them."); gd.addCheckbox ("Keep pre-filter", filt_keep_pre, "Keep even before the first scene filter."); gd.addCheckbox ("Apply filters at once", filt_atonce, "If false, first filter by main scene only, do not process secondary scene if main failed."); gd.addNumericField("Peak hight fraction", filt_frac_max, 5,7,"","Fraction of the peak hight for eigenvlues (radius and elongation)."); gd.addNumericField("Max radius, main, full", filt_max_radius[0][0], 5,7,"pix","Maximal peak cross-section average radius at certain height."); Loading Loading @@ -1921,6 +1932,7 @@ public class OrthoMapsCollection implements Serializable{ abs_obscure_frac = gd.getNextNumber(); filt_keep= gd.getNextBoolean(); filt_keep_pre= gd.getNextBoolean(); filt_atonce= gd.getNextBoolean(); filt_frac_max= gd.getNextNumber(); filt_max_radius[0][0]= gd.getNextNumber(); Loading Loading @@ -1972,6 +1984,7 @@ public class OrthoMapsCollection implements Serializable{ abs_obscure_warm, // boolean abs_obscure_warm, // = true; // obscured can only be by warmer objects abs_obscure_frac, // double abs_obscure_frac, // 0.25; // obscured threshold between center and outer filt_keep, // boolean filt_keep, filt_keep_pre, // boolean filt_keep_pre, filt_atonce, // boolean filt_atonce, filt_frac_max, // double frac_max, // measure are at fraction of max filt_max_radius, // double [][] filt_max_radius, Loading Loading @@ -2014,6 +2027,7 @@ public class OrthoMapsCollection implements Serializable{ boolean abs_obscure_warm, // = true; // obscured can only be by warmer objects double abs_obscure_frac, // 0.25; // obscured threshold between center and outer boolean filt_keep, boolean filt_keep_pre, boolean filt_atonce, double frac_max, // measure are at fraction of max double [][] filt_max_radius, Loading Loading @@ -2451,7 +2465,6 @@ public class OrthoMapsCollection implements Serializable{ center_xy, // double [] center_xy, extr_size, // int size, corrs_out[scene_num][best_patt], // double [] src_img, // bestcorr[scene_num], // double [] src_img, width); // int width) // combine from scratch, best[] uses thresholding inside if (combine_full[0]) { Loading @@ -2470,42 +2483,7 @@ public class OrthoMapsCollection implements Serializable{ frac_max, // double frac_max) filt_other_rad, // double other_radius, debugLevel); // final int debugLevel) { /* // extract main scene data, needed for the absolute contrast calculations, no display showExtractedImages( // scene_num == 0 here null, // ortho_maps[indices[scene_num]].getName()+"-prefilter", // String prefix scene_num, //int scene_num, //sort_pattern_index, // int sort_pattern_index, extr_size, // int extr_size, gops[scene_num], // GroundObjectPattern gop, matches_list, // ArrayList <ItemMatch> matches_list, match_sort, // ArrayList<Integer> match_sort, extracted_objects, // double[][][] extracted_objects, // may be null - will not be generated null, // extract_display, // double[][][] extract_display, // may be null - will not be displayed dmulti, // double[][] dmulti, width, // int width, remove_dc, // boolean remove_dc, null, // imps_extracted, //ImagePlus[] imps_extracted, // may be null - will not be displayed debugLevel); // int debugLevel */ } /* // calculate absolute contrasts for all patterns, update best_sub modes: 0 - keep, 1 - keep type, 2 keep type and if half +/-1 setAbsoluteContrasts( abs_force_round, // boolean abs_force_round, abs_mode, // int mode, // 0 - keep, 1 keep type and if half +/-1, 2 - keep type, 3 - any abs_invert, // boolean neg_better, // more negative is difference - stronger result abs_outliers_frac, // double outliers_frac, abs_obscure_warm, // boolean abs_obscure_warm, // = true; // obscured can only be by warmer objects abs_obscure_frac, // double abs_obscure_frac, // 0.25; // obscured threshold between center and outer gops[scene_num], // GroundObjectPattern gop, matches_list, // ArrayList <ItemMatch> matches_list, match_sort, // ArrayList<Integer> match_sort, extracted_objects[scene_num], //double[][] extracted_objects, // for this scene icorr_patterns[scene_num], // int [][] ipatterns, extracted_masked[scene_num], // double [][] masked_src, // if not null, will return masked extracted objects debugLevel); // int debugLevel */ double [] scene_xy_offset = {centers[last_scene][0]-centers[0][0],centers[last_scene][1]-centers[0][1]}; boolean [] removed = null; double scene_agl = gops[last_scene].getAGL(); // second scene agl Loading Loading @@ -2556,14 +2534,14 @@ public class OrthoMapsCollection implements Serializable{ } } if (!filt_atonce) { if (!filt_atonce) { // first filter using scene 1 only boolean[] filt_main_other = new boolean [indices.length]; //{true,false}; filt_main_other[0] = true; //int num_removed = // filt_abs_contrast // filt_abs_easepart removed = filterCandidates( filt_keep, // boolean filt_keep, filt_keep_pre, // boolean filt_keep, filt_main_other, // new boolean [] filt_main_other, min_corrs, // double [] min_corrs, // one per min_corr_full_rel, // double min_corr_full_rel, Loading @@ -2584,7 +2562,7 @@ public class OrthoMapsCollection implements Serializable{ matches_list, // ArrayList <ItemMatch> matches_list, match_sort, // ArrayList<Integer> match_sort, debugLevel); // int debugLevel ) if (!filt_keep && (removed.length > match_sort.size())) { // decimate data arrays if (!filt_keep_pre && (removed.length > match_sort.size())) { // decimate data arrays for (int sn = 0; sn < filter_data.length; sn++) { filter_data[sn] = removeFilteredOut (filter_data[sn], removed); extracted_objects[sn] = removeFilteredOut (extracted_objects[sn], removed); Loading @@ -2592,11 +2570,8 @@ public class OrthoMapsCollection implements Serializable{ extr_corr[sn] = removeFilteredOut (extr_corr[sn], removed); extr_corr_half[sn] = removeFilteredOut (extr_corr_half[sn], removed); } // best_patt_indx = removeFilteredOut(best_patt_indx, removed); removed = new boolean [match_sort.size()]; } // System.out.println(num_removed+ "scenes filtered out, "+match_sort.size()+" candidates remain"); } if (indices.length > 1) { // for a multi-scene show after filtering by the first scene // show extracted scenes after some were optionally removed by the main scene filters Loading Loading @@ -2862,7 +2837,13 @@ public class OrthoMapsCollection implements Serializable{ "(First value is the total offset in pixels, second accounts for parallax.) "+ " filt_height="+filt_height+ " meters."); System.out.println("filt_other_rad="+filt_other_rad+"pix, filt_other_frac=["+filt_other_frac[0]+", "+filt_other_frac[1]+"],"+ " filt_full_half_frac=["+filt_full_half_frac[0]+", "+filt_full_half_frac[1]+"]."); " filt_full_half_frac=["+filt_full_half_frac[0]+", "+filt_full_half_frac[1]+"], filt_roundness="+filt_roundness[0]+"."); System.out.println("filt_abs_contrast="+filt_abs_contrast+", filt_abs_easepart="+filt_abs_easepart); System.out.println("abs_edge_frac="+abs_edge_frac+", abs_oversize="+abs_oversize+ ", abs_force_round="+abs_force_round+", abs_mode="+abs_mode+", abs_invert="+abs_invert); System.out.println("abs_outliers_frac="+abs_outliers_frac+", abs_obscure_warm="+abs_obscure_warm+ ", abs_obscure_frac="+abs_obscure_frac); if (indices.length > 1) { System.out.println("Second image is offset by dx="+scene_xy_offset[0]+", dy="+scene_xy_offset[1]+", dist="+ Math.sqrt(scene_xy_offset[0]*scene_xy_offset[0]+scene_xy_offset[1]*scene_xy_offset[1])+" pix"); Loading