package com.elphel.imagej.tileprocessor; /** ** ** ExtendSurfaces predict disparity in the unknown areas ** ** Copyright (C) 2017 Elphel, Inc. ** ** -----------------------------------------------------------------------------** ** ** ExtendSurfaces.java is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see <http://www.gnu.org/licenses/>. ** -----------------------------------------------------------------------------** ** */ import java.util.ArrayList; import java.util.concurrent.atomic.AtomicInteger; import com.elphel.imagej.common.PolynomialApproximation; import com.elphel.imagej.common.ShowDoubleFloatArrays; public class ExtendSurfaces { TileProcessor tp; public ExtendSurfaces(TileProcessor tp){ this.tp = tp; } public int smoothNew( // return maximal correction value // should first be initialized with all not known = Double.NaN final double [] values, // will be modified, Double.NaN is not yet assigned // final double [] strengths, // cell weights final boolean [] known, // cells with known values (will not be modified) final boolean [] new_cells, // cells that need to be calculated final int smpl_size, // == 5 final int min_points, // == 3 final boolean use_wnd, // use window function fro the neighbors final double tilt_cost, final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg final double same_range, // modify final double diff_continue, // maximal difference from the old value (for previously defined tiles final double max_abs_tilt, // = 2.0; // pix per tile final double max_rel_tilt, // = 0.2; // (pix / disparity) per tile final boolean en_normal, // expand sngle-range cells (that have all neighbors within split_threshold) final boolean en_far, // expand background - use neighbors cells within same_range from the lowest // en_near is only valid if !en_far final boolean en_near, // expand foreground - use neighbors cells within same_range from the highest final int max_tries, // maximal number of smoothing steps final double final_diff, // maximal change to finish iterations final boolean new_only, // expand only Double.NaN cells (not yet assigned), use for first passes final int dbg_x, final int dbg_y, final int debugLevel) { for (int nTile = 0; nTile < values.length; nTile++){ if (!known[nTile]) values [nTile] = Double.NaN; } for (int num_try = 0; num_try < max_tries; num_try ++){ double max_diff = smoothNewStep( // return maximal correction value // should first be initialized with all not known = Double.NaN values, // final double [] values, // will be modified, Double.NaN is not yet assigned new_cells, // final boolean [] new_cells, // cells that need to be calculated smpl_size, // final int smpl_size, // == 5 min_points, // final int min_points, // == 3 use_wnd, // final boolean use_wnd, // use window function fro the neighbors tilt_cost, // final double tilt_cost, split_threshold, // final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg same_range, // final double same_range, // modify diff_continue, // final double diff_continue, // maximal difference from the old value (for previously defined tiles max_abs_tilt, // final double max_abs_tilt, // = 2.0; // pix per tile max_rel_tilt, // final double max_rel_tilt, // = 0.2; // (pix / disparity) per tile en_normal, // final boolean en_normal, // expand sngle-range cells (that have all neighbors within split_threshold) en_far, // final boolean en_far, // expand background - use neighbors cells within same_range from the lowest // en_near is only valid if !en_far en_near, // final boolean en_near, // expand foreground - use neighbors cells within same_range from the highest new_only, // final boolean new_only, // expand only Double.NaN cells (not yet assigned), use for first passes true, // final boolean no_zero, // do not use values[i] == 0.0, exact 0.0 is only background dbg_x, // final int dbg_x, dbg_y, // final int dbg_y, debugLevel); // final int debugLevel); if (max_diff <= final_diff) break; } int num_new = 0; for (int nTile = 0; nTile < values.length; nTile++){ if (new_cells[nTile] && !Double.isNaN(values[nTile])) num_new++; } return num_new; } private int [] getNeibIndices( int size) { final int [] neib_indices = new int [8]; // indices of the sample array immediately around the center; int ni = 0; for (int sy = -1; sy <= 1; sy++) { for (int sx = -1; sx <= 1; sx++) { if ((sy != 0) || (sx != 0)){ neib_indices[ni++] = (size/2 + sx) + (size/2 + sy) * size; } } } return neib_indices; } private double smoothNewStep( // return maximal correction value // should first be initialized with all not known = Double.NaN final double [] values, // will be modified, Double.NaN is not yet assigned final boolean [] new_cells, // cells that need to be calculated final int smpl_size, // == 5 final int min_points, // == 3 final boolean use_wnd, // use window function for the neighbors final double tilt_cost, final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg final double same_range, // modify for old - +/- 0.5? final double diff_continue, // maximal difference from the old value (for previously defined tiles final double max_abs_tilt, // = 2.0; // pix per tile final double max_rel_tilt, // = 0.2; // (pix / disparity) per tile final boolean en_normal, // expand single-range cells (that have all neighbors within split_threshold) final boolean en_far, // expand background - use neighbors cells within same_range from the lowest // en_near is only valid if !en_far final boolean en_near, // expand foreground - use neighbors cells within same_range from the highest final boolean new_only, // expand only Double.NaN cells (not yet assigned), use for first passes final boolean no_zero, // do not use values[i] == 0.0, exact 0.0 is only background final int dbg_x, final int dbg_y, final int debugLevel) { final int tilesX = tp.getTilesX(); final int tilesY = tp.getTilesY(); final int smpl_half = smpl_size / 2; // 2 // probably should not be needed final double thresholdLin = 1.0E-20; // threshold ratio of matrix determinant to norm for linear approximation (det too low - fail) final double [] damping = {tilt_cost,tilt_cost,0.0}; // 0.0 will be applied to average value, tilt_cost - to both tilts final int center_index = smpl_half * (smpl_size + 1); // final int smpl_high = smpl_size - smpl_low; // 3 final int smpl_len = smpl_size * smpl_size; final int dbg_tile = dbg_x + tilesX * dbg_y; final double [] smpl_weights = MeasuredLayers.getSampleWindow(smpl_size, !use_wnd); final Thread[] threads = ImageDtt.newThreadArray(tp.threadsMax); final double [] max_corrs = new double [threads.length]; final AtomicInteger ai_thread = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0); final double [] new_vals = values.clone(); final int [] neib_indices = getNeibIndices(smpl_size); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { PolynomialApproximation pa = new PolynomialApproximation(); int this_thread = ai_thread.getAndIncrement(); for (int nTile = ai.getAndIncrement(); nTile < new_vals.length; nTile = ai.getAndIncrement()) { if (new_cells[nTile] && (!new_only || Double.isNaN(values[nTile]))) { int dl = (nTile == dbg_tile) ? debugLevel : -1; int tileX = nTile % tilesX; int tileY = nTile / tilesX; // boolean [] smpl_new = new boolean [smpl_len]; boolean [] smpl_sel = new boolean [smpl_len]; double [] smpl_d = new double [smpl_len]; // double [] smpl_p = new double [smpl_len]; // double [] smpl_w = new double [smpl_len]; int num_in_sample = 0; for (int sy = 0; sy < smpl_size; sy++) { int y = tileY + sy - smpl_half; if ((y >= 0) && (y < tilesY)) { for (int sx = 0; sx < smpl_size; sx++) { int x = tileX + sx - smpl_half; if ((x >= 0) && (x < tilesX)) { int indx = x + y * tilesX; // if (!Double.isNaN(values[indx]) && (indx != center_index)){ if (!Double.isNaN(values[indx]) && (!no_zero || (values[indx] != 0.0))){ int indxs = sx + sy * smpl_size; // double w = smpl_weights[indxs]; smpl_sel[indxs] = true; smpl_d[indxs] = values[indx]; num_in_sample++; } } } } } if (dl > 1){ System.out.println("smoothNewStep(): tileX="+tileX+", tileY="+tileY+", nTile="+nTile+" num_in_sample="+num_in_sample); for (int sy = 0; sy < smpl_size; sy++) { int y = tileY + sy - smpl_half; if ((y >= 0) && (y < tilesY)) { for (int sx = 0; sx < smpl_size; sx++) { int x = tileX + sx - smpl_half; if ((x >= 0) && (x < tilesX)) { int indx = x + y * tilesX; if (!Double.isNaN(values[indx])){ int indxs = sx + sy * smpl_size; System.out.print(String.format("%8.3f ", smpl_d[indxs])); } else { System.out.print(String.format("%8s ", "--NaN--")); } } } } System.out.println(); } } if (num_in_sample >= min_points) { // if center was NaN - diff is the absolute value. // Two branches - for existing and new cells. // New cells may stick to the far/near, already defined - only to similar, // otherwise they can all switch from some distant cell during many iteration steps boolean process_sample = false; if (smpl_sel[center_index]) { // Keep only cells within +/- diff_continue from the center value for (int indxs = 0; indxs < smpl_len; indxs ++ ) if (smpl_sel[indxs]){ if (Math.abs(smpl_d[indxs] - smpl_d[center_index]) > diff_continue){ smpl_sel[indxs] = false; num_in_sample--; } } process_sample = (num_in_sample > 1); } else { // add starting from the known cells. When using 5x5 samples, having immediate neighbor // to the center usually means that likely there is enough data to determine the tilt. boolean has_neib = false; for (int i = 0; i < neib_indices.length; i++) if (smpl_sel[neib_indices[i]]) { has_neib = true; break; } // process_sample = false; if (has_neib) { // all conditions met, find linear 2-d damped approximation for the center int imin = -1, imax = -1; for (int indxs = 0; indxs < smpl_len; indxs ++ ) if (smpl_sel[indxs]){ if ((imin < 0) || (smpl_d[indxs] < smpl_d[imin])) imin = indxs ; if ((imax < 0) || (smpl_d[indxs] > smpl_d[imax])) imax = indxs ; } // does it all fit if ((smpl_d[imax] - smpl_d[imin]) <= split_threshold){ process_sample = en_normal; } else { if (en_far) { double threshold = smpl_d[imin] + same_range; for (int indxs = 0; indxs < smpl_len; indxs ++ ) if (smpl_sel[indxs]){ if (smpl_d[indxs] > threshold) { smpl_sel[indxs] = false; num_in_sample--; } } process_sample = true; } else if (en_near){ double threshold = smpl_d[imax] - same_range; for (int indxs = 0; indxs < smpl_len; indxs ++ ) if (smpl_sel[indxs]){ if (smpl_d[indxs] < threshold) { smpl_sel[indxs] = false; num_in_sample--; } } process_sample = true; } // removed some points - recheck neighbors if (process_sample){ has_neib = false; for (int i = 0; i < neib_indices.length; i++) if (smpl_sel[neib_indices[i]]) { has_neib = true; break; } if (!has_neib) process_sample = false; // neighbor was removed, will process if (dl > 1){ System.out.println("smoothNewStep(): tileX="+tileX+", tileY="+tileY+", nTile="+nTile+ " num_in_sample="+num_in_sample+" has_neib="+has_neib+ " process_sample="+process_sample); } // with other direction } } } } if (dl > 1){ System.out.println("smoothNewStep(): tileX="+tileX+", tileY="+tileY+", nTile="+nTile+ " num_in_sample="+num_in_sample+" process_sample="+process_sample); } if (num_in_sample < min_points) { process_sample = false; } if (process_sample) { // build linear 2d approximation, damped as there could be co-linear cells // or even a single cell double sw = 0.0; double [][][] mdata = new double [num_in_sample][3][]; int mindx = 0; for (int sy = 0; sy < smpl_size; sy++){ for (int sx = 0; sx < smpl_size; sx++){ int indxs = sy * smpl_size + sx; if (smpl_sel[indxs]) { mdata[mindx][0] = new double [2]; mdata[mindx][0][0] = sx - smpl_half; // should match integer center mdata[mindx][0][1] = sy - smpl_half; mdata[mindx][1] = new double [1]; mdata[mindx][1][0] = smpl_d[indxs]; mdata[mindx][2] = new double [1]; mdata[mindx][2][0] = smpl_weights[indxs]; if (mdata[mindx][1][0] == 0.0){ System.out.println("zero!!!"); } mindx ++; } } } double[][] approx2d = pa.quadraticApproximation( mdata, true, // boolean forceLinear, // use linear approximation damping, // double [] damping, thresholdLin, // threshold ratio of matrix determinant to norm for linear approximation (det too low - fail) 0.0, // threshold ratio of matrix determinant to norm for quadratic approximation (det too low - fail) dl-1); // int debugLevel; if (approx2d == null) { System.out.println("A BUG in smoothNewStep() - failed quadraticApproximation()"); continue; } double tilt2 = approx2d[0][0]*approx2d[0][0] + approx2d[0][1]*approx2d[0][1]; if (dl > 1){ System.out.println("smoothNewStep(): tileX="+tileX+" coeffs: D="+ approx2d[0][0]+" E="+approx2d[0][1]+" F="+approx2d[0][2]+ ", tilt = "+Math.sqrt(tilt2)); } double max_tilt = Math.min(max_abs_tilt, max_rel_tilt * approx2d[0][2]); if (tilt2 > (max_tilt * max_tilt)){ continue; } double new_center_val = approx2d[0][2]; // Last coefficient, F (of 6) double this_corr; if (Double.isNaN(values[nTile])) this_corr = Math.abs(new_center_val); else this_corr = Math.abs(new_center_val - values[nTile]); new_vals[nTile] = new_center_val; max_corrs[this_thread] = Math.max(max_corrs[this_thread], this_corr); } } } } } }; } ImageDtt.startAndJoin(threads); System.arraycopy(new_vals, 0, values, 0, new_vals.length); double max_corr = 0; for (int i = 0; i < max_corrs.length; i++) max_corr = Math.max(max_corr,max_corrs[i]); return max_corr; } private boolean [] startDiscontinuity( final double [] values, // will be modified, Double.NaN is not yet assigned final boolean [] known, // cells with new values (will be modified) final int smpl_size, // == 5 final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg final boolean extend_far, // extend far (false - extend near) final boolean no_zero, // do not use values[i] == 0.0, exact 0.0 is only background final int dbg_x, final int dbg_y, final int debugLevel) { final int tilesX = tp.getTilesX(); final int tilesY = tp.getTilesY(); final int smpl_half = smpl_size / 2; // 2 final boolean [] discont_cells = new boolean [tilesX * tilesY]; final Thread[] threads = ImageDtt.newThreadArray(tp.threadsMax); final int [] num_new = new int [threads.length]; final AtomicInteger ai_thread = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0); final int dbg_tile = dbg_x + tilesX * dbg_y; for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int this_thread = ai_thread.getAndIncrement(); for (int nTile = ai.getAndIncrement(); nTile < known.length; nTile = ai.getAndIncrement()) if (known[nTile]){ double threshold = extend_far ? (values[nTile] - split_threshold): (values[nTile] + split_threshold); int dl = (nTile == dbg_tile) ? debugLevel : -1; // int dl = (nTile == dbg_tile) ? debugLevel : -1; int tileX = nTile % tilesX; int tileY = nTile / tilesX; label_tile: { for (int sy = 0; sy < smpl_size; sy++) { int y = tileY + sy - smpl_half; if ((y >= 0) && (y < tilesY)) { for (int sx = 0; sx < smpl_size; sx++) { int x = tileX + sx - smpl_half; if ((x >= 0) && (x < tilesX)) { int indx = x + y * tilesX; if (known[indx] && (!no_zero || (values[indx] != 0.0))) { if ( (extend_far && (values[indx] < threshold)) || (!extend_far && (values[indx] > threshold))){ discont_cells[nTile] = true; num_new[this_thread] ++; break label_tile; } } } } } } } } } }; } ImageDtt.startAndJoin(threads); ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int this_thread = ai_thread.getAndIncrement(); for (int nTile = ai.getAndIncrement(); nTile < known.length; nTile = ai.getAndIncrement()){ if (discont_cells[nTile]){ // values[nTile] = Double.NaN; known[nTile] = false; } if (!known[nTile]){ values[nTile] = Double.NaN; } } } }; } ImageDtt.startAndJoin(threads); for (int i = 0; i < num_new.length; i++) if (num_new[i] > 0){ return discont_cells; } return null; // nothing found } private boolean [] startExpanding( final double [] values, // will be modified, Double.NaN is not yet assigned final boolean [] known, // cells with new values (will not be modified) final int smpl_size, // == 5 final boolean no_zero, // do not use values[i] == 0.0, exact 0.0 is only background final int dbg_x, final int dbg_y, final int debugLevel) { final int tilesX = tp.getTilesX(); final int tilesY = tp.getTilesY(); final boolean [] expanding = new boolean [tilesX * tilesY]; final Thread[] threads = ImageDtt.newThreadArray(tp.threadsMax); final int [] num_new = new int [threads.length]; final AtomicInteger ai_thread = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0); final int dbg_tile = dbg_x + tilesX * dbg_y; final TileNeibs tnSurface = new TileNeibs(tilesX, tilesY); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int this_thread = ai_thread.getAndIncrement(); for (int nTile = ai.getAndIncrement(); nTile < known.length; nTile = ai.getAndIncrement()) if (!known[nTile]){ int dl = (nTile == dbg_tile) ? debugLevel : -1; boolean has_exp_neib = false; for (int dir = 0; dir <8; dir++){ int nTile1 = tnSurface.getNeibIndex(nTile, dir); if ((nTile1 >= 0) && known[nTile1] && !Double.isNaN(values[nTile1]) && (!no_zero || (values[nTile1] != 0.0))){ has_exp_neib = true; break; } } if (has_exp_neib) { expanding[nTile] = true; num_new[this_thread] ++; } } } }; } ImageDtt.startAndJoin(threads); ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int nTile = ai.getAndIncrement(); nTile < known.length; nTile = ai.getAndIncrement()){ if (expanding[nTile] || !known[nTile]){ values[nTile] = Double.NaN; } } } }; } ImageDtt.startAndJoin(threads); if (debugLevel > 2){ String [] titles = {"values","known", "expanding"}; double [][] dbg_img = new double [titles.length][]; dbg_img[0] = values; dbg_img[1] = new double [tilesX*tilesY]; dbg_img[2] = new double [tilesX*tilesY]; for (int i = 0; i < dbg_img[1].length; i++){ dbg_img[1][i] = known[i] ? 50.0: 0.0; dbg_img[2][i] = expanding[i] ? 50.0: 0.0; } ShowDoubleFloatArrays.showArrays(dbg_img, tilesX, tilesY, true, "startExpanding",titles); } for (int i = 0; i < num_new.length; i++) if (num_new[i] > 0){ return expanding; } return null; // nothing found } private int expandDiscontinuityStep( final double [] values, // will be modified, Double.NaN is not yet assigned final boolean [] known, // cells with known values (will be modified) final boolean [] prohibited, // cells that can not be used (tried before with similar disparity) final boolean [] expanding, // cells with new values (will be modified) final int smpl_size, // == 5 final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg final boolean extend_far, // extend far (false - extend near) final boolean unknown_only, // pure expanding, not over previously found values final int dbg_x, final int dbg_y, final int debugLevel) { final int tilesX = tp.getTilesX(); final int tilesY = tp.getTilesY(); final int smpl_half = smpl_size / 2; // 2 final boolean [] expanding_prev = expanding.clone(); final Thread[] threads = ImageDtt.newThreadArray(tp.threadsMax); final int [] num_new = new int [threads.length]; final AtomicInteger ai_thread = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0); final int dbg_tile = dbg_x + tilesX * dbg_y; final TileNeibs tnSurface = new TileNeibs(tilesX, tilesY); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int this_thread = ai_thread.getAndIncrement(); for (int nTile = ai.getAndIncrement(); nTile < known.length; nTile = ai.getAndIncrement()){ if (!expanding_prev[nTile] && ((prohibited == null) || !prohibited[nTile])) { int dl = (nTile == dbg_tile) ? debugLevel : -1; boolean has_exp_neib = false; for (int dir = 0; dir <8; dir++){ int nTile1 = tnSurface.getNeibIndex(nTile, dir); if ((nTile1 >= 0) && expanding_prev[nTile1] && !Double.isNaN(values[nTile1])){ has_exp_neib = true; break; } } if (has_exp_neib) { if (!known[nTile]){ expanding[nTile] = true; num_new[this_thread] ++; } else if (!unknown_only){ double threshold = extend_far ? (values[nTile] - split_threshold): (values[nTile] + split_threshold); int tileX = nTile % tilesX; int tileY = nTile / tilesX; label_tile: { for (int sy = 0; sy < smpl_size; sy++) { int y = tileY + sy - smpl_half; if ((y >= 0) && (y < tilesY)) { for (int sx = 0; sx < smpl_size; sx++) { int x = tileX + sx - smpl_half; if ((x >= 0) && (x < tilesX)) { int indx = x + y * tilesX; if ((known[indx] || (expanding_prev[indx]) && !Double.isNaN(values[indx]))) { if ( (extend_far && (values[indx] < threshold)) || (!extend_far && (values[indx] > threshold))){ expanding[nTile] = true; num_new[this_thread] ++; break label_tile; } } } } } } } } } } } } }; } ImageDtt.startAndJoin(threads); ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { // int this_thread = ai_thread.getAndIncrement(); for (int nTile = ai.getAndIncrement(); nTile < known.length; nTile = ai.getAndIncrement()){ if (expanding[nTile] && !expanding_prev[nTile]){ values[nTile] = Double.NaN; known[nTile] = false; } } } }; } ImageDtt.startAndJoin(threads); int total_new = 0; for (int i = 0; i < num_new.length; i++){ total_new +=num_new[i]; } return total_new; } public boolean [] expandDiscontinuity( // return maximal correction value final ArrayList <CLTPass3d> passes, final int firstPass, final int lastPassPlus1, final double [] values, // will be modified, Double.NaN is not yet assigned final boolean [] known, // cells with known values (will not be modified) final int num_steps, // how far to extend final int smpl_size, // == 5 final int min_points, // == 3 final boolean use_wnd, // use window function for the neighbors final double tilt_cost, final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg final double same_range, // modify final double diff_continue, // maximal difference from the old value (for previously defined tiles final double max_abs_tilt, // = 2.0; // pix per tile final double max_rel_tilt, // = 0.2; // (pix / disparity) per tile final boolean extend_far, // extend far (false - extend near) final int max_tries, // maximal number of smoothing steps final double final_diff, // maximal change to finish iterations final double grow_disp_min, final double grow_disp_max, final double grow_disp_step, final double unique_pre_tolerance, // usually larger than clt_parameters.unique_tolerance final boolean try_next, // try next disparity range if the current one was already tried final int dbg_x, final int dbg_y, final int debugLevel) { boolean [] expanding = startDiscontinuity( values, // final double [] values, // will be modified, Double.NaN is not yet assigned known, // final boolean [] known, // cells with known values (will not be modified) smpl_size, // final int smpl_size, // == 5 split_threshold, // final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg extend_far, // final boolean extend_far, // extend far (false - extend near) true, // final boolean no_zero, // do not use values[i] == 0.0, exact 0.0 is only background dbg_x, // final int dbg_x, dbg_y, // final int dbg_y, debugLevel); // final int debugLevel) if (expanding == null){ return null; // no discontinuity seeds } boolean [] prohibited = tp.getTriedBefore( passes, // final ArrayList <CLTPass3d> passes, firstPass, // final int firstPass, lastPassPlus1, // final int lastPassPlus1, expanding, // final boolean [] selected, null, // final boolean [] prohibited, values, // final double [] disparity, true, // final boolean mod_selected, true, // final boolean mod_disparity, false, // final boolean en_near, false, // final boolean en_far, grow_disp_min, // final double grow_disp_min, grow_disp_max, // final double grow_disp_max, grow_disp_step, // final double grow_disp_step, try_next ? 0.0: unique_pre_tolerance); // final double unique_pre_tolerance) // disable for try_next for (int nstep = 0; nstep < num_steps; nstep++){ int num_new_cells = 0; if (nstep > 0){ num_new_cells = expandDiscontinuityStep( values, // final double [] values, // will be modified, Double.NaN is not yet assigned known, // final boolean [] known, // cells with known values (will not be modified) prohibited, // final boolean [] prohibited, // cells that can not be used (tried before with similar disparity) expanding, // final boolean [] expanding, // cells with known values (will not be modified) smpl_size, //final int smpl_size, // == 5 split_threshold, // final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg extend_far, // final boolean extend_far, // extend far (false - extend near) false, // inal boolean unknown_only, // pure expanding, not over previously found values dbg_x, // final int dbg_x, dbg_y, // final int dbg_y, debugLevel); // final int debugLevel) tp.getTriedBefore( passes, // final ArrayList <CLTPass3d> passes, firstPass, // final int firstPass, lastPassPlus1, // final int lastPassPlus1, expanding, // final boolean [] selected, prohibited, // final boolean [] prohibited, values, // final double [] disparity, true, // final boolean mod_selected, true, // final boolean mod_disparity, false, // final boolean en_near, false, // final boolean en_far, grow_disp_min, // final double grow_disp_min, grow_disp_max, // final double grow_disp_max, grow_disp_step, // final double grow_disp_step, try_next ? 0.0: unique_pre_tolerance); // final double unique_pre_tolerance) // disable for try_next } int mt = 2 * (nstep + 1); // max_tries; // or use k * nstep ??? // increase tries last iteration? if (((num_new_cells == 0) && (nstep > 0)) || (nstep == (num_steps -1))) { mt = max_tries; // last time smooth more } for (int num_try = 0; num_try < mt; num_try ++){ if (debugLevel > 1){ System.out.print("expandDiscontinuity(): nstep="+nstep+" num_try="+num_try+" "); if (num_try == (mt - 1)){ System.out.print("expandDiscontinuity(): LAST try "); } } double max_diff = smoothNewStep( // return maximal correction value // should first be initialized with all not known = Double.NaN values, // final double [] values, // will be modified, Double.NaN is not yet assigned expanding, // final boolean [] new_cells, // cells that need to be calculated smpl_size, // final int smpl_size, // == 5 min_points, // final int min_points, // == 3 use_wnd, // final boolean use_wnd, // use window function fro the neighbors tilt_cost, // final double tilt_cost, split_threshold, // final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg same_range, // final double same_range, // modify diff_continue, // final double diff_continue, // maximal difference from the old value (for previously defined tiles max_abs_tilt, // final double max_abs_tilt, // = 2.0; // pix per tile max_rel_tilt, // final double max_rel_tilt, // = 0.2; // (pix / disparity) per tile true, // final boolean en_normal, // expand sngle-range cells (that have all neighbors within split_threshold) extend_far, // final boolean en_far, // expand background - use neighbors cells within same_range from the lowest // en_near is only valid if !en_far !extend_far, // final boolean en_near, // expand foreground - use neighbors cells within same_range from the highest (num_try == 0), // new_only, // first run - set new cells, later - smooth all true, // final boolean no_zero, // do not use values[i] == 0.0, exact 0.0 is only background dbg_x, // final int dbg_x, dbg_y, // final int dbg_y, debugLevel); // final int debugLevel); if (debugLevel > 1){ System.out.println("expandDiscontinuity() -> max_diff="+max_diff); } if (max_diff <= final_diff) break; } if (debugLevel > 1){ System.out.println("expandDiscontinuity(): nstep="+nstep+" mt="+mt); } } if (try_next){ tp.getTriedBefore( passes, // final ArrayList <CLTPass3d> passes, firstPass, // final int firstPass, lastPassPlus1, // final int lastPassPlus1, expanding, // final boolean [] selected, prohibited, // final boolean [] prohibited, values, // final double [] disparity, true, // final boolean mod_selected, true, // final boolean mod_disparity, // TODO: some version to enable both en_near and en_far? or make en_far assume en_near and make it first? !extend_far, // final boolean en_near, extend_far, // final boolean en_far, grow_disp_min, // final double grow_disp_min, grow_disp_max, // final double grow_disp_max, grow_disp_step, // final double grow_disp_step, unique_pre_tolerance); // final double unique_pre_tolerance) } return expanding; } public boolean[] expandKnown( // return maximal correction value // should first be initialized with all not known = Double.NaN final ArrayList <CLTPass3d> passes, final int firstPass, final int lastPassPlus1, final double [] values, // will be modified, Double.NaN is not yet assigned final boolean [] known, // cells with known values (will not be modified) final int num_steps, // how far to extend final int smpl_size, // == 5 final int min_points, // == 3 final boolean use_wnd, // use window function fro the neighbors final double tilt_cost, final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg final double same_range, // modify final double diff_continue, // maximal difference from the old value (for previously defined tiles final double max_abs_tilt, // = 2.0; // pix per tile final double max_rel_tilt, // = 0.2; // (pix / disparity) per tile final boolean smooth_only, // Do not expand ambiguous cells (with discontinuity) final boolean extend_far, // extend far (false - extend near) final int max_tries, // maximal number of smoothing steps final double final_diff, // maximal change to finish iterations final double grow_disp_min, final double grow_disp_max, final double grow_disp_step, final double unique_pre_tolerance, // usually larger than clt_parameters.unique_tolerance final boolean try_next, // try next disparity range if the current one was already tried final int dbg_x, final int dbg_y, final int debugLevel) { boolean [] expanding = startExpanding( values, // final double [] values, // will be modified, Double.NaN is not yet assigned known, // final boolean [] known, // cells with known values (will not be modified) smpl_size, // final int smpl_size, // == 5 true, // final boolean no_zero, // do not use values[i] == 0.0, exact 0.0 is only background dbg_x, // final int dbg_x, dbg_y, // final int dbg_y, debugLevel+0); // final int debugLevel) // +2 for image if (expanding == null){ return null; // no discontinuity seeds } boolean [] prohibited = tp.getTriedBefore( passes, // final ArrayList <CLTPass3d> passes, firstPass, // final int firstPass, lastPassPlus1, // final int lastPassPlus1, expanding, // final boolean [] selected, null, // final boolean [] prohibited, values, // final double [] disparity, true, // final boolean mod_selected, true, // final boolean mod_disparity, false, // final boolean en_near, false, // final boolean en_far, grow_disp_min, // final double grow_disp_min, grow_disp_max, // final double grow_disp_max, grow_disp_step, // final double grow_disp_step, try_next ? 0.0: unique_pre_tolerance); // final double unique_pre_tolerance) // disable for try_next for (int nstep = 0; nstep < num_steps; nstep++){ int num_new_cells = 0; if (nstep > 0){ num_new_cells = expandDiscontinuityStep( values, // final double [] values, // will be modified, Double.NaN is not yet assigned known, // final boolean [] known, // cells with known values (will not be modified) prohibited, // final boolean [] prohibited, // cells that can not be used (tried before with similar disparity) expanding, // final boolean [] expanding, // cells with known values (will not be modified) smpl_size, //final int smpl_size, // == 5 split_threshold, // final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg extend_far, // final boolean extend_far, // extend far (false - extend near) true, // final boolean unknown_only, // pure expanding, not over previously found values dbg_x, // final int dbg_x, dbg_y, // final int dbg_y, debugLevel); // final int debugLevel) tp.getTriedBefore( passes, // final ArrayList <CLTPass3d> passes, firstPass, // final int firstPass, lastPassPlus1, // final int lastPassPlus1, expanding, // final boolean [] selected, prohibited, // final boolean [] prohibited, values, // final double [] disparity, true, // final boolean mod_selected, true, // final boolean mod_disparity, false, // final boolean en_near, false, // final boolean en_far, grow_disp_min, // final double grow_disp_min, grow_disp_max, // final double grow_disp_max, grow_disp_step, // final double grow_disp_step, try_next ? 0.0: unique_pre_tolerance); // final double unique_pre_tolerance) // disable for try_next } int mt = 2 * (nstep + 1); // max_tries; // or use k * nstep ??? // increase tries last iteration? if (((num_new_cells == 0) && (nstep > 0)) || (nstep == (num_steps -1))) { mt = max_tries; // last time smooth more } for (int num_try = 0; num_try < mt; num_try ++){ if (debugLevel >1){ System.out.print("expandKnown(): nstep="+nstep+" num_try="+num_try+" "); if (num_try == (mt - 1)){ System.out.print("expandKnown(): LAST try "); } } double max_diff = smoothNewStep( // return maximal correction value // should first be initialized with all not known = Double.NaN values, // final double [] values, // will be modified, Double.NaN is not yet assigned expanding, // final boolean [] new_cells, // cells that need to be calculated smpl_size, // final int smpl_size, // == 5 min_points, // final int min_points, // == 3 use_wnd, // final boolean use_wnd, // use window function fro the neighbors tilt_cost, // final double tilt_cost, split_threshold, // final double split_threshold, // if full range of the values around the cell higher, need separate fg, bg same_range, // final double same_range, // modify diff_continue, // final double diff_continue, // maximal difference from the old value (for previously defined tiles max_abs_tilt, // final double max_abs_tilt, // = 2.0; // pix per tile max_rel_tilt, // final double max_rel_tilt, // = 0.2; // (pix / disparity) per tile true, // final boolean en_normal, // expand sngle-range cells (that have all neighbors within split_threshold) !smooth_only && extend_far, // final boolean en_far, // expand background - use neighbors cells within same_range from the lowest // en_near is only valid if !en_far !smooth_only && !extend_far, // final boolean en_near, // expand foreground - use neighbors cells within same_range from the highest (num_try == 0), // new_only, // first run - set new cells, later - smooth all true, // final boolean no_zero, // do not use values[i] == 0.0, exact 0.0 is only background dbg_x, // final int dbg_x, dbg_y, // final int dbg_y, debugLevel); // final int debugLevel); if (debugLevel > 1){ System.out.println("expandKnown() -> max_diff="+max_diff); } if (max_diff <= final_diff) break; } if (debugLevel > 1){ System.out.println("expandKnown(): nstep="+nstep+" mt="+mt); } } if (try_next){ tp.getTriedBefore( passes, // final ArrayList <CLTPass3d> passes, firstPass, // final int firstPass, lastPassPlus1, // final int lastPassPlus1, expanding, // final boolean [] selected, prohibited, // final boolean [] prohibited, values, // final double [] disparity, true, // final boolean mod_selected, true, // final boolean mod_disparity, // TODO: some version to enable both en_near and en_far? or make en_far assume en_near and make it first? !extend_far, // final boolean en_near, extend_far, // final boolean en_far, grow_disp_min, // final double grow_disp_min, grow_disp_max, // final double grow_disp_max, grow_disp_step, // final double grow_disp_step, unique_pre_tolerance); // final double unique_pre_tolerance) } return expanding; } }