Loading src/main/java/com/elphel/imagej/cameras/CLTParameters.java +74 −16 Original line number Diff line number Diff line Loading @@ -321,6 +321,21 @@ public class CLTParameters { public boolean lyr_filter_ds = false; // true; public boolean lyr_filter_lyf = false; // ~clt_parameters.lyf_filter, but may be different, now off for a single cameras // Multi-scene LY parameters // Infinity detection public double lyms_far_inf = -0.5; // Far limit when searching for infinity objects public double lyms_near_inf = 0.5; // Near limit when searching for infinity objects public double lyms_far_fract = 0.05; // Mode of disparity distribution within range public double lyms_inf_range_offs = 0.05; // Add to the disparity distribution mode for infinity center public double lyms_inf_range = 0.15; // Consider infinity tiles that are within +/- half of this range from infinity center //non-infinity parameters public double lyms_min_inf_str = 0.2; // Minimal strength of infinity tiles public double lyms_min_fg_str = 0.4; // Minimal strength of non-infinity tiles public int lyms_clust_size = 4; // cluster size (same in both directions) for measuring LY data public double lyms_scene_range = 10.0; // disparity range for non-infinity in the same cluster public int lyms_min_num_inf = 10; // Minimal number of tiles (in all scenes total) in an infinity cluster // old fcorr parameters, reuse? // public int fcorr_sample_size = 32; // Use square this size side to detect outliers Loading Loading @@ -1243,6 +1258,17 @@ public class CLTParameters { properties.setProperty(prefix+"lyr_filter_ds", this.lyr_filter_ds +""); properties.setProperty(prefix+"lyr_filter_lyf", this.lyr_filter_lyf +""); properties.setProperty(prefix+"lyms_far_inf", this.lyms_far_inf +""); properties.setProperty(prefix+"lyms_near_inf", this.lyms_near_inf +""); properties.setProperty(prefix+"lyms_far_fract", this.lyms_far_fract +""); properties.setProperty(prefix+"lyms_inf_range_offs", this.lyms_inf_range_offs +""); properties.setProperty(prefix+"lyms_inf_range", this.lyms_inf_range +""); properties.setProperty(prefix+"lyms_min_inf_str", this.lyms_min_inf_str +""); properties.setProperty(prefix+"lyms_min_fg_str", this.lyms_min_fg_str +""); properties.setProperty(prefix+"lyms_clust_size", this.lyms_clust_size +""); properties.setProperty(prefix+"lyms_scene_range", this.lyms_scene_range +""); properties.setProperty(prefix+"lyms_min_num_inf", this.lyms_min_num_inf +""); properties.setProperty(prefix+"corr_magic_scale", this.corr_magic_scale +""); properties.setProperty(prefix+"corr_select", this.corr_select +""); Loading Loading @@ -2073,6 +2099,17 @@ public class CLTParameters { if (properties.getProperty(prefix+"lyr_filter_ds")!=null) this.lyr_filter_ds=Boolean.parseBoolean(properties.getProperty(prefix+"lyr_filter_ds")); if (properties.getProperty(prefix+"lyr_filter_lyf")!=null) this.lyr_filter_lyf=Boolean.parseBoolean(properties.getProperty(prefix+"lyr_filter_lyf")); if (properties.getProperty(prefix+"lyms_far_inf")!=null) this.lyms_far_inf=Double.parseDouble(properties.getProperty(prefix+"lyms_far_inf")); if (properties.getProperty(prefix+"lyms_near_inf")!=null) this.lyms_near_inf=Double.parseDouble(properties.getProperty(prefix+"lyms_near_inf")); if (properties.getProperty(prefix+"lyms_far_fract")!=null) this.lyms_far_fract=Double.parseDouble(properties.getProperty(prefix+"lyms_far_fract")); if (properties.getProperty(prefix+"lyms_inf_range_offs")!=null) this.lyms_inf_range_offs=Double.parseDouble(properties.getProperty(prefix+"lyms_inf_range_offs")); if (properties.getProperty(prefix+"lyms_inf_range")!=null) this.lyms_inf_range=Double.parseDouble(properties.getProperty(prefix+"lyms_inf_range")); if (properties.getProperty(prefix+"lyms_min_inf_str")!=null) this.lyms_min_inf_str=Double.parseDouble(properties.getProperty(prefix+"lyms_min_inf_str")); if (properties.getProperty(prefix+"lyms_min_fg_str")!=null) this.lyms_min_fg_str=Double.parseDouble(properties.getProperty(prefix+"lyms_min_fg_str")); if (properties.getProperty(prefix+"lyms_clust_size")!=null) this.lyms_clust_size=Integer.parseInt(properties.getProperty(prefix+"lyms_clust_size")); if (properties.getProperty(prefix+"lyms_scene_range")!=null) this.lyms_scene_range=Double.parseDouble(properties.getProperty(prefix+"lyms_scene_range")); if (properties.getProperty(prefix+"lyms_min_num_inf")!=null) this.lyms_min_num_inf=Integer.parseInt(properties.getProperty(prefix+"lyms_min_num_inf")); if (properties.getProperty(prefix+"corr_magic_scale")!=null) this.corr_magic_scale=Double.parseDouble(properties.getProperty(prefix+"corr_magic_scale")); if (properties.getProperty(prefix+"corr_select")!=null) this.corr_select=Integer.parseInt(properties.getProperty(prefix+"corr_select")); Loading Loading @@ -3006,13 +3043,30 @@ public class CLTParameters { gd.addCheckbox ("Filter lazy eye pairs by their values wen GT data is available", this.lyr_filter_lyf, "Same as \"Filter lazy eye pairs by their values\" above, but for the rig-guided adjustments"); // gd.addNumericField("Use square this size side to detect outliers", this.fcorr_sample_size, 0); // gd.addNumericField("Keep tiles only if there are more in each square", this.fcorr_mintiles, 0); // gd.addNumericField("Remove this fraction of tiles from each sample", this.fcorr_reloutliers, 3); // gd.addNumericField("Gaussian blur channel mismatch data", this.fcorr_sigma, 3); /// gd.addNumericField("Calculated from correlation offset vs. actual one (not yet understood)", this.corr_magic_scale, 3); gd.addTab ("LY multiscene", "Multiscene series Lazy Eye correction"); gd.addMessage ("--- Infinity detection ---"); gd.addNumericField("Infinity far", this.lyms_far_inf, 4,6,"pix", "Far limit when searching for infinity objects"); gd.addNumericField("Infinity near", this.lyms_near_inf, 4,6,"pix", "Near limit when searching for infinity objects"); gd.addNumericField("Infinity mode (0.0 - min, 1.0 - max", this.lyms_far_fract, 4,6,"", "Mode of disparity distribution within range (0.0 - min, 1.0 - max)"); gd.addNumericField("Offset infinity center from mode", this.lyms_inf_range_offs, 4,6,"pix", "Add to the disparity distribution mode for infinity center"); gd.addNumericField("Infinity full range", this.lyms_inf_range, 4,6,"pix", "Consider infinity tiles that are within +/- half of this range from infinity center"); gd.addMessage ("--- LY data measurement ---"); gd.addNumericField("Minimal strength (infinity)", this.lyms_min_inf_str, 4,6,"", "Minimal strength of infinity tiles"); gd.addNumericField("Minimal strength (non-infinity)", this.lyms_min_fg_str, 4,6,"", "Minimal strength of non-infinity tiles"); gd.addNumericField("Cluster size", this.lyms_clust_size, 0,3,"pix", "Cluster size (same in both directions) for measuring LY data"); gd.addNumericField("Per-scene disparity range", this.lyms_scene_range, 4,6,"pix", "Disparity range for non-infinity in the same cluster"); gd.addNumericField("Minimal number of infinity tiles", this.lyms_min_num_inf, 0,3,"", "Minimal number of tiles (in all scenes total) in an infinity cluster"); gd.addTab ("3D", "3D reconstruction"); gd.addMessage ("--- 3D reconstruction ---"); Loading Loading @@ -3977,12 +4031,16 @@ public class CLTParameters { this.lyr_filter_ds= gd.getNextBoolean(); this.lyr_filter_lyf= gd.getNextBoolean(); // this.fcorr_sample_size= (int)gd.getNextNumber(); // this.fcorr_mintiles= (int) gd.getNextNumber(); // this.fcorr_reloutliers= gd.getNextNumber(); // this.fcorr_sigma= gd.getNextNumber(); /// this.corr_magic_scale= gd.getNextNumber(); this.lyms_far_inf= gd.getNextNumber(); this.lyms_near_inf= gd.getNextNumber(); this.lyms_far_fract= gd.getNextNumber(); this.lyms_inf_range_offs= gd.getNextNumber(); this.lyms_inf_range= gd.getNextNumber(); this.lyms_min_inf_str= gd.getNextNumber(); this.lyms_min_fg_str= gd.getNextNumber(); this.lyms_clust_size= (int) gd.getNextNumber(); this.lyms_scene_range= gd.getNextNumber(); this.lyms_min_num_inf=(int) gd.getNextNumber(); this.show_textures= gd.getNextBoolean(); this.debug_filters= gd.getNextBoolean(); Loading src/main/java/com/elphel/imagej/tileprocessor/ImageDttCPU.java +58 −0 Original line number Diff line number Diff line Loading @@ -8950,6 +8950,64 @@ public class ImageDttCPU { return corr2d_decimated; } public static double [][] corr2d_decimate( // not used in lwir final double [][] corr2d_img, final int tilesX, final int tilesY, final int clust_size, final int [] wh, final int threadsMax, // maximal number of threads to launch final int globalDebugLevel) { int len = 0; final double [][] corr2d_decimated = new double [corr2d_img.length][]; for (int i = 0; i < corr2d_img.length; i++) { if (corr2d_img[i] != null) { len = corr2d_img[i].length; break; } } final int tile_size = (int) Math.round(Math.sqrt(len/(tilesX * tilesY))); final int clustersX = (int) Math.ceil(1.0 * tilesX / clust_size); final int clustersY = (int) Math.ceil(1.0 * tilesY / clust_size); final int clusters = clustersX * clustersY; final Thread[] threads = newThreadArray(threadsMax); final AtomicInteger ai = new AtomicInteger(0); final int clust_lines = clust_size * tile_size; final int in_line_len = clustersX * clust_size * tile_size; final int out_line_len = clustersX * tile_size; if (wh != null) { wh[0] = clustersX * tile_size; wh[1] = clustersY * tile_size; } for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { @Override public void run() { for (int nLayer = ai.getAndIncrement(); nLayer < corr2d_img.length; nLayer = ai.getAndIncrement()) { if (corr2d_img[nLayer] != null){ corr2d_decimated[nLayer] = new double [clusters * tile_size * tile_size]; for (int clustY = 0; clustY < clustersY; clustY++) { for (int clustX = 0; clustX < clustersX; clustX++) { int offs = clustY * clust_lines * in_line_len; for (int line = 0; line < tile_size; line++) { System.arraycopy( corr2d_img[nLayer], (clustY * clust_lines + line) * in_line_len + clustX * clust_lines, corr2d_decimated[nLayer], (clustY * tile_size + line) * out_line_len + clustX * tile_size, tile_size); } } } } } } }; } startAndJoin(threads); return corr2d_decimated; } Loading src/main/java/com/elphel/imagej/tileprocessor/MultisceneLY.java +216 −69 Original line number Diff line number Diff line Loading @@ -281,10 +281,12 @@ public class MultisceneLY { final int clust_size, final double inf_range, // full range centered at inf_disp_ref to be used as infinity final double scene_range, // disparity range for non-infinity in the same cluster final int min_num_inf, // Minimal number of tiles (in all scenes total) in an infinity cluster final QuadCLT [] scenes, // ordered by increasing timestamps final boolean [][] valid_tile, // tile with lma and single correlation maximum final double inf_disp_ref, // average disparity at infinity for ref scene final boolean [][] is_infinity, // may be null, if not - may be infinity from the composite depth map final boolean [][] is_infinity, // may be null (all non-infinity), if not - may be infinity from the composite depth map final boolean only_infinity, // do not process non-infinity int [] in_num_tiles, // null or array of number of clusters boolean [] in_inf_cluster, // null or array of number of clusters, will return if cluster uses only infinite tiles final int threadsMax, Loading @@ -303,6 +305,10 @@ public class MultisceneLY { final int [] num_tiles = (in_num_tiles != null)? in_num_tiles : (new int [clusters]); final boolean [] inf_cluster = (in_inf_cluster != null)? in_inf_cluster : (new boolean [clusters]); Arrays.fill(num_tiles, 0); Arrays.fill(inf_cluster, false); final int [] num_inf_cluster = new int[clusters]; for (int nscene = 0; nscene < num_scenes; nscene++) { target_disparities[nscene] = scenes[nscene].getDSRBG()[0]; Arrays.fill(rslt_disparities[nscene], Double.NaN); Loading @@ -314,7 +320,7 @@ public class MultisceneLY { for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { Cluster: // Cluster: for (int nClust = ai.getAndIncrement(); nClust < clusters; nClust = ai.getAndIncrement()) { int clustX = nClust % clustersX; int clustY = nClust / clustersX; Loading @@ -329,20 +335,36 @@ public class MultisceneLY { if (is_infinity[nscene][nTile] && valid_tile[nscene][nTile] && // next may be NaN (Math.abs(target_disparities[nscene][nTile] - inf_disp_ref) <= inf_hrange)) { inf_cluster[nClust] = true; continue Cluster; num_inf_cluster[nClust]++; // inf_cluster[nClust] = true; // continue Cluster; } } } } } } } } }; } ImageDtt.startAndJoin(threads); ai.set(0); // mark clusters as infinity if they have enough infinity tiles for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int nClust = ai.getAndIncrement(); nClust < clusters; nClust = ai.getAndIncrement()) { if (num_inf_cluster[nClust] >= min_num_inf) { inf_cluster[nClust] = true; } } } }; } ImageDtt.startAndJoin(threads); // Mark suitable infinity tiles (they are NaN now) ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { Loading Loading @@ -378,6 +400,7 @@ public class MultisceneLY { ImageDtt.startAndJoin(threads); } if (!only_infinity) { ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { Loading Loading @@ -454,15 +477,119 @@ public class MultisceneLY { }; } ImageDtt.startAndJoin(threads); } return rslt_disparities; } public static double [][][] getLYDataInfNoinf( final CLTParameters clt_parameters, final int clust_size, final double inf_range, // full range centered at inf_disp_ref to be used as infinity final double scene_range, // disparity range for non-infinity in the same cluster final int min_num_inf, // Minimal number of tiles (in all scenes total) in an infinity cluster final QuadCLT [] scenes, // ordered by increasing timestamps final boolean [][] valid_tile, // tile with lma and single correlation maximum final double inf_disp_ref, // average disparity at infinity for ref scene // is_scene_infinity final boolean [][] is_scene_infinity, // may be null, if not - may be infinity from the composite depth map final double [][][] target_disparities, final double dbg_disparity_offset, final int [][] in_num_tiles, // null or number of tiles per cluster to multiply strength final int threadsMax, final int debug_level){ final double [][][] inf_noinf_lazy_eye_data = new double [2][][]; int last_scene_index = scenes.length-1; QuadCLT last_scene = scenes[last_scene_index]; int tilesX = last_scene.tp.getTilesX(); int tilesY = last_scene.tp.getTilesY(); int clustersX = (int) Math.ceil(1.0 * tilesX / clust_size); int clustersY = (int) Math.ceil(1.0 * tilesY / clust_size); int clusters = clustersX * clustersY; final int [][] num_tiles = (in_num_tiles != null)? in_num_tiles : (new int [2][]); for (int i = 0; i < num_tiles.length; i++) { num_tiles[i] = new int [clusters]; } // int [][] num_tiles = new int [2][clusters]; // may be null;; // null; boolean [] inf_cluster = new boolean [clusters]; // null; boolean debug = debug_level > -3; // get for infinity only double [][] target_disparities_inf = MultisceneLY.useTilesLY( clust_size, // final int clust_size, inf_range, // final double inf_range, // full range centered at inf_disp_ref to be used as infinity scene_range, // final double scene_range, // disparity range for non-infinity in the same cluster min_num_inf, // final int min_num_inf, // Minimal number of tiles (in all scenes total) in an infinity cluster scenes, // final QuadCLT [] scenes, // ordered by increasing timestamps valid_tile, // final boolean [][] valid_tile, // tile with lma and single correlation maximum inf_disp_ref, // final double inf_disp_ref, // average disparity at infinity for ref scene // is_scene_infinity is_scene_infinity, // final boolean [][] is_infinity, // may be null, if not - may be infinity from the composite depth map true, // final boolean only_infinity, // do not process non-infinity num_tiles[0], // int [] in_num_tiles, // null or array of number of clusters inf_cluster, // boolean [] in_inf_cluster, // null or array of number of clusters, will return if cluster uses only infinite tiles threadsMax, // final int threadsMax, debug); // final boolean debug) if (dbg_disparity_offset != 0.0) { for (int nscene = 0; nscene < target_disparities_inf.length; nscene++) { for (int i = 0; i < target_disparities_inf[nscene].length; i++) { if (!Double.isNaN(target_disparities_inf[nscene][i])) { target_disparities_inf[nscene][i] += dbg_disparity_offset; } } } } inf_noinf_lazy_eye_data[0] = MultisceneLY.getLYData( // TODO: show lazy_eye_data[][] clt_parameters, // final CLTParameters clt_parameters, clust_size, // final int clust_size, scenes, // final QuadCLT [] scenes, // ordered by increasing timestamps target_disparities_inf, // final double[][] target_disparities, num_tiles[0], // final int [] num_tiles, threadsMax, // final int threadsMax, debug_level); // final int debug_level); // now for non-infinity: double [][] target_disparities_noinf = MultisceneLY.useTilesLY( clust_size, // final int clust_size, inf_range, // final double inf_range, // full range centered at inf_disp_ref to be used as infinity scene_range, // final double scene_range, // disparity range for non-infinity in the same cluster min_num_inf, // final int min_num_inf, // Minimal number of tiles (in all scenes total) in an infinity cluster scenes, // final QuadCLT [] scenes, // ordered by increasing timestamps valid_tile, // final boolean [][] valid_tile, // tile with lma and single correlation maximum inf_disp_ref, // final double inf_disp_ref, // average disparity at infinity for ref scene // is_scene_infinity null, // final boolean [][] is_infinity, // may be null, if not - may be infinity from the composite depth map false, // final boolean only_infinity, // do not process non-infinity num_tiles[1], // int [] in_num_tiles, // null or array of number of clusters inf_cluster, // boolean [] in_inf_cluster, // null or array of number of clusters, will return if cluster uses only infinite tiles threadsMax, // final int threadsMax, debug); // final boolean debug) if (dbg_disparity_offset != 0.0) { for (int nscene = 0; nscene < target_disparities_noinf.length; nscene++) { for (int i = 0; i < target_disparities_noinf[nscene].length; i++) { if (!Double.isNaN(target_disparities_noinf[nscene][i])) { target_disparities_noinf[nscene][i] += dbg_disparity_offset; } } } } inf_noinf_lazy_eye_data[1] = MultisceneLY.getLYData( // TODO: show lazy_eye_data[][] clt_parameters, // final CLTParameters clt_parameters, clust_size, // final int clust_size, scenes, // final QuadCLT [] scenes, // ordered by increasing timestamps target_disparities_noinf, // final double[][] target_disparities, num_tiles[1], // final int [] num_tiles, threadsMax, // final int threadsMax, debug_level); // final int debug_level); if (target_disparities != null) { target_disparities[0] = target_disparities_inf; target_disparities[1] = target_disparities_noinf; } return inf_noinf_lazy_eye_data; } public static double [][] getLYData( final CLTParameters clt_parameters, final int clust_size, final QuadCLT [] scenes, // ordered by increasing timestamps final double[][] target_disparities, final int [] num_tiles, final int [] num_tiles, // null or number of tiles per cluster to multiply strength final int threadsMax, final int debug_level){ int last_scene_index = scenes.length-1; Loading Loading @@ -700,6 +827,24 @@ public class MultisceneLY { true, last_scene.getImageName()+"-CORR-DECIMATED"+clust_size, titles); double [][] disparity_map_decimated = ImageDtt.corr2d_decimate( // not used in lwir disparity_map, // final float [][] corr2d_img, tilesX, // final int tilesX, tilesY, // final int tilesY, clust_size, // final int clust_size, wh, // final int [] wh, threadsMax, // final int threadsMax, // maximal number of threads to launch debug_level); // final int globalDebugLevel) (new ShowDoubleFloatArrays()).showArrays( disparity_map_decimated, wh[0], wh[1], true, "disparity_map_decimated", ImageDtt.getDisparityTitles(last_scene.getNumSensors(),last_scene.isMonochrome()) // ImageDtt.DISPARITY_TITLES ); } final double [][] rXY = last_scene.getErsCorrection().getRXY(false); Loading @@ -719,7 +864,9 @@ public class MultisceneLY { lazy_eye_data[nClust] = new double [ExtrinsicAdjustment.get_INDX_LENGTH(numSens)]; // Number of tiles, strength or a product double strength = disparity_map[ImageDtt.DISPARITY_INDEX_POLY + 1][nTile0]; if (num_tiles != null) { strength *= num_tiles[nClust]; } lazy_eye_data[nClust][ExtrinsicAdjustment.INDX_STRENGTH] = strength; lazy_eye_data[nClust][ExtrinsicAdjustment.INDX_TARGET] = combo_pXpYD[nTile0][2]; lazy_eye_data[nClust][ExtrinsicAdjustment.INDX_DIFF] = disparity_map[ImageDtt.DISPARITY_INDEX_POLY][nTile0]; Loading Loading
src/main/java/com/elphel/imagej/cameras/CLTParameters.java +74 −16 Original line number Diff line number Diff line Loading @@ -321,6 +321,21 @@ public class CLTParameters { public boolean lyr_filter_ds = false; // true; public boolean lyr_filter_lyf = false; // ~clt_parameters.lyf_filter, but may be different, now off for a single cameras // Multi-scene LY parameters // Infinity detection public double lyms_far_inf = -0.5; // Far limit when searching for infinity objects public double lyms_near_inf = 0.5; // Near limit when searching for infinity objects public double lyms_far_fract = 0.05; // Mode of disparity distribution within range public double lyms_inf_range_offs = 0.05; // Add to the disparity distribution mode for infinity center public double lyms_inf_range = 0.15; // Consider infinity tiles that are within +/- half of this range from infinity center //non-infinity parameters public double lyms_min_inf_str = 0.2; // Minimal strength of infinity tiles public double lyms_min_fg_str = 0.4; // Minimal strength of non-infinity tiles public int lyms_clust_size = 4; // cluster size (same in both directions) for measuring LY data public double lyms_scene_range = 10.0; // disparity range for non-infinity in the same cluster public int lyms_min_num_inf = 10; // Minimal number of tiles (in all scenes total) in an infinity cluster // old fcorr parameters, reuse? // public int fcorr_sample_size = 32; // Use square this size side to detect outliers Loading Loading @@ -1243,6 +1258,17 @@ public class CLTParameters { properties.setProperty(prefix+"lyr_filter_ds", this.lyr_filter_ds +""); properties.setProperty(prefix+"lyr_filter_lyf", this.lyr_filter_lyf +""); properties.setProperty(prefix+"lyms_far_inf", this.lyms_far_inf +""); properties.setProperty(prefix+"lyms_near_inf", this.lyms_near_inf +""); properties.setProperty(prefix+"lyms_far_fract", this.lyms_far_fract +""); properties.setProperty(prefix+"lyms_inf_range_offs", this.lyms_inf_range_offs +""); properties.setProperty(prefix+"lyms_inf_range", this.lyms_inf_range +""); properties.setProperty(prefix+"lyms_min_inf_str", this.lyms_min_inf_str +""); properties.setProperty(prefix+"lyms_min_fg_str", this.lyms_min_fg_str +""); properties.setProperty(prefix+"lyms_clust_size", this.lyms_clust_size +""); properties.setProperty(prefix+"lyms_scene_range", this.lyms_scene_range +""); properties.setProperty(prefix+"lyms_min_num_inf", this.lyms_min_num_inf +""); properties.setProperty(prefix+"corr_magic_scale", this.corr_magic_scale +""); properties.setProperty(prefix+"corr_select", this.corr_select +""); Loading Loading @@ -2073,6 +2099,17 @@ public class CLTParameters { if (properties.getProperty(prefix+"lyr_filter_ds")!=null) this.lyr_filter_ds=Boolean.parseBoolean(properties.getProperty(prefix+"lyr_filter_ds")); if (properties.getProperty(prefix+"lyr_filter_lyf")!=null) this.lyr_filter_lyf=Boolean.parseBoolean(properties.getProperty(prefix+"lyr_filter_lyf")); if (properties.getProperty(prefix+"lyms_far_inf")!=null) this.lyms_far_inf=Double.parseDouble(properties.getProperty(prefix+"lyms_far_inf")); if (properties.getProperty(prefix+"lyms_near_inf")!=null) this.lyms_near_inf=Double.parseDouble(properties.getProperty(prefix+"lyms_near_inf")); if (properties.getProperty(prefix+"lyms_far_fract")!=null) this.lyms_far_fract=Double.parseDouble(properties.getProperty(prefix+"lyms_far_fract")); if (properties.getProperty(prefix+"lyms_inf_range_offs")!=null) this.lyms_inf_range_offs=Double.parseDouble(properties.getProperty(prefix+"lyms_inf_range_offs")); if (properties.getProperty(prefix+"lyms_inf_range")!=null) this.lyms_inf_range=Double.parseDouble(properties.getProperty(prefix+"lyms_inf_range")); if (properties.getProperty(prefix+"lyms_min_inf_str")!=null) this.lyms_min_inf_str=Double.parseDouble(properties.getProperty(prefix+"lyms_min_inf_str")); if (properties.getProperty(prefix+"lyms_min_fg_str")!=null) this.lyms_min_fg_str=Double.parseDouble(properties.getProperty(prefix+"lyms_min_fg_str")); if (properties.getProperty(prefix+"lyms_clust_size")!=null) this.lyms_clust_size=Integer.parseInt(properties.getProperty(prefix+"lyms_clust_size")); if (properties.getProperty(prefix+"lyms_scene_range")!=null) this.lyms_scene_range=Double.parseDouble(properties.getProperty(prefix+"lyms_scene_range")); if (properties.getProperty(prefix+"lyms_min_num_inf")!=null) this.lyms_min_num_inf=Integer.parseInt(properties.getProperty(prefix+"lyms_min_num_inf")); if (properties.getProperty(prefix+"corr_magic_scale")!=null) this.corr_magic_scale=Double.parseDouble(properties.getProperty(prefix+"corr_magic_scale")); if (properties.getProperty(prefix+"corr_select")!=null) this.corr_select=Integer.parseInt(properties.getProperty(prefix+"corr_select")); Loading Loading @@ -3006,13 +3043,30 @@ public class CLTParameters { gd.addCheckbox ("Filter lazy eye pairs by their values wen GT data is available", this.lyr_filter_lyf, "Same as \"Filter lazy eye pairs by their values\" above, but for the rig-guided adjustments"); // gd.addNumericField("Use square this size side to detect outliers", this.fcorr_sample_size, 0); // gd.addNumericField("Keep tiles only if there are more in each square", this.fcorr_mintiles, 0); // gd.addNumericField("Remove this fraction of tiles from each sample", this.fcorr_reloutliers, 3); // gd.addNumericField("Gaussian blur channel mismatch data", this.fcorr_sigma, 3); /// gd.addNumericField("Calculated from correlation offset vs. actual one (not yet understood)", this.corr_magic_scale, 3); gd.addTab ("LY multiscene", "Multiscene series Lazy Eye correction"); gd.addMessage ("--- Infinity detection ---"); gd.addNumericField("Infinity far", this.lyms_far_inf, 4,6,"pix", "Far limit when searching for infinity objects"); gd.addNumericField("Infinity near", this.lyms_near_inf, 4,6,"pix", "Near limit when searching for infinity objects"); gd.addNumericField("Infinity mode (0.0 - min, 1.0 - max", this.lyms_far_fract, 4,6,"", "Mode of disparity distribution within range (0.0 - min, 1.0 - max)"); gd.addNumericField("Offset infinity center from mode", this.lyms_inf_range_offs, 4,6,"pix", "Add to the disparity distribution mode for infinity center"); gd.addNumericField("Infinity full range", this.lyms_inf_range, 4,6,"pix", "Consider infinity tiles that are within +/- half of this range from infinity center"); gd.addMessage ("--- LY data measurement ---"); gd.addNumericField("Minimal strength (infinity)", this.lyms_min_inf_str, 4,6,"", "Minimal strength of infinity tiles"); gd.addNumericField("Minimal strength (non-infinity)", this.lyms_min_fg_str, 4,6,"", "Minimal strength of non-infinity tiles"); gd.addNumericField("Cluster size", this.lyms_clust_size, 0,3,"pix", "Cluster size (same in both directions) for measuring LY data"); gd.addNumericField("Per-scene disparity range", this.lyms_scene_range, 4,6,"pix", "Disparity range for non-infinity in the same cluster"); gd.addNumericField("Minimal number of infinity tiles", this.lyms_min_num_inf, 0,3,"", "Minimal number of tiles (in all scenes total) in an infinity cluster"); gd.addTab ("3D", "3D reconstruction"); gd.addMessage ("--- 3D reconstruction ---"); Loading Loading @@ -3977,12 +4031,16 @@ public class CLTParameters { this.lyr_filter_ds= gd.getNextBoolean(); this.lyr_filter_lyf= gd.getNextBoolean(); // this.fcorr_sample_size= (int)gd.getNextNumber(); // this.fcorr_mintiles= (int) gd.getNextNumber(); // this.fcorr_reloutliers= gd.getNextNumber(); // this.fcorr_sigma= gd.getNextNumber(); /// this.corr_magic_scale= gd.getNextNumber(); this.lyms_far_inf= gd.getNextNumber(); this.lyms_near_inf= gd.getNextNumber(); this.lyms_far_fract= gd.getNextNumber(); this.lyms_inf_range_offs= gd.getNextNumber(); this.lyms_inf_range= gd.getNextNumber(); this.lyms_min_inf_str= gd.getNextNumber(); this.lyms_min_fg_str= gd.getNextNumber(); this.lyms_clust_size= (int) gd.getNextNumber(); this.lyms_scene_range= gd.getNextNumber(); this.lyms_min_num_inf=(int) gd.getNextNumber(); this.show_textures= gd.getNextBoolean(); this.debug_filters= gd.getNextBoolean(); Loading
src/main/java/com/elphel/imagej/tileprocessor/ImageDttCPU.java +58 −0 Original line number Diff line number Diff line Loading @@ -8950,6 +8950,64 @@ public class ImageDttCPU { return corr2d_decimated; } public static double [][] corr2d_decimate( // not used in lwir final double [][] corr2d_img, final int tilesX, final int tilesY, final int clust_size, final int [] wh, final int threadsMax, // maximal number of threads to launch final int globalDebugLevel) { int len = 0; final double [][] corr2d_decimated = new double [corr2d_img.length][]; for (int i = 0; i < corr2d_img.length; i++) { if (corr2d_img[i] != null) { len = corr2d_img[i].length; break; } } final int tile_size = (int) Math.round(Math.sqrt(len/(tilesX * tilesY))); final int clustersX = (int) Math.ceil(1.0 * tilesX / clust_size); final int clustersY = (int) Math.ceil(1.0 * tilesY / clust_size); final int clusters = clustersX * clustersY; final Thread[] threads = newThreadArray(threadsMax); final AtomicInteger ai = new AtomicInteger(0); final int clust_lines = clust_size * tile_size; final int in_line_len = clustersX * clust_size * tile_size; final int out_line_len = clustersX * tile_size; if (wh != null) { wh[0] = clustersX * tile_size; wh[1] = clustersY * tile_size; } for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { @Override public void run() { for (int nLayer = ai.getAndIncrement(); nLayer < corr2d_img.length; nLayer = ai.getAndIncrement()) { if (corr2d_img[nLayer] != null){ corr2d_decimated[nLayer] = new double [clusters * tile_size * tile_size]; for (int clustY = 0; clustY < clustersY; clustY++) { for (int clustX = 0; clustX < clustersX; clustX++) { int offs = clustY * clust_lines * in_line_len; for (int line = 0; line < tile_size; line++) { System.arraycopy( corr2d_img[nLayer], (clustY * clust_lines + line) * in_line_len + clustX * clust_lines, corr2d_decimated[nLayer], (clustY * tile_size + line) * out_line_len + clustX * tile_size, tile_size); } } } } } } }; } startAndJoin(threads); return corr2d_decimated; } Loading
src/main/java/com/elphel/imagej/tileprocessor/MultisceneLY.java +216 −69 Original line number Diff line number Diff line Loading @@ -281,10 +281,12 @@ public class MultisceneLY { final int clust_size, final double inf_range, // full range centered at inf_disp_ref to be used as infinity final double scene_range, // disparity range for non-infinity in the same cluster final int min_num_inf, // Minimal number of tiles (in all scenes total) in an infinity cluster final QuadCLT [] scenes, // ordered by increasing timestamps final boolean [][] valid_tile, // tile with lma and single correlation maximum final double inf_disp_ref, // average disparity at infinity for ref scene final boolean [][] is_infinity, // may be null, if not - may be infinity from the composite depth map final boolean [][] is_infinity, // may be null (all non-infinity), if not - may be infinity from the composite depth map final boolean only_infinity, // do not process non-infinity int [] in_num_tiles, // null or array of number of clusters boolean [] in_inf_cluster, // null or array of number of clusters, will return if cluster uses only infinite tiles final int threadsMax, Loading @@ -303,6 +305,10 @@ public class MultisceneLY { final int [] num_tiles = (in_num_tiles != null)? in_num_tiles : (new int [clusters]); final boolean [] inf_cluster = (in_inf_cluster != null)? in_inf_cluster : (new boolean [clusters]); Arrays.fill(num_tiles, 0); Arrays.fill(inf_cluster, false); final int [] num_inf_cluster = new int[clusters]; for (int nscene = 0; nscene < num_scenes; nscene++) { target_disparities[nscene] = scenes[nscene].getDSRBG()[0]; Arrays.fill(rslt_disparities[nscene], Double.NaN); Loading @@ -314,7 +320,7 @@ public class MultisceneLY { for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { Cluster: // Cluster: for (int nClust = ai.getAndIncrement(); nClust < clusters; nClust = ai.getAndIncrement()) { int clustX = nClust % clustersX; int clustY = nClust / clustersX; Loading @@ -329,20 +335,36 @@ public class MultisceneLY { if (is_infinity[nscene][nTile] && valid_tile[nscene][nTile] && // next may be NaN (Math.abs(target_disparities[nscene][nTile] - inf_disp_ref) <= inf_hrange)) { inf_cluster[nClust] = true; continue Cluster; num_inf_cluster[nClust]++; // inf_cluster[nClust] = true; // continue Cluster; } } } } } } } } }; } ImageDtt.startAndJoin(threads); ai.set(0); // mark clusters as infinity if they have enough infinity tiles for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int nClust = ai.getAndIncrement(); nClust < clusters; nClust = ai.getAndIncrement()) { if (num_inf_cluster[nClust] >= min_num_inf) { inf_cluster[nClust] = true; } } } }; } ImageDtt.startAndJoin(threads); // Mark suitable infinity tiles (they are NaN now) ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { Loading Loading @@ -378,6 +400,7 @@ public class MultisceneLY { ImageDtt.startAndJoin(threads); } if (!only_infinity) { ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { Loading Loading @@ -454,15 +477,119 @@ public class MultisceneLY { }; } ImageDtt.startAndJoin(threads); } return rslt_disparities; } public static double [][][] getLYDataInfNoinf( final CLTParameters clt_parameters, final int clust_size, final double inf_range, // full range centered at inf_disp_ref to be used as infinity final double scene_range, // disparity range for non-infinity in the same cluster final int min_num_inf, // Minimal number of tiles (in all scenes total) in an infinity cluster final QuadCLT [] scenes, // ordered by increasing timestamps final boolean [][] valid_tile, // tile with lma and single correlation maximum final double inf_disp_ref, // average disparity at infinity for ref scene // is_scene_infinity final boolean [][] is_scene_infinity, // may be null, if not - may be infinity from the composite depth map final double [][][] target_disparities, final double dbg_disparity_offset, final int [][] in_num_tiles, // null or number of tiles per cluster to multiply strength final int threadsMax, final int debug_level){ final double [][][] inf_noinf_lazy_eye_data = new double [2][][]; int last_scene_index = scenes.length-1; QuadCLT last_scene = scenes[last_scene_index]; int tilesX = last_scene.tp.getTilesX(); int tilesY = last_scene.tp.getTilesY(); int clustersX = (int) Math.ceil(1.0 * tilesX / clust_size); int clustersY = (int) Math.ceil(1.0 * tilesY / clust_size); int clusters = clustersX * clustersY; final int [][] num_tiles = (in_num_tiles != null)? in_num_tiles : (new int [2][]); for (int i = 0; i < num_tiles.length; i++) { num_tiles[i] = new int [clusters]; } // int [][] num_tiles = new int [2][clusters]; // may be null;; // null; boolean [] inf_cluster = new boolean [clusters]; // null; boolean debug = debug_level > -3; // get for infinity only double [][] target_disparities_inf = MultisceneLY.useTilesLY( clust_size, // final int clust_size, inf_range, // final double inf_range, // full range centered at inf_disp_ref to be used as infinity scene_range, // final double scene_range, // disparity range for non-infinity in the same cluster min_num_inf, // final int min_num_inf, // Minimal number of tiles (in all scenes total) in an infinity cluster scenes, // final QuadCLT [] scenes, // ordered by increasing timestamps valid_tile, // final boolean [][] valid_tile, // tile with lma and single correlation maximum inf_disp_ref, // final double inf_disp_ref, // average disparity at infinity for ref scene // is_scene_infinity is_scene_infinity, // final boolean [][] is_infinity, // may be null, if not - may be infinity from the composite depth map true, // final boolean only_infinity, // do not process non-infinity num_tiles[0], // int [] in_num_tiles, // null or array of number of clusters inf_cluster, // boolean [] in_inf_cluster, // null or array of number of clusters, will return if cluster uses only infinite tiles threadsMax, // final int threadsMax, debug); // final boolean debug) if (dbg_disparity_offset != 0.0) { for (int nscene = 0; nscene < target_disparities_inf.length; nscene++) { for (int i = 0; i < target_disparities_inf[nscene].length; i++) { if (!Double.isNaN(target_disparities_inf[nscene][i])) { target_disparities_inf[nscene][i] += dbg_disparity_offset; } } } } inf_noinf_lazy_eye_data[0] = MultisceneLY.getLYData( // TODO: show lazy_eye_data[][] clt_parameters, // final CLTParameters clt_parameters, clust_size, // final int clust_size, scenes, // final QuadCLT [] scenes, // ordered by increasing timestamps target_disparities_inf, // final double[][] target_disparities, num_tiles[0], // final int [] num_tiles, threadsMax, // final int threadsMax, debug_level); // final int debug_level); // now for non-infinity: double [][] target_disparities_noinf = MultisceneLY.useTilesLY( clust_size, // final int clust_size, inf_range, // final double inf_range, // full range centered at inf_disp_ref to be used as infinity scene_range, // final double scene_range, // disparity range for non-infinity in the same cluster min_num_inf, // final int min_num_inf, // Minimal number of tiles (in all scenes total) in an infinity cluster scenes, // final QuadCLT [] scenes, // ordered by increasing timestamps valid_tile, // final boolean [][] valid_tile, // tile with lma and single correlation maximum inf_disp_ref, // final double inf_disp_ref, // average disparity at infinity for ref scene // is_scene_infinity null, // final boolean [][] is_infinity, // may be null, if not - may be infinity from the composite depth map false, // final boolean only_infinity, // do not process non-infinity num_tiles[1], // int [] in_num_tiles, // null or array of number of clusters inf_cluster, // boolean [] in_inf_cluster, // null or array of number of clusters, will return if cluster uses only infinite tiles threadsMax, // final int threadsMax, debug); // final boolean debug) if (dbg_disparity_offset != 0.0) { for (int nscene = 0; nscene < target_disparities_noinf.length; nscene++) { for (int i = 0; i < target_disparities_noinf[nscene].length; i++) { if (!Double.isNaN(target_disparities_noinf[nscene][i])) { target_disparities_noinf[nscene][i] += dbg_disparity_offset; } } } } inf_noinf_lazy_eye_data[1] = MultisceneLY.getLYData( // TODO: show lazy_eye_data[][] clt_parameters, // final CLTParameters clt_parameters, clust_size, // final int clust_size, scenes, // final QuadCLT [] scenes, // ordered by increasing timestamps target_disparities_noinf, // final double[][] target_disparities, num_tiles[1], // final int [] num_tiles, threadsMax, // final int threadsMax, debug_level); // final int debug_level); if (target_disparities != null) { target_disparities[0] = target_disparities_inf; target_disparities[1] = target_disparities_noinf; } return inf_noinf_lazy_eye_data; } public static double [][] getLYData( final CLTParameters clt_parameters, final int clust_size, final QuadCLT [] scenes, // ordered by increasing timestamps final double[][] target_disparities, final int [] num_tiles, final int [] num_tiles, // null or number of tiles per cluster to multiply strength final int threadsMax, final int debug_level){ int last_scene_index = scenes.length-1; Loading Loading @@ -700,6 +827,24 @@ public class MultisceneLY { true, last_scene.getImageName()+"-CORR-DECIMATED"+clust_size, titles); double [][] disparity_map_decimated = ImageDtt.corr2d_decimate( // not used in lwir disparity_map, // final float [][] corr2d_img, tilesX, // final int tilesX, tilesY, // final int tilesY, clust_size, // final int clust_size, wh, // final int [] wh, threadsMax, // final int threadsMax, // maximal number of threads to launch debug_level); // final int globalDebugLevel) (new ShowDoubleFloatArrays()).showArrays( disparity_map_decimated, wh[0], wh[1], true, "disparity_map_decimated", ImageDtt.getDisparityTitles(last_scene.getNumSensors(),last_scene.isMonochrome()) // ImageDtt.DISPARITY_TITLES ); } final double [][] rXY = last_scene.getErsCorrection().getRXY(false); Loading @@ -719,7 +864,9 @@ public class MultisceneLY { lazy_eye_data[nClust] = new double [ExtrinsicAdjustment.get_INDX_LENGTH(numSens)]; // Number of tiles, strength or a product double strength = disparity_map[ImageDtt.DISPARITY_INDEX_POLY + 1][nTile0]; if (num_tiles != null) { strength *= num_tiles[nClust]; } lazy_eye_data[nClust][ExtrinsicAdjustment.INDX_STRENGTH] = strength; lazy_eye_data[nClust][ExtrinsicAdjustment.INDX_TARGET] = combo_pXpYD[nTile0][2]; lazy_eye_data[nClust][ExtrinsicAdjustment.INDX_DIFF] = disparity_map[ImageDtt.DISPARITY_INDEX_POLY][nTile0]; Loading