Loading src/main/java/com/elphel/imagej/tileprocessor/IntersceneMatchParameters.java +13 −4 Original line number Original line Diff line number Diff line Loading @@ -892,6 +892,8 @@ min_str_neib_fpn 0.35 public int terr_num_exaggerate = 3; // generate exaggerated rendering public int terr_num_exaggerate = 3; // generate exaggerated rendering // Experimental reconstruction // Experimental reconstruction public boolean terr_rebuild_elev = false; // rebuild elevations and scales public int terr_elev_grow = 1024; // was 200 public double terr_threshold_terrain = 0.05; public double terr_threshold_terrain = 0.05; public double terr_min_max_terrain= 0.1; public double terr_min_max_terrain= 0.1; public double terr_min_terrain = 0.001; public double terr_min_terrain = 0.001; Loading Loading @@ -2249,6 +2251,9 @@ min_str_neib_fpn 0.35 gd.addNumericField("Exagerrate steps", terr_num_exaggerate, 0,3,"", "."); gd.addNumericField("Exagerrate steps", terr_num_exaggerate, 0,3,"", "."); gd.addMessage ("Experimental"); gd.addMessage ("Experimental"); gd.addCheckbox ("Rebuild elevations", terr_rebuild_elev, "Regenerate elevations/scales in *.terrveg-tiff file"); gd.addNumericField("Grow elevations", terr_elev_grow, 0,3,"","Grow elevations over NaNs."); gd.addNumericField("Terrain threshold alpha",terr_threshold_terrain, 5,7,"", "."); gd.addNumericField("Terrain threshold alpha",terr_threshold_terrain, 5,7,"", "."); gd.addNumericField("Min max terrain", terr_min_max_terrain, 5,7,"", "."); gd.addNumericField("Min max terrain", terr_min_max_terrain, 5,7,"", "."); gd.addNumericField("Minimal terrain", terr_min_terrain, 5,7,"", "."); gd.addNumericField("Minimal terrain", terr_min_terrain, 5,7,"", "."); Loading Loading @@ -3021,7 +3026,8 @@ min_str_neib_fpn 0.35 terr_boost_render = gd.getNextNumber(); // double terr_boost_render = gd.getNextNumber(); // double terr_max_render = gd.getNextNumber(); // double terr_max_render = gd.getNextNumber(); // double terr_num_exaggerate = (int)gd.getNextNumber(); // int terr_num_exaggerate = (int)gd.getNextNumber(); // int terr_rebuild_elev = gd.getNextBoolean();// boolean terr_elev_grow = (int)gd.getNextNumber(); // int terr_threshold_terrain = gd.getNextNumber();// double terr_threshold_terrain = gd.getNextNumber();// double terr_min_max_terrain = gd.getNextNumber();// double terr_min_max_terrain = gd.getNextNumber();// double terr_min_terrain = gd.getNextNumber();// double terr_min_terrain = gd.getNextNumber();// double Loading Loading @@ -3772,7 +3778,8 @@ min_str_neib_fpn 0.35 properties.setProperty(prefix+"terr_boost_render", terr_boost_render+""); // double properties.setProperty(prefix+"terr_boost_render", terr_boost_render+""); // double properties.setProperty(prefix+"terr_max_render", terr_max_render+""); // double properties.setProperty(prefix+"terr_max_render", terr_max_render+""); // double properties.setProperty(prefix+"terr_num_exaggerate", terr_num_exaggerate+""); // int properties.setProperty(prefix+"terr_num_exaggerate", terr_num_exaggerate+""); // int properties.setProperty(prefix+"terr_rebuild_elev", terr_rebuild_elev+""); // boolean properties.setProperty(prefix+"terr_elev_grow", terr_elev_grow+""); // int properties.setProperty(prefix+"terr_threshold_terrain", terr_threshold_terrain+""); // double properties.setProperty(prefix+"terr_threshold_terrain", terr_threshold_terrain+""); // double properties.setProperty(prefix+"terr_min_max_terrain", terr_min_max_terrain+""); // double properties.setProperty(prefix+"terr_min_max_terrain", terr_min_max_terrain+""); // double properties.setProperty(prefix+"terr_min_terrain", terr_min_terrain+""); // double properties.setProperty(prefix+"terr_min_terrain", terr_min_terrain+""); // double Loading Loading @@ -4543,7 +4550,8 @@ min_str_neib_fpn 0.35 if (properties.getProperty(prefix+"terr_boost_render")!= null) terr_boost_render=Double.parseDouble(properties.getProperty(prefix+"terr_boost_render")); if (properties.getProperty(prefix+"terr_boost_render")!= null) terr_boost_render=Double.parseDouble(properties.getProperty(prefix+"terr_boost_render")); if (properties.getProperty(prefix+"terr_max_render")!= null) terr_max_render=Double.parseDouble(properties.getProperty(prefix+"terr_max_render")); if (properties.getProperty(prefix+"terr_max_render")!= null) terr_max_render=Double.parseDouble(properties.getProperty(prefix+"terr_max_render")); if (properties.getProperty(prefix+"terr_num_exaggerate")!= null) terr_num_exaggerate=Integer.parseInt(properties.getProperty(prefix+"terr_num_exaggerate")); if (properties.getProperty(prefix+"terr_num_exaggerate")!= null) terr_num_exaggerate=Integer.parseInt(properties.getProperty(prefix+"terr_num_exaggerate")); if (properties.getProperty(prefix+"terr_rebuild_elev")!= null) terr_rebuild_elev=Boolean.parseBoolean(properties.getProperty(prefix+"terr_rebuild_elev")); if (properties.getProperty(prefix+"terr_elev_grow")!= null) terr_elev_grow=Integer.parseInt(properties.getProperty(prefix+"terr_elev_grow")); if (properties.getProperty(prefix+"terr_threshold_terrain")!= null) terr_threshold_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_threshold_terrain")); if (properties.getProperty(prefix+"terr_threshold_terrain")!= null) terr_threshold_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_threshold_terrain")); if (properties.getProperty(prefix+"terr_min_max_terrain")!= null) terr_min_max_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_max_terrain")); if (properties.getProperty(prefix+"terr_min_max_terrain")!= null) terr_min_max_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_max_terrain")); if (properties.getProperty(prefix+"terr_min_terrain")!= null) terr_min_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_terrain")); if (properties.getProperty(prefix+"terr_min_terrain")!= null) terr_min_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_terrain")); Loading Loading @@ -5275,7 +5283,8 @@ min_str_neib_fpn 0.35 imp.terr_boost_render = this.terr_boost_render; imp.terr_boost_render = this.terr_boost_render; imp.terr_max_render = this.terr_max_render; imp.terr_max_render = this.terr_max_render; imp.terr_num_exaggerate = this.terr_num_exaggerate; imp.terr_num_exaggerate = this.terr_num_exaggerate; imp.terr_rebuild_elev = this.terr_rebuild_elev; imp.terr_elev_grow = this.terr_elev_grow; imp.terr_threshold_terrain = this.terr_threshold_terrain; imp.terr_threshold_terrain = this.terr_threshold_terrain; imp.terr_min_max_terrain = this.terr_min_max_terrain; imp.terr_min_max_terrain = this.terr_min_max_terrain; imp.terr_min_terrain = this.terr_min_terrain; imp.terr_min_terrain = this.terr_min_terrain; Loading src/main/java/com/elphel/imagej/tileprocessor/TexturedModel.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -5531,7 +5531,8 @@ public class TexturedModel { 0.7, // double diagonal_weight, // relative to ortho 0.7, // double diagonal_weight, // relative to ortho 100, // int num_passes, 100, // int num_passes, 0.01, // final double max_rchange, // = 0.01 0.01, // final double max_rchange, // = 0.01 THREADS_MAX); // final int threadsMax) // maximal number of threads to launch THREADS_MAX, // final int threadsMax) // maximal number of threads to launch 0); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations if (dbg_img != null) dbg_img[4] = sky_pixels_filled.clone(); if (dbg_img != null) dbg_img[4] = sky_pixels_filled.clone(); if (blur_sigma > 0.0) { if (blur_sigma > 0.0) { (new DoubleGaussianBlur()).blurDouble( (new DoubleGaussianBlur()).blurDouble( Loading src/main/java/com/elphel/imagej/tileprocessor/TileProcessor.java +203 −7 Original line number Original line Diff line number Diff line Loading @@ -24,8 +24,10 @@ package com.elphel.imagej.tileprocessor; */ */ import java.awt.Rectangle; import java.awt.Rectangle; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Collections; import java.util.Comparator; import java.util.Comparator; //import java.util.concurrent.atomic.AtomicInteger; //import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -8805,7 +8807,8 @@ ImageDtt.startAndJoin(threads); diagonal_weight, //double diagonal_weight, // relative to ortho diagonal_weight, //double diagonal_weight, // relative to ortho num_passes, // int num_passes, num_passes, // int num_passes, max_rchange, // final double max_rchange, // = 0.01 max_rchange, // final double max_rchange, // = 0.01 ImageDtt.THREADS_MAX); // final int threadsMax) ImageDtt.THREADS_MAX, // final int threadsMax) 0); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations } } public static double [] fillNaNs( public static double [] fillNaNs( final double [] data, final double [] data, Loading @@ -8826,15 +8829,201 @@ ImageDtt.startAndJoin(threads); diagonal_weight, //double diagonal_weight, // relative to ortho diagonal_weight, //double diagonal_weight, // relative to ortho num_passes, // int num_passes, num_passes, // int num_passes, max_rchange, // final double max_rchange, // = 0.01 max_rchange, // final double max_rchange, // = 0.01 threadsMax); // final int threadsMax) threadsMax, // final int threadsMax) 0); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations } } /** * Us this one when filling full frame and prohibit is not used. Faster as it first tries lower resolution, then full * @param data_in input data array * @param width_full width of the input dtata * @param decimate_step decimation step (such as 16) * @param num_decimate number of decimation steps (should be >=1). If 1 just two passes * @param num_passes number of passes for each decimation step (100) * @param max_rchange maximal relative change to exit * @param debugTitle Generate images if non-null * @param debugLevel debug inner method: 0 - none, 1 - when done, 2 - all iterations * @return */ public static double [] fillNaNs( final double [] data_in, int width_full, final int decimate_step, // 16 final int num_decimate, int num_passes, final double max_rchange, // = 0.01 String debugTitle, final int debugLevel) { // 0 - none, 1 - when done, 2 - all iterations final int dbg_pix = (debugTitle == null) ? -1 : -1205; final double diagonal_weight = 0.7; // relative to ortho int height_full = data_in.length/width_full; if (debugTitle != null) { ShowDoubleFloatArrays.showArrays( data_in, width_full, height_full, debugTitle+"-data_in"); } double [] data_prev_filled = null; int width_prev = -1; double [] dbg_bkp = null; for (int ndecimate = num_decimate; ndecimate >= 0; ndecimate--) { int dcm = 1; for (int i = 0; i < ndecimate; i++) { dcm *= decimate_step; } final int decimate = dcm; final int width = (width_full+(decimate-1))/decimate; final int height = (height_full+(decimate-1))/decimate; final int num_pixels = width*height; final double [] data = new double[num_pixels]; final double [] data_nan = new double[num_pixels]; // only nan/non-nan final int grow = 2 * Math.max(width, height); if (ndecimate == num_decimate) { // prepare initial lo-res data final Thread[] threads = ImageDtt.newThreadArray(); final AtomicInteger ai = new AtomicInteger(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int nDecPix = ai.getAndIncrement(); nDecPix < num_pixels; nDecPix = ai.getAndIncrement()) { if (nDecPix == dbg_pix) { System.out.println("fillNaNs(multi) nDecPix="+nDecPix); } int x_dcm = nDecPix % width; int y_dcm = nDecPix / width; int num_defined = 0; double sum_val = 0; int x0_full = x_dcm*decimate; int x1_full = Math.min((x_dcm + 1) * decimate, width_full); int y0_full = y_dcm*decimate; int y1_full = Math.min((y_dcm + 1) * decimate, height_full); for (int y_full = y0_full; y_full < y1_full; y_full++) { for (int x_full = x0_full; x_full < x1_full; x_full++) { int pix_full = y_full * width_full + x_full; double d = data_in[pix_full]; if (!Double.isNaN(d)) { sum_val += d; num_defined++; } } } if (num_defined > 0) { data[nDecPix] = sum_val/num_defined; } else { data[nDecPix] = Double.NaN; } } } }; } ImageDtt.startAndJoin(threads); if (debugTitle != null) { dbg_bkp = data.clone(); } data_prev_filled = fillNaNs( data, // final double [] data, null, // final double [] data_nan, // only modify tiles that are not fixed null, // final boolean [] prohibit, width, // int width, grow, // final int grow, diagonal_weight, // double diagonal_weight, // relative to ortho num_passes, // int num_passes, max_rchange, //final double max_rchange, // = 0.01 ImageDtt.THREADS_MAX, // final int threadsMax) // maximal number of threads to launch debugLevel); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations } else { // assuming no NaN in data_prev_filled final double [] fdata_prev_filled = data_prev_filled; final int fwidth_prev = width_prev; final Thread[] threads = ImageDtt.newThreadArray(); final AtomicInteger ai = new AtomicInteger(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int nDecPix = ai.getAndIncrement(); nDecPix < num_pixels; nDecPix = ai.getAndIncrement()) { int x_dcm = nDecPix % width; int y_dcm = nDecPix / width; double sum_val = 0; int x0_full = x_dcm*decimate; int x1_full = Math.min((x_dcm + 1) * decimate, width_full); int y0_full = y_dcm*decimate; int y1_full = Math.min((y_dcm + 1) * decimate, height_full); int y_pdcm = y_dcm / decimate_step; int x_pdcm = x_dcm / decimate_step; int pix_prev = y_pdcm * fwidth_prev + x_pdcm; double d_prev = fdata_prev_filled[pix_prev]; int num_defined = (y1_full-y0_full) * (x1_full-x0_full); int num_defined1 = 0; int num_fixed = 0; // number of actually defined pixels (not filled in the previous steps for (int y_full = y0_full; y_full < y1_full; y_full++) { for (int x_full = x0_full; x_full < x1_full; x_full++) { int pix_full = y_full * width_full + x_full; double d = data_in[pix_full]; if (!Double.isNaN(d)) { sum_val += d; num_fixed ++; } else { sum_val += d_prev; } num_defined1++; } } if ((num_defined1 != num_defined) || (num_defined == 0)) { System.out.println("fillNaNs(multi) BUG: num_defined="+num_defined+", num_defined1="+num_defined1); } data[nDecPix] = sum_val/num_defined; data_nan[nDecPix] = (num_fixed > 0) ? data[nDecPix] : Double.NaN; // non-NaN may be any value, like 0.0; } } }; } ImageDtt.startAndJoin(threads); if (debugTitle != null) { dbg_bkp = data.clone(); } data_prev_filled = fillNaNs( data, // final double [] data, data_nan, // final double [] data_nan, // only modify tiles that are not fixed null, // final boolean [] prohibit, width, // int width, grow, // final int grow, diagonal_weight, // double diagonal_weight, // relative to ortho num_passes, // int num_passes, max_rchange, //final double max_rchange, // = 0.01 ImageDtt.THREADS_MAX, // final int threadsMax) // maximal number of threads to launch debugLevel); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations } if (debugTitle != null) { String [] dbg_titles = {"data","nan","filled"}; double [][] dbg_data = {dbg_bkp,data_nan, data_prev_filled}; ShowDoubleFloatArrays.showArrays( dbg_data, width, height, true, debugTitle+"-dcm"+decimate, dbg_titles); } width_prev = width; } return data_prev_filled; } /** /** * Fill NaN values in 2D array from neighbors using Laplacian==0 * Fill NaN values in 2D array from neighbors using Laplacian==0 * @param data data array (in line-scan order) with NaN values to be filled, * @param data data array (in line-scan order) with NaN values to be filled, * non-NaN values will not be modified. * non-NaN values will not be modified. * @param data_nan optional "original" data with NaN values to be replaced. If null, * @param data_nan optional "original" data with NaN values to be replaced. If null, * (single-pass) the data[] array will be used * (single-pass) the data[] array will be used * If non-null, will be used as a mask NaN/nonNaN and data - as initial values * @param prohibit_in optional (may be null) boolean array of the same size specifying * @param prohibit_in optional (may be null) boolean array of the same size specifying * prohibited pixels. * prohibited pixels. * @param width data width (height = data.length/width) * @param width data width (height = data.length/width) Loading @@ -8843,6 +9032,7 @@ ImageDtt.startAndJoin(threads); * @param num_passes maximal number of iterations. * @param num_passes maximal number of iterations. * @param max_rchange max relative (to data RMS) step change to exit iterations. * @param max_rchange max relative (to data RMS) step change to exit iterations. * @param threadsMax maximal number of concurrent threads to launch. * @param threadsMax maximal number of concurrent threads to launch. * @param debugLevel 0 - none, 1 - when done, 2 - all iterations * @return data array made of input data with replaced NaN limited by * @return data array made of input data with replaced NaN limited by * optional prohibit array and amount of growth. * optional prohibit array and amount of growth. */ */ Loading @@ -8855,7 +9045,8 @@ ImageDtt.startAndJoin(threads); double diagonal_weight, // relative to ortho double diagonal_weight, // relative to ortho int num_passes, int num_passes, final double max_rchange, // = 0.01 final double max_rchange, // = 0.01 final int threadsMax) // maximal number of threads to launch final int threadsMax, // maximal number of threads to launch final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations { { int height = data.length/width; int height = data.length/width; double wdiag = 0.25 *diagonal_weight / (diagonal_weight + 1.0); double wdiag = 0.25 *diagonal_weight / (diagonal_weight + 1.0); Loading Loading @@ -8984,6 +9175,9 @@ ImageDtt.startAndJoin(threads); s /= sw; s /= sw; data_io[1][nt] = s; data_io[1][nt] = s; last_change[ti] = Math.max(last_change[ti], Math.abs(data_io[1][nt]-data_io[0][nt])); last_change[ti] = Math.max(last_change[ti], Math.abs(data_io[1][nt]-data_io[0][nt])); if (Double.isNaN(last_change[ti] )) { System.out.println("fillNaNs():ti="+ti+",data_io[0]["+nt+"]="+data_io[0][nt]+",data_io[1]["+nt+"]="+data_io[1][nt]); } } } } } }; }; Loading @@ -8994,8 +9188,10 @@ ImageDtt.startAndJoin(threads); multi_change = Math.max(multi_change, last_change[i]); multi_change = Math.max(multi_change, last_change[i]); } } boolean done = (pass >= (num_passes - 1)) || (multi_change < max_change); boolean done = (pass >= (num_passes - 1)) || (multi_change < max_change); if (data_nan != null) { if ((debugLevel > 1) || ((debugLevel >0) && done)) { System.out.println("fillNaNs(): pass="+pass+" change="+multi_change+" done="+done); // if (data_nan != null) { System.out.println("fillNaNs(): "+(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime()))+ " pass="+pass+" change="+multi_change+" done="+done); } } if (done) { if (done) { break; break; Loading Loading
src/main/java/com/elphel/imagej/tileprocessor/IntersceneMatchParameters.java +13 −4 Original line number Original line Diff line number Diff line Loading @@ -892,6 +892,8 @@ min_str_neib_fpn 0.35 public int terr_num_exaggerate = 3; // generate exaggerated rendering public int terr_num_exaggerate = 3; // generate exaggerated rendering // Experimental reconstruction // Experimental reconstruction public boolean terr_rebuild_elev = false; // rebuild elevations and scales public int terr_elev_grow = 1024; // was 200 public double terr_threshold_terrain = 0.05; public double terr_threshold_terrain = 0.05; public double terr_min_max_terrain= 0.1; public double terr_min_max_terrain= 0.1; public double terr_min_terrain = 0.001; public double terr_min_terrain = 0.001; Loading Loading @@ -2249,6 +2251,9 @@ min_str_neib_fpn 0.35 gd.addNumericField("Exagerrate steps", terr_num_exaggerate, 0,3,"", "."); gd.addNumericField("Exagerrate steps", terr_num_exaggerate, 0,3,"", "."); gd.addMessage ("Experimental"); gd.addMessage ("Experimental"); gd.addCheckbox ("Rebuild elevations", terr_rebuild_elev, "Regenerate elevations/scales in *.terrveg-tiff file"); gd.addNumericField("Grow elevations", terr_elev_grow, 0,3,"","Grow elevations over NaNs."); gd.addNumericField("Terrain threshold alpha",terr_threshold_terrain, 5,7,"", "."); gd.addNumericField("Terrain threshold alpha",terr_threshold_terrain, 5,7,"", "."); gd.addNumericField("Min max terrain", terr_min_max_terrain, 5,7,"", "."); gd.addNumericField("Min max terrain", terr_min_max_terrain, 5,7,"", "."); gd.addNumericField("Minimal terrain", terr_min_terrain, 5,7,"", "."); gd.addNumericField("Minimal terrain", terr_min_terrain, 5,7,"", "."); Loading Loading @@ -3021,7 +3026,8 @@ min_str_neib_fpn 0.35 terr_boost_render = gd.getNextNumber(); // double terr_boost_render = gd.getNextNumber(); // double terr_max_render = gd.getNextNumber(); // double terr_max_render = gd.getNextNumber(); // double terr_num_exaggerate = (int)gd.getNextNumber(); // int terr_num_exaggerate = (int)gd.getNextNumber(); // int terr_rebuild_elev = gd.getNextBoolean();// boolean terr_elev_grow = (int)gd.getNextNumber(); // int terr_threshold_terrain = gd.getNextNumber();// double terr_threshold_terrain = gd.getNextNumber();// double terr_min_max_terrain = gd.getNextNumber();// double terr_min_max_terrain = gd.getNextNumber();// double terr_min_terrain = gd.getNextNumber();// double terr_min_terrain = gd.getNextNumber();// double Loading Loading @@ -3772,7 +3778,8 @@ min_str_neib_fpn 0.35 properties.setProperty(prefix+"terr_boost_render", terr_boost_render+""); // double properties.setProperty(prefix+"terr_boost_render", terr_boost_render+""); // double properties.setProperty(prefix+"terr_max_render", terr_max_render+""); // double properties.setProperty(prefix+"terr_max_render", terr_max_render+""); // double properties.setProperty(prefix+"terr_num_exaggerate", terr_num_exaggerate+""); // int properties.setProperty(prefix+"terr_num_exaggerate", terr_num_exaggerate+""); // int properties.setProperty(prefix+"terr_rebuild_elev", terr_rebuild_elev+""); // boolean properties.setProperty(prefix+"terr_elev_grow", terr_elev_grow+""); // int properties.setProperty(prefix+"terr_threshold_terrain", terr_threshold_terrain+""); // double properties.setProperty(prefix+"terr_threshold_terrain", terr_threshold_terrain+""); // double properties.setProperty(prefix+"terr_min_max_terrain", terr_min_max_terrain+""); // double properties.setProperty(prefix+"terr_min_max_terrain", terr_min_max_terrain+""); // double properties.setProperty(prefix+"terr_min_terrain", terr_min_terrain+""); // double properties.setProperty(prefix+"terr_min_terrain", terr_min_terrain+""); // double Loading Loading @@ -4543,7 +4550,8 @@ min_str_neib_fpn 0.35 if (properties.getProperty(prefix+"terr_boost_render")!= null) terr_boost_render=Double.parseDouble(properties.getProperty(prefix+"terr_boost_render")); if (properties.getProperty(prefix+"terr_boost_render")!= null) terr_boost_render=Double.parseDouble(properties.getProperty(prefix+"terr_boost_render")); if (properties.getProperty(prefix+"terr_max_render")!= null) terr_max_render=Double.parseDouble(properties.getProperty(prefix+"terr_max_render")); if (properties.getProperty(prefix+"terr_max_render")!= null) terr_max_render=Double.parseDouble(properties.getProperty(prefix+"terr_max_render")); if (properties.getProperty(prefix+"terr_num_exaggerate")!= null) terr_num_exaggerate=Integer.parseInt(properties.getProperty(prefix+"terr_num_exaggerate")); if (properties.getProperty(prefix+"terr_num_exaggerate")!= null) terr_num_exaggerate=Integer.parseInt(properties.getProperty(prefix+"terr_num_exaggerate")); if (properties.getProperty(prefix+"terr_rebuild_elev")!= null) terr_rebuild_elev=Boolean.parseBoolean(properties.getProperty(prefix+"terr_rebuild_elev")); if (properties.getProperty(prefix+"terr_elev_grow")!= null) terr_elev_grow=Integer.parseInt(properties.getProperty(prefix+"terr_elev_grow")); if (properties.getProperty(prefix+"terr_threshold_terrain")!= null) terr_threshold_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_threshold_terrain")); if (properties.getProperty(prefix+"terr_threshold_terrain")!= null) terr_threshold_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_threshold_terrain")); if (properties.getProperty(prefix+"terr_min_max_terrain")!= null) terr_min_max_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_max_terrain")); if (properties.getProperty(prefix+"terr_min_max_terrain")!= null) terr_min_max_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_max_terrain")); if (properties.getProperty(prefix+"terr_min_terrain")!= null) terr_min_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_terrain")); if (properties.getProperty(prefix+"terr_min_terrain")!= null) terr_min_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_terrain")); Loading Loading @@ -5275,7 +5283,8 @@ min_str_neib_fpn 0.35 imp.terr_boost_render = this.terr_boost_render; imp.terr_boost_render = this.terr_boost_render; imp.terr_max_render = this.terr_max_render; imp.terr_max_render = this.terr_max_render; imp.terr_num_exaggerate = this.terr_num_exaggerate; imp.terr_num_exaggerate = this.terr_num_exaggerate; imp.terr_rebuild_elev = this.terr_rebuild_elev; imp.terr_elev_grow = this.terr_elev_grow; imp.terr_threshold_terrain = this.terr_threshold_terrain; imp.terr_threshold_terrain = this.terr_threshold_terrain; imp.terr_min_max_terrain = this.terr_min_max_terrain; imp.terr_min_max_terrain = this.terr_min_max_terrain; imp.terr_min_terrain = this.terr_min_terrain; imp.terr_min_terrain = this.terr_min_terrain; Loading
src/main/java/com/elphel/imagej/tileprocessor/TexturedModel.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -5531,7 +5531,8 @@ public class TexturedModel { 0.7, // double diagonal_weight, // relative to ortho 0.7, // double diagonal_weight, // relative to ortho 100, // int num_passes, 100, // int num_passes, 0.01, // final double max_rchange, // = 0.01 0.01, // final double max_rchange, // = 0.01 THREADS_MAX); // final int threadsMax) // maximal number of threads to launch THREADS_MAX, // final int threadsMax) // maximal number of threads to launch 0); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations if (dbg_img != null) dbg_img[4] = sky_pixels_filled.clone(); if (dbg_img != null) dbg_img[4] = sky_pixels_filled.clone(); if (blur_sigma > 0.0) { if (blur_sigma > 0.0) { (new DoubleGaussianBlur()).blurDouble( (new DoubleGaussianBlur()).blurDouble( Loading
src/main/java/com/elphel/imagej/tileprocessor/TileProcessor.java +203 −7 Original line number Original line Diff line number Diff line Loading @@ -24,8 +24,10 @@ package com.elphel.imagej.tileprocessor; */ */ import java.awt.Rectangle; import java.awt.Rectangle; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Collections; import java.util.Comparator; import java.util.Comparator; //import java.util.concurrent.atomic.AtomicInteger; //import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -8805,7 +8807,8 @@ ImageDtt.startAndJoin(threads); diagonal_weight, //double diagonal_weight, // relative to ortho diagonal_weight, //double diagonal_weight, // relative to ortho num_passes, // int num_passes, num_passes, // int num_passes, max_rchange, // final double max_rchange, // = 0.01 max_rchange, // final double max_rchange, // = 0.01 ImageDtt.THREADS_MAX); // final int threadsMax) ImageDtt.THREADS_MAX, // final int threadsMax) 0); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations } } public static double [] fillNaNs( public static double [] fillNaNs( final double [] data, final double [] data, Loading @@ -8826,15 +8829,201 @@ ImageDtt.startAndJoin(threads); diagonal_weight, //double diagonal_weight, // relative to ortho diagonal_weight, //double diagonal_weight, // relative to ortho num_passes, // int num_passes, num_passes, // int num_passes, max_rchange, // final double max_rchange, // = 0.01 max_rchange, // final double max_rchange, // = 0.01 threadsMax); // final int threadsMax) threadsMax, // final int threadsMax) 0); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations } } /** * Us this one when filling full frame and prohibit is not used. Faster as it first tries lower resolution, then full * @param data_in input data array * @param width_full width of the input dtata * @param decimate_step decimation step (such as 16) * @param num_decimate number of decimation steps (should be >=1). If 1 just two passes * @param num_passes number of passes for each decimation step (100) * @param max_rchange maximal relative change to exit * @param debugTitle Generate images if non-null * @param debugLevel debug inner method: 0 - none, 1 - when done, 2 - all iterations * @return */ public static double [] fillNaNs( final double [] data_in, int width_full, final int decimate_step, // 16 final int num_decimate, int num_passes, final double max_rchange, // = 0.01 String debugTitle, final int debugLevel) { // 0 - none, 1 - when done, 2 - all iterations final int dbg_pix = (debugTitle == null) ? -1 : -1205; final double diagonal_weight = 0.7; // relative to ortho int height_full = data_in.length/width_full; if (debugTitle != null) { ShowDoubleFloatArrays.showArrays( data_in, width_full, height_full, debugTitle+"-data_in"); } double [] data_prev_filled = null; int width_prev = -1; double [] dbg_bkp = null; for (int ndecimate = num_decimate; ndecimate >= 0; ndecimate--) { int dcm = 1; for (int i = 0; i < ndecimate; i++) { dcm *= decimate_step; } final int decimate = dcm; final int width = (width_full+(decimate-1))/decimate; final int height = (height_full+(decimate-1))/decimate; final int num_pixels = width*height; final double [] data = new double[num_pixels]; final double [] data_nan = new double[num_pixels]; // only nan/non-nan final int grow = 2 * Math.max(width, height); if (ndecimate == num_decimate) { // prepare initial lo-res data final Thread[] threads = ImageDtt.newThreadArray(); final AtomicInteger ai = new AtomicInteger(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int nDecPix = ai.getAndIncrement(); nDecPix < num_pixels; nDecPix = ai.getAndIncrement()) { if (nDecPix == dbg_pix) { System.out.println("fillNaNs(multi) nDecPix="+nDecPix); } int x_dcm = nDecPix % width; int y_dcm = nDecPix / width; int num_defined = 0; double sum_val = 0; int x0_full = x_dcm*decimate; int x1_full = Math.min((x_dcm + 1) * decimate, width_full); int y0_full = y_dcm*decimate; int y1_full = Math.min((y_dcm + 1) * decimate, height_full); for (int y_full = y0_full; y_full < y1_full; y_full++) { for (int x_full = x0_full; x_full < x1_full; x_full++) { int pix_full = y_full * width_full + x_full; double d = data_in[pix_full]; if (!Double.isNaN(d)) { sum_val += d; num_defined++; } } } if (num_defined > 0) { data[nDecPix] = sum_val/num_defined; } else { data[nDecPix] = Double.NaN; } } } }; } ImageDtt.startAndJoin(threads); if (debugTitle != null) { dbg_bkp = data.clone(); } data_prev_filled = fillNaNs( data, // final double [] data, null, // final double [] data_nan, // only modify tiles that are not fixed null, // final boolean [] prohibit, width, // int width, grow, // final int grow, diagonal_weight, // double diagonal_weight, // relative to ortho num_passes, // int num_passes, max_rchange, //final double max_rchange, // = 0.01 ImageDtt.THREADS_MAX, // final int threadsMax) // maximal number of threads to launch debugLevel); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations } else { // assuming no NaN in data_prev_filled final double [] fdata_prev_filled = data_prev_filled; final int fwidth_prev = width_prev; final Thread[] threads = ImageDtt.newThreadArray(); final AtomicInteger ai = new AtomicInteger(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int nDecPix = ai.getAndIncrement(); nDecPix < num_pixels; nDecPix = ai.getAndIncrement()) { int x_dcm = nDecPix % width; int y_dcm = nDecPix / width; double sum_val = 0; int x0_full = x_dcm*decimate; int x1_full = Math.min((x_dcm + 1) * decimate, width_full); int y0_full = y_dcm*decimate; int y1_full = Math.min((y_dcm + 1) * decimate, height_full); int y_pdcm = y_dcm / decimate_step; int x_pdcm = x_dcm / decimate_step; int pix_prev = y_pdcm * fwidth_prev + x_pdcm; double d_prev = fdata_prev_filled[pix_prev]; int num_defined = (y1_full-y0_full) * (x1_full-x0_full); int num_defined1 = 0; int num_fixed = 0; // number of actually defined pixels (not filled in the previous steps for (int y_full = y0_full; y_full < y1_full; y_full++) { for (int x_full = x0_full; x_full < x1_full; x_full++) { int pix_full = y_full * width_full + x_full; double d = data_in[pix_full]; if (!Double.isNaN(d)) { sum_val += d; num_fixed ++; } else { sum_val += d_prev; } num_defined1++; } } if ((num_defined1 != num_defined) || (num_defined == 0)) { System.out.println("fillNaNs(multi) BUG: num_defined="+num_defined+", num_defined1="+num_defined1); } data[nDecPix] = sum_val/num_defined; data_nan[nDecPix] = (num_fixed > 0) ? data[nDecPix] : Double.NaN; // non-NaN may be any value, like 0.0; } } }; } ImageDtt.startAndJoin(threads); if (debugTitle != null) { dbg_bkp = data.clone(); } data_prev_filled = fillNaNs( data, // final double [] data, data_nan, // final double [] data_nan, // only modify tiles that are not fixed null, // final boolean [] prohibit, width, // int width, grow, // final int grow, diagonal_weight, // double diagonal_weight, // relative to ortho num_passes, // int num_passes, max_rchange, //final double max_rchange, // = 0.01 ImageDtt.THREADS_MAX, // final int threadsMax) // maximal number of threads to launch debugLevel); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations } if (debugTitle != null) { String [] dbg_titles = {"data","nan","filled"}; double [][] dbg_data = {dbg_bkp,data_nan, data_prev_filled}; ShowDoubleFloatArrays.showArrays( dbg_data, width, height, true, debugTitle+"-dcm"+decimate, dbg_titles); } width_prev = width; } return data_prev_filled; } /** /** * Fill NaN values in 2D array from neighbors using Laplacian==0 * Fill NaN values in 2D array from neighbors using Laplacian==0 * @param data data array (in line-scan order) with NaN values to be filled, * @param data data array (in line-scan order) with NaN values to be filled, * non-NaN values will not be modified. * non-NaN values will not be modified. * @param data_nan optional "original" data with NaN values to be replaced. If null, * @param data_nan optional "original" data with NaN values to be replaced. If null, * (single-pass) the data[] array will be used * (single-pass) the data[] array will be used * If non-null, will be used as a mask NaN/nonNaN and data - as initial values * @param prohibit_in optional (may be null) boolean array of the same size specifying * @param prohibit_in optional (may be null) boolean array of the same size specifying * prohibited pixels. * prohibited pixels. * @param width data width (height = data.length/width) * @param width data width (height = data.length/width) Loading @@ -8843,6 +9032,7 @@ ImageDtt.startAndJoin(threads); * @param num_passes maximal number of iterations. * @param num_passes maximal number of iterations. * @param max_rchange max relative (to data RMS) step change to exit iterations. * @param max_rchange max relative (to data RMS) step change to exit iterations. * @param threadsMax maximal number of concurrent threads to launch. * @param threadsMax maximal number of concurrent threads to launch. * @param debugLevel 0 - none, 1 - when done, 2 - all iterations * @return data array made of input data with replaced NaN limited by * @return data array made of input data with replaced NaN limited by * optional prohibit array and amount of growth. * optional prohibit array and amount of growth. */ */ Loading @@ -8855,7 +9045,8 @@ ImageDtt.startAndJoin(threads); double diagonal_weight, // relative to ortho double diagonal_weight, // relative to ortho int num_passes, int num_passes, final double max_rchange, // = 0.01 final double max_rchange, // = 0.01 final int threadsMax) // maximal number of threads to launch final int threadsMax, // maximal number of threads to launch final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations { { int height = data.length/width; int height = data.length/width; double wdiag = 0.25 *diagonal_weight / (diagonal_weight + 1.0); double wdiag = 0.25 *diagonal_weight / (diagonal_weight + 1.0); Loading Loading @@ -8984,6 +9175,9 @@ ImageDtt.startAndJoin(threads); s /= sw; s /= sw; data_io[1][nt] = s; data_io[1][nt] = s; last_change[ti] = Math.max(last_change[ti], Math.abs(data_io[1][nt]-data_io[0][nt])); last_change[ti] = Math.max(last_change[ti], Math.abs(data_io[1][nt]-data_io[0][nt])); if (Double.isNaN(last_change[ti] )) { System.out.println("fillNaNs():ti="+ti+",data_io[0]["+nt+"]="+data_io[0][nt]+",data_io[1]["+nt+"]="+data_io[1][nt]); } } } } } }; }; Loading @@ -8994,8 +9188,10 @@ ImageDtt.startAndJoin(threads); multi_change = Math.max(multi_change, last_change[i]); multi_change = Math.max(multi_change, last_change[i]); } } boolean done = (pass >= (num_passes - 1)) || (multi_change < max_change); boolean done = (pass >= (num_passes - 1)) || (multi_change < max_change); if (data_nan != null) { if ((debugLevel > 1) || ((debugLevel >0) && done)) { System.out.println("fillNaNs(): pass="+pass+" change="+multi_change+" done="+done); // if (data_nan != null) { System.out.println("fillNaNs(): "+(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime()))+ " pass="+pass+" change="+multi_change+" done="+done); } } if (done) { if (done) { break; break; Loading