Loading src/main/java/com/elphel/imagej/tileprocessor/TexturedModel.java +343 −75 Original line number Original line Diff line number Diff line Loading @@ -4717,6 +4717,7 @@ public class TexturedModel { if ( tile_keep[fnslice][tile] && if ( tile_keep[fnslice][tile] && !tile_fg_strong[fnslice][tile] && !tile_fg_strong[fnslice][tile] && !tile_stitch[fnslice][tile]) { // *** !tile_stitch[fnslice][tile]) { // *** double [][] offs_bg = channel_pixel_offsets[fnslice][tile]; double [][] offs_bg = channel_pixel_offsets[fnslice][tile]; for (int ns = 0; ns < num_slices; ns++) { for (int ns = 0; ns < num_slices; ns++) { if ((ns != fnslice) && if ((ns != fnslice) && Loading Loading @@ -4847,7 +4848,8 @@ public class TexturedModel { public void run() { public void run() { for (int tile = ai.getAndIncrement(); tile < tiles; tile = ai.getAndIncrement()) { for (int tile = ai.getAndIncrement(); tile < tiles; tile = ai.getAndIncrement()) { int tileY = tile / tilesX; int tileY = tile / tilesX; int indx = tileY * transform_size * width; int tileX = tile % tilesX; int indx = (tileY * width + tileX) * transform_size; search_pix: search_pix: for (int dy = 0; dy < transform_size; dy++) { for (int dy = 0; dy < transform_size; dy++) { for (int dx = 0; dx < transform_size; dx++) { for (int dx = 0; dx < transform_size; dx++) { Loading @@ -4872,8 +4874,10 @@ public class TexturedModel { final double [][][][] channel_pixel_offsets, final double [][][][] channel_pixel_offsets, final double [][] textures, final double [][] textures, final boolean [][] alpha_pix, // will be updated final boolean [][] alpha_pix, // will be updated final double [][] combo_texture, // final double [][] combo_texture, final double [][][] sensor_texture, final double [][][] sensor_texture, final int [][] occluded_map, // bitmap of blocked by FG sensors final int min_sensors, // minimal number of sensors visible from the FG pixel final double [][] slice_disparities, final double [][] slice_disparities, final boolean [][] tile_keep, // tiles that have at least one pixel final boolean [][] tile_keep, // tiles that have at least one pixel final boolean [][] tile_stitch, // tiles that have at least one pixel final boolean [][] tile_stitch, // tiles that have at least one pixel Loading @@ -4885,9 +4889,17 @@ public class TexturedModel { final boolean en_patch, // enable change FG pixel to opaque from transparent final boolean en_patch, // enable change FG pixel to opaque from transparent final double min_disp_diff, // do not consider obscuring too close BG (1 pix or more?) final double min_disp_diff, // do not consider obscuring too close BG (1 pix or more?) // other parameters // other parameters final double [][] debug_cost, // if not null, should be double [nslices][] - will return costs/NaN final double weight_neib, // weight of same neighbors final double weight_bg, // weight of BG cost relative to the FG one // final double weight_bg2, // fraction of BG variance cost (1-weight_bg2) - the BG true one final double best_dir_frac, // for BG - use this fraction of all sensors in the best direction final double cost_min, // minimal absolute value of the total cost to make changes // debug arrays final double [][][] debug_costs, // if not null, should be double [nslices][] - will return costs/NaN final int [][] debug_stats, // if not null, should be int [nslices][] - will return number of added/removed per slice final int width, final int width, final int transform_size){ final int transform_size){ final int min_sensors_bg = min_sensors; // maybe reduce? *=best_dir_frac? final int num_slices = alpha_pix.length; final int num_slices = alpha_pix.length; final int img_size = alpha_pix[0].length; final int img_size = alpha_pix[0].length; final int height = img_size/width; final int height = img_size/width; Loading @@ -4900,24 +4912,40 @@ public class TexturedModel { final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger aplus = new AtomicInteger(0); // number of added opaque pixels final AtomicInteger aplus = new AtomicInteger(0); // number of added opaque pixels final AtomicInteger aminus = new AtomicInteger(0); // number of removed opaque pixels final AtomicInteger aminus = new AtomicInteger(0); // number of removed opaque pixels final TileNeibs pn = new TileNeibs(width,height); final boolean [] new_alpha = new boolean[img_size]; int num_modified_pixels = 0; final int dbg_pix = 168170; final boolean [][] new_alpha = new boolean[num_slices][img_size]; for (int nslice = 0; nslice < num_slices; nslice++) { for (int nslice = 0; nslice < num_slices; nslice++) { int fnslice = nslice; int fnslice = nslice; System.arraycopy(alpha_pix[fnslice], 0, new_alpha, 0, img_size); System.arraycopy(alpha_pix[fnslice], 0, new_alpha[fnslice], 0, img_size); if (debug_costs != null) { debug_costs[fnslice] = new double [3][img_size]; // {cost, cost_fg, cost_bg} for (int i = 0; i < debug_costs[fnslice].length; i++) { Arrays.fill(debug_costs[fnslice][i], Double.NaN); } } ai.set(0); ai.set(0); aplus.set(0); aplus.set(0); aminus.set(0); aminus.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { threads[ithread] = new Thread() { public void run() { public void run() { double [][][] bg_value = new double [transform_size][transform_size][]; double [][][] bg_disparity = new double [transform_size][transform_size][]; for (int tile = ai.getAndIncrement(); tile < tiles; tile = ai.getAndIncrement()) { for (int tile = ai.getAndIncrement(); tile < tiles; tile = ai.getAndIncrement()) { if ((fnslice == dbg_slice) && (tile == dbg_tile )) { if ((fnslice == dbg_slice) && (tile == dbg_tile )) { System.out.println("updateFgAlpha().1 nslice="+fnslice+", tile="+tile); System.out.println("updateFgAlpha().1 nslice="+fnslice+", tile="+tile); } } if ( trim_tiles [fnslice][tile] && if ( trim_tiles [fnslice][tile] && !tile_stitch[fnslice][tile]) { !tile_stitch[fnslice][tile]) { int tileX = tile % tilesX; int tileY = tile / tilesX; int pix0 = (tileY * width + tileX) * transform_size; double [][] offs_fg = channel_pixel_offsets[fnslice][tile]; double [][] offs_fg = channel_pixel_offsets[fnslice][tile]; int num_sens = offs_fg.length; int best_dir_number = (int) Math.round (best_dir_frac * num_sens); boolean valid_bg = false; for (int ns = 0; ns < num_slices; ns++) { for (int ns = 0; ns < num_slices; ns++) { if ((ns != fnslice) && if ((ns != fnslice) && tile_keep[ns][tile] && tile_keep[ns][tile] && Loading @@ -4925,22 +4953,23 @@ public class TexturedModel { (slice_disparities[ns][tile] < slice_disparities[fnslice][tile]) && (slice_disparities[ns][tile] < slice_disparities[fnslice][tile]) && ((slice_disparities[fnslice][tile] - slice_disparities[ns][tile]) > min_disp_diff )) { ((slice_disparities[fnslice][tile] - slice_disparities[ns][tile]) > min_disp_diff )) { double [][] offs_bg = channel_pixel_offsets[ns][tile]; double [][] offs_bg = channel_pixel_offsets[ns][tile]; double [][] pixel_offs = new double [offs_bg.length][2]; double [][] pixel_offs = new double [num_sens][2]; for (int nsens = 0; nsens < pixel_offs.length; nsens++) { for (int nsens = 0; nsens < num_sens; nsens++) { if (offs_bg[nsens] != null) { // to implement sensor mask later if (offs_bg[nsens] != null) { // to implement sensor mask later pixel_offs[nsens][0] = offs_fg[nsens][0] - offs_bg[nsens][0]; pixel_offs[nsens][0] = offs_fg[nsens][0] - offs_bg[nsens][0]; pixel_offs[nsens][1] = offs_fg[nsens][1] - offs_bg[nsens][1]; pixel_offs[nsens][1] = offs_fg[nsens][1] - offs_bg[nsens][1]; } } } } int tileX = tile % tilesX; int tileY = tile / tilesX; int pix0 = (tileY * width + tileX) * transform_size; for (int dy = 0; dy < transform_size; dy++) { for (int dy = 0; dy < transform_size; dy++) { int py0 = tileY * transform_size + dy; int py0 = tileY * transform_size + dy; int pix1 = pix0 + dy * width; int pix1 = pix0 + dy * width; for (int dx = 0; dx < transform_size; dx++) { for (int dx = 0; dx < transform_size; dx++) { int px0 = tileX * transform_size + dx; int px0 = tileX * transform_size + dx; int pix = pix1 + dx; int pix = pix1 + dx; if (pix==dbg_pix) { System.out.println("updateFgAlpha().1 pix="+pix+", ns="+ns+", dx="+dx+", dy="+dy+ ", disp_fg="+slice_disparities[fnslice][tile]+", disp_bg="+slice_disparities[ns][tile]); } if (trim_pix[fnslice][pix]) { // assign for all trim_pix if (trim_pix[fnslice][pix]) { // assign for all trim_pix if (!transparent[fnslice][pix] && !opaque[fnslice][pix]) { if (!transparent[fnslice][pix] && !opaque[fnslice][pix]) { if ((alpha_pix[fnslice][pix] && en_patch) || (!alpha_pix[fnslice][pix] && en_cut)) { if ((alpha_pix[fnslice][pix] && en_patch) || (!alpha_pix[fnslice][pix] && en_cut)) { Loading @@ -4952,43 +4981,220 @@ public class TexturedModel { // consider spread normalize to sigma? // consider spread normalize to sigma? // how to normalize BG error // how to normalize BG error // Or do not normalize at all - compare absolute values? // Or do not normalize at all - compare absolute values? if (!valid_bg) { // lazy initialization for (int i = 0; i < transform_size; i++) { Arrays.fill(bg_disparity[i], null); } valid_bg = true; } if (bg_disparity[dy][dx] == null) { bg_disparity[dy][dx] = new double [num_sens]; Arrays.fill(bg_disparity[dy][dx], Double.NaN); } if (bg_value[dy][dx] == null) { // do not need to initialize bg_value[dy][dx] = new double [num_sens]; } for (int nsens = 0; nsens < pixel_offs.length; nsens++) if (offs_bg[nsens] != null) { for (int nsens = 0; nsens < pixel_offs.length; nsens++) if (offs_bg[nsens] != null) { // corresponding BG pixels // corresponding BG pixels double px = px0 + pixel_offs[nsens][0]; double bgx = px0 + pixel_offs[nsens][0]; double py = py0 + pixel_offs[nsens][1]; double bgy = py0 + pixel_offs[nsens][1]; int ipx = (int) Math.round(px); // here just center int ibgx = (int) Math.round(bgx); // here just center int ipy = (int) Math.round(py); int ibgy = (int) Math.round(bgy); int pix_bg = ipx + ipy * width; int bg_pix = ibgx + ibgy * width; if (alpha_pix[ns][bg_pix] && !Double.isNaN(textures[ns][bg_pix])) { if (!(bg_disparity[dy][dx][nsens] >= slice_disparities[ns][tile])) { // was NaN -> true bg_disparity[dy][dx][nsens] = slice_disparities[ns][tile]; bg_value[dy][dx][nsens] = textures[ns][bg_pix]; if (pix==dbg_pix) { System.out.println(String.format( "%2d: bg_pix=%6d ibgx=%3d ibgy=%3d bg_value=%8.2f", nsens, bg_pix, ibgx, ibgy, bg_value[dy][dx][nsens])); } } } } } } } } } } } // for (int ns = 0; ns < num_slices; ns++) { // now consider if (!transparent[fnslice][indx] && !opaque[fnslice][indx]), // use bg_value[][][], bg_disparity[][][] to calculate bg weighths, // calculate FG weights (same as VAR_INTER) // add num neibs - 4 weight and make decisions for (int dy = 0; dy < transform_size; dy++) { int pix1 = pix0 + dy * width; for (int dx = 0; dx < transform_size; dx++) { int pix = pix1 + dx; if (pix==dbg_pix) { System.out.println("updateFgAlpha().2 pix="+pix); } if (trim_pix[fnslice][pix]) { // assign for all trim_pix boolean new_transparent = false; boolean new_opaque = false; if (!transparent[fnslice][pix] && !opaque[fnslice][pix]) { if ((alpha_pix[fnslice][pix] && en_patch) || (!alpha_pix[fnslice][pix] && en_cut)) { // calculate number of sensors, visible from this FG pixel int smask = occluded_map[fnslice][pix]; int num_fg = 0; double s_fg=0, s2_fg = 0; for (int nsens = 0; nsens < num_sens; nsens++ ) { if ((smask & (1 << nsens)) == 0) { double d = sensor_texture[fnslice][nsens][pix]; s_fg += d; s2_fg += d * d; num_fg++; } } int num_bg=0; double s2_bg = 0; for (int nsens = 0; nsens < (best_dir_number-1); nsens++ ) { if (pix==dbg_pix) { System.out.println(String.format( "%2d: fg_value= %8.2f bg_value=%8.2f diff=%8.2f", nsens, sensor_texture[fnslice][nsens][pix], bg_value[dy][dx][nsens], sensor_texture[fnslice][nsens][pix] - bg_value[dy][dx][nsens])); } if (((smask & (1 << nsens)) == 0) && (bg_disparity[dy][dx] != null) && !Double.isNaN(bg_disparity[dy][dx][nsens])) { double db = sensor_texture[fnslice][nsens][pix] - bg_value[dy][dx][nsens]; s2_bg += db * db; num_bg ++; } } double best_cost_bg = Double.NaN; for (int i = 0; i < num_sens; i++ ) { int nsens_plus = (best_dir_number + i - 1) % num_sens; int nsens_minus = i; if (pix==dbg_pix) { System.out.println(String.format( "%2d: fg_value= %8.2f bg_value=%8.2f diff=%8.2f", nsens_plus, sensor_texture[fnslice][nsens_plus][pix], bg_value[dy][dx][nsens_plus], sensor_texture[fnslice][nsens_plus][pix] - bg_value[dy][dx][nsens_plus])); } if (((smask & (1 << nsens_plus)) == 0) && (bg_disparity[dy][dx] != null) && !Double.isNaN(bg_disparity[dy][dx][nsens_plus])) { double db = sensor_texture[fnslice][nsens_plus][pix] - bg_value[dy][dx][nsens_plus]; s2_bg += db * db; num_bg ++; } if (num_bg >= min_sensors_bg) { double avg2_bg = s2_bg/num_bg; double cost_bg= Math.sqrt(avg2_bg); if (!(cost_bg > best_cost_bg)) { best_cost_bg = cost_bg; } if (pix==dbg_pix) { System.out.print(String.format( "avg2_bg= %8.2f cost_bg=%8.2f -> ", avg2_bg, cost_bg)); } } if (i < (num_sens -1)) { if (((smask & (1 << nsens_minus)) == 0) && (bg_disparity[dy][dx] != null) && !Double.isNaN(bg_disparity[dy][dx][nsens_minus])) { double db = sensor_texture[fnslice][nsens_minus][pix] - bg_value[dy][dx][nsens_minus]; s2_bg -= db * db; num_bg --; } } } // calculate costs // maybe multiple backgrounds? Then combine them all // each sensor - single BG - common array of 16? // cost for FG - average w/o center, possibly tilt // consider spread normalize to sigma? // how to normalize BG error // Or do not normalize at all - compare absolute values? if (num_fg >= min_sensors) {// (do not touch if less) double avg_fg = s_fg/num_fg; double avg2_fg = s2_fg/num_fg; double cost_fg = Math.sqrt(avg2_fg-avg_fg*avg_fg); double cost_bg = best_cost_bg; // calculate number of opaque neighbors int n_opaque = 0, n_neibs=0; for (int dir = 0; dir < TileNeibs.DIRS; dir++) { int pix_n = pn.getNeibIndex(pix, dir); if (pix_n >=0) { if (alpha_pix[fnslice][pix_n]) { n_opaque++; } } n_neibs++; } // positive for more opaque, negative - for more transparent double cost_neibs = weight_neib * (n_opaque - 0.5* n_neibs); double cost = Double.NaN; if (Double.isNaN(cost_bg)) { new_opaque = true; } else { // cost > 0 -> opaque, cost < 0 -> transparent cost = weight_bg*cost_bg - cost_fg + cost_neibs; if (Math.abs(cost) > cost_min) { new_opaque = cost > 0; new_transparent = cost < 0; } } if (debug_costs != null) { debug_costs[fnslice][0][pix] = cost; debug_costs[fnslice][1][pix] = cost_fg; debug_costs[fnslice][2][pix] = cost_bg; if (pix==dbg_pix) { System.out.println(String.format( "cost= %8.2f cost_neibs=%8.2f cost_fg=%8.2f cost_bg=%8.2f", cost, cost_neibs, cost_fg, cost_bg)); } } } } } // if (num_vis >= min_sensors) { } } // process sure transparent/opaque pixels } else { // if (!transparent[fnslice][indx] && !opaque[fnslice][indx]) { } else { // if (!transparent[fnslice][indx] && !opaque[fnslice][indx]) { if (transparent[fnslice][pix]) { if (transparent[fnslice][pix]) { if (alpha_pix[fnslice][pix] && en_cut) { new_transparent = true; new_alpha[pix] = false; aminus.getAndIncrement(); } } else if (opaque[fnslice][pix]) { } else if (opaque[fnslice][pix]) { new_opaque = true; } } // if (!transparent[fnslice][pix] && !opaque[fnslice][pix]) if (new_opaque) { if (!alpha_pix[fnslice][pix] && en_patch) { if (!alpha_pix[fnslice][pix] && en_patch) { new_alpha[pix] = true; new_alpha[fnslice][pix] = true; aplus.getAndIncrement(); aplus.getAndIncrement(); } } } else if (new_transparent){ if (alpha_pix[fnslice][pix] && en_cut) { new_alpha[fnslice][pix] = false; aminus.getAndIncrement(); } } } } } } } } // for (int dx = 0; dx < transform_size; dx++) { } } // for (int dy = 0; dy < transform_size; dy++) } // for (int ns = 0; ns < num_slices; ns++) { } } } } } } }; }; } } ImageDtt.startAndJoin(threads); ImageDtt.startAndJoin(threads); if (debug_stats != null) { debug_stats[nslice] = new int[] {aplus.get(), aminus.get()}; } num_modified_pixels += aplus.get() + aminus.get(); } // replace boolean alphas with the new ones. for (int nslice = 0; nslice < num_slices; nslice++) { alpha_pix[nslice] = new_alpha[nslice]; } } return aplus.get() + aminus.get(); // consider using such method without preliminary methods with using // analog (semi-transparent) alpha that finally stick to 0/1 return num_modified_pixels; } } Loading Loading @@ -5601,9 +5807,7 @@ public class TexturedModel { // Sure values to set unconditionally transparent and unconditionally opaque FG // Sure values to set unconditionally transparent and unconditionally opaque FG final double seed_fom_sure = 5.0; final double seed_fom_sure = 5.0; final double seed_inter_sure = 150.0; // 13.0; final double seed_inter_sure = 150.0; // 13.0; final double trim_fom_sure = 2.0; final double trim_fom_sure = 10; // 2.0; temporary disabling it final double min_incr = 100; // temporary disable // 5; // 20.0; // 0.5; // only for sky? final double min_incr = 100; // temporary disable // 5; // 20.0; // 0.5; // only for sky? // final double thr_same = 16; // 20; // minimal value of vars_same to block propagation // final double thr_same = 16; // 20; // minimal value of vars_same to block propagation Loading Loading @@ -5848,20 +6052,31 @@ public class TexturedModel { final boolean en_cut = true; // enable change FG pixel to transparent from opaque final boolean en_cut = true; // enable change FG pixel to transparent from opaque final boolean en_patch = true; // enable change FG pixel to opaque from transparent final boolean en_patch = true; // enable change FG pixel to opaque from transparent final double fg_disp_diff = 1.0; // do not consider obscuring too close BG (1 pix or more?) final double fg_disp_diff = 1.0; // do not consider obscuring too close BG (1 pix or more?) int max_trim_iterations = 1; final int min_sensors = 4; // minimal number of sensors visible from the FG pixel final double weight_neib = 2.0; // 1.0; // weight of same neighbors - add to cost multiplied by num_neib-4 final double weight_bg = 0.9; // 0.8; // 1.0; // 15.0/16; // 1.0; // weight of BG cost relative to the FG one // final double weight_bg2 = 0.0; // fraction of BG variance cost (1-weight_bg2) - the BG true one final double best_dir_frac = 0.6; // for BG - use this fraction of all sensors in the best direction final double cost_min = 1.0; // minimal absolute value of the total cost to make changes int max_trim_iterations = 10; int [][] occluded_map = null; int [][] occluded_map = null; double [][] dbg_occluded_map = null; double [][] dbg_occluded_map = null; double [][] occluded_textures = null; double [][] occluded_textures = null; double [][] occluded_filled_textures = null; double [][] occluded_filled_textures = null; boolean [][] sure_transparent = null; boolean [][] sure_transparent = null; boolean [][] sure_opaque = null; boolean [][] sure_opaque = null; double [][] debug_cost = (dbg_prefix != null) ? new double [trim_pixels.length][] : null; double [][][] debug_costs = (dbg_prefix != null) ? new double [trim_pixels.length][][] : null; int [][] debug_stats = (dbg_prefix != null) ? new int [trim_pixels.length][] : null; boolean [][] debug_alpha = (dbg_prefix != null) ? new boolean [trim_pixels.length][] : null; boolean [][] trim_tiles = getTrimTiles( boolean [][] trim_tiles = getTrimTiles( trim_pixels, // boolean [][] trim_pix, trim_pixels, // boolean [][] trim_pix, width, // final int width, width, // final int width, transform_size); // final int transform_size); transform_size); // final int transform_size); int updated_tiles = 0; for (int niter = 0; niter < max_trim_iterations; niter++) { for (int niter = 0; niter < max_trim_iterations; niter++) { occluded_map = getOccludedMap( occluded_map = getOccludedMap( Loading Loading @@ -5891,6 +6106,8 @@ public class TexturedModel { 0.001, // final double max_change, 0.001, // final double max_change, width); // final int width) width); // final int width) // TODO: Break here from the cycle after updating BG if (niter < (max_trim_iterations-1)) { sure_transparent = getTrimSeeds( sure_transparent = getTrimSeeds( trim_pixels, // final boolean [][] trim_pix, // pixels that may be trimmed trim_pixels, // final boolean [][] trim_pix, // pixels that may be trimmed null, // final boolean [][] seed_pix_in, // FG edge, just outside of trim_pix. Will be modified. Or null null, // final boolean [][] seed_pix_in, // FG edge, just outside of trim_pix. Will be modified. Or null Loading @@ -5905,13 +6122,20 @@ public class TexturedModel { trim_fom_pix, // final double [][] data, trim_fom_pix, // final double [][] data, trim_fom_sure, // final double threshold, trim_fom_sure, // final double threshold, true); // final boolean greater) true); // final boolean greater) if (dbg_prefix != null) { for (int i = 0; i < unbound_alpha.length; i++) { debug_alpha[i] = unbound_alpha[i].clone(); } } int updated_tiles = updateFgAlpha( updated_tiles = updateFgAlpha( channel_pixel_offsets, // final double [][][][] channel_pixel_offsets, channel_pixel_offsets, // final double [][][][] channel_pixel_offsets, occluded_filled_textures, // final double [][] textures, occluded_filled_textures, // final double [][] textures, unbound_alpha, // final boolean [][] alpha_pix, unbound_alpha, // final boolean [][] alpha_pix, gcombo_texture, // final double [][] combo_texture, // gcombo_texture, // final double [][] combo_texture, sensor_texture, // final double [][][] sensor_texture, sensor_texture, // final double [][][] sensor_texture, occluded_map, // final int [][] occluded_map, // bitmap of blocked by FG sensors min_sensors, // final int min_sensors, // minimal number of sensors visible from the FG pixel slice_disparities, // final double [][] slice_disparities, slice_disparities, // final double [][] slice_disparities, tile_booleans[TILE_KEEP], // final boolean [][] tile_keep, // tiles that have at least one pixel tile_booleans[TILE_KEEP], // final boolean [][] tile_keep, // tiles that have at least one pixel tile_booleans[TILE_STITCH], // final boolean [][] tile_stitch, // tiles that have at least one pixel tile_booleans[TILE_STITCH], // final boolean [][] tile_stitch, // tiles that have at least one pixel Loading @@ -5923,13 +6147,57 @@ public class TexturedModel { en_patch, // final boolean en_patch, // enable change FG pixel to opaque from transparent en_patch, // final boolean en_patch, // enable change FG pixel to opaque from transparent fg_disp_diff, // final double min_disp_diff, // do not consider obscuring too close BG (1 pix or more?) fg_disp_diff, // final double min_disp_diff, // do not consider obscuring too close BG (1 pix or more?) // other parameters // other parameters debug_cost, // final double [][] debug_cost, // if not null, should be double [nslices][] - will return costs/NaN weight_neib, // final double weight_neib, // weight of same neighbors weight_bg, // final double weight_bg, // weight of BG cost relative to the FG one // weight_bg2, // final double weight_bg2, // fraction of BG variance cost (1-weight_bg2) - the BG true one best_dir_frac, // final double best_dir_frac, // for BG - use this fraction of all sensors in the best direction cost_min, // final double cost_min, // minimal absolute value of the total cost to make changes debug_costs, // final double [][] debug_cost, // if not null, should be double [nslices][] - will return costs/NaN debug_stats, // final int [][] debug_stats, // if not null, should be int [nslices][] - will return number of added/removed per slice width, // final int width, width, // final int width, transform_size); // final int transform_size){ transform_size); // final int transform_size){ } if (dbg_prefix != null) { if (dbg_prefix != null) { System.out.println("updateFgAlpha() -> "+updated_tiles); for (int nslice = 0; nslice < debug_stats.length; nslice++) { System.out.println (String.format("#%02d: %5d added, %5d removed (total %5d) opaque FG pixels", nslice, debug_stats[nslice][0], debug_stats[nslice][1], debug_stats[nslice][0]+debug_stats[nslice][1])); } } String [] dbg_titles0 = {"sure","before","after", "cost", "cost_fg", "cost_bg", "combo", "occluded-filed", "occluded"}; int dbg_len = width * height; int sublen = dbg_titles0.length; String [] dbg_titles = new String [sublen * num_slices]; double [][] dbg_img = new double [dbg_titles.length][]; for (int nslice = 0; nslice< num_slices; nslice++) { for (int i = 0; i < dbg_titles0.length; i++) { dbg_titles[nslice * sublen + i] = dbg_titles0[i]+"-"+nslice; } dbg_img[nslice * sublen + 0] = new double [dbg_len]; dbg_img[nslice * sublen + 1] = new double [dbg_len]; dbg_img[nslice * sublen + 2] = new double [dbg_len]; for (int i = 0; i < dbg_len; i++) { dbg_img[nslice * sublen + 0][i] = (sure_transparent[nslice][i]? 0 : 1) + (sure_opaque[nslice][i]? 2 : 0); dbg_img[nslice * sublen + 1][i] = (debug_alpha[nslice][i]? 3 : 0); dbg_img[nslice * sublen + 2][i] = (unbound_alpha[nslice][i]? 3 : 0); } dbg_img[nslice * sublen + 3] = debug_costs[nslice][0]; dbg_img[nslice * sublen + 4] = debug_costs[nslice][1]; dbg_img[nslice * sublen + 5] = debug_costs[nslice][2]; dbg_img[nslice * sublen + 6] = gcombo_texture[nslice]; dbg_img[nslice * sublen + 7] = occluded_filled_textures[nslice]; dbg_img[nslice * sublen + 8] = occluded_textures[nslice]; } ShowDoubleFloatArrays.showArrays( dbg_img, width, height, true, dbg_prefix+"-update_fg-"+niter, // +nslice, dbg_titles); System.out.println("updateFgAlpha() -> "+updated_tiles); } } } Loading Loading
src/main/java/com/elphel/imagej/tileprocessor/TexturedModel.java +343 −75 Original line number Original line Diff line number Diff line Loading @@ -4717,6 +4717,7 @@ public class TexturedModel { if ( tile_keep[fnslice][tile] && if ( tile_keep[fnslice][tile] && !tile_fg_strong[fnslice][tile] && !tile_fg_strong[fnslice][tile] && !tile_stitch[fnslice][tile]) { // *** !tile_stitch[fnslice][tile]) { // *** double [][] offs_bg = channel_pixel_offsets[fnslice][tile]; double [][] offs_bg = channel_pixel_offsets[fnslice][tile]; for (int ns = 0; ns < num_slices; ns++) { for (int ns = 0; ns < num_slices; ns++) { if ((ns != fnslice) && if ((ns != fnslice) && Loading Loading @@ -4847,7 +4848,8 @@ public class TexturedModel { public void run() { public void run() { for (int tile = ai.getAndIncrement(); tile < tiles; tile = ai.getAndIncrement()) { for (int tile = ai.getAndIncrement(); tile < tiles; tile = ai.getAndIncrement()) { int tileY = tile / tilesX; int tileY = tile / tilesX; int indx = tileY * transform_size * width; int tileX = tile % tilesX; int indx = (tileY * width + tileX) * transform_size; search_pix: search_pix: for (int dy = 0; dy < transform_size; dy++) { for (int dy = 0; dy < transform_size; dy++) { for (int dx = 0; dx < transform_size; dx++) { for (int dx = 0; dx < transform_size; dx++) { Loading @@ -4872,8 +4874,10 @@ public class TexturedModel { final double [][][][] channel_pixel_offsets, final double [][][][] channel_pixel_offsets, final double [][] textures, final double [][] textures, final boolean [][] alpha_pix, // will be updated final boolean [][] alpha_pix, // will be updated final double [][] combo_texture, // final double [][] combo_texture, final double [][][] sensor_texture, final double [][][] sensor_texture, final int [][] occluded_map, // bitmap of blocked by FG sensors final int min_sensors, // minimal number of sensors visible from the FG pixel final double [][] slice_disparities, final double [][] slice_disparities, final boolean [][] tile_keep, // tiles that have at least one pixel final boolean [][] tile_keep, // tiles that have at least one pixel final boolean [][] tile_stitch, // tiles that have at least one pixel final boolean [][] tile_stitch, // tiles that have at least one pixel Loading @@ -4885,9 +4889,17 @@ public class TexturedModel { final boolean en_patch, // enable change FG pixel to opaque from transparent final boolean en_patch, // enable change FG pixel to opaque from transparent final double min_disp_diff, // do not consider obscuring too close BG (1 pix or more?) final double min_disp_diff, // do not consider obscuring too close BG (1 pix or more?) // other parameters // other parameters final double [][] debug_cost, // if not null, should be double [nslices][] - will return costs/NaN final double weight_neib, // weight of same neighbors final double weight_bg, // weight of BG cost relative to the FG one // final double weight_bg2, // fraction of BG variance cost (1-weight_bg2) - the BG true one final double best_dir_frac, // for BG - use this fraction of all sensors in the best direction final double cost_min, // minimal absolute value of the total cost to make changes // debug arrays final double [][][] debug_costs, // if not null, should be double [nslices][] - will return costs/NaN final int [][] debug_stats, // if not null, should be int [nslices][] - will return number of added/removed per slice final int width, final int width, final int transform_size){ final int transform_size){ final int min_sensors_bg = min_sensors; // maybe reduce? *=best_dir_frac? final int num_slices = alpha_pix.length; final int num_slices = alpha_pix.length; final int img_size = alpha_pix[0].length; final int img_size = alpha_pix[0].length; final int height = img_size/width; final int height = img_size/width; Loading @@ -4900,24 +4912,40 @@ public class TexturedModel { final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger aplus = new AtomicInteger(0); // number of added opaque pixels final AtomicInteger aplus = new AtomicInteger(0); // number of added opaque pixels final AtomicInteger aminus = new AtomicInteger(0); // number of removed opaque pixels final AtomicInteger aminus = new AtomicInteger(0); // number of removed opaque pixels final TileNeibs pn = new TileNeibs(width,height); final boolean [] new_alpha = new boolean[img_size]; int num_modified_pixels = 0; final int dbg_pix = 168170; final boolean [][] new_alpha = new boolean[num_slices][img_size]; for (int nslice = 0; nslice < num_slices; nslice++) { for (int nslice = 0; nslice < num_slices; nslice++) { int fnslice = nslice; int fnslice = nslice; System.arraycopy(alpha_pix[fnslice], 0, new_alpha, 0, img_size); System.arraycopy(alpha_pix[fnslice], 0, new_alpha[fnslice], 0, img_size); if (debug_costs != null) { debug_costs[fnslice] = new double [3][img_size]; // {cost, cost_fg, cost_bg} for (int i = 0; i < debug_costs[fnslice].length; i++) { Arrays.fill(debug_costs[fnslice][i], Double.NaN); } } ai.set(0); ai.set(0); aplus.set(0); aplus.set(0); aminus.set(0); aminus.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { threads[ithread] = new Thread() { public void run() { public void run() { double [][][] bg_value = new double [transform_size][transform_size][]; double [][][] bg_disparity = new double [transform_size][transform_size][]; for (int tile = ai.getAndIncrement(); tile < tiles; tile = ai.getAndIncrement()) { for (int tile = ai.getAndIncrement(); tile < tiles; tile = ai.getAndIncrement()) { if ((fnslice == dbg_slice) && (tile == dbg_tile )) { if ((fnslice == dbg_slice) && (tile == dbg_tile )) { System.out.println("updateFgAlpha().1 nslice="+fnslice+", tile="+tile); System.out.println("updateFgAlpha().1 nslice="+fnslice+", tile="+tile); } } if ( trim_tiles [fnslice][tile] && if ( trim_tiles [fnslice][tile] && !tile_stitch[fnslice][tile]) { !tile_stitch[fnslice][tile]) { int tileX = tile % tilesX; int tileY = tile / tilesX; int pix0 = (tileY * width + tileX) * transform_size; double [][] offs_fg = channel_pixel_offsets[fnslice][tile]; double [][] offs_fg = channel_pixel_offsets[fnslice][tile]; int num_sens = offs_fg.length; int best_dir_number = (int) Math.round (best_dir_frac * num_sens); boolean valid_bg = false; for (int ns = 0; ns < num_slices; ns++) { for (int ns = 0; ns < num_slices; ns++) { if ((ns != fnslice) && if ((ns != fnslice) && tile_keep[ns][tile] && tile_keep[ns][tile] && Loading @@ -4925,22 +4953,23 @@ public class TexturedModel { (slice_disparities[ns][tile] < slice_disparities[fnslice][tile]) && (slice_disparities[ns][tile] < slice_disparities[fnslice][tile]) && ((slice_disparities[fnslice][tile] - slice_disparities[ns][tile]) > min_disp_diff )) { ((slice_disparities[fnslice][tile] - slice_disparities[ns][tile]) > min_disp_diff )) { double [][] offs_bg = channel_pixel_offsets[ns][tile]; double [][] offs_bg = channel_pixel_offsets[ns][tile]; double [][] pixel_offs = new double [offs_bg.length][2]; double [][] pixel_offs = new double [num_sens][2]; for (int nsens = 0; nsens < pixel_offs.length; nsens++) { for (int nsens = 0; nsens < num_sens; nsens++) { if (offs_bg[nsens] != null) { // to implement sensor mask later if (offs_bg[nsens] != null) { // to implement sensor mask later pixel_offs[nsens][0] = offs_fg[nsens][0] - offs_bg[nsens][0]; pixel_offs[nsens][0] = offs_fg[nsens][0] - offs_bg[nsens][0]; pixel_offs[nsens][1] = offs_fg[nsens][1] - offs_bg[nsens][1]; pixel_offs[nsens][1] = offs_fg[nsens][1] - offs_bg[nsens][1]; } } } } int tileX = tile % tilesX; int tileY = tile / tilesX; int pix0 = (tileY * width + tileX) * transform_size; for (int dy = 0; dy < transform_size; dy++) { for (int dy = 0; dy < transform_size; dy++) { int py0 = tileY * transform_size + dy; int py0 = tileY * transform_size + dy; int pix1 = pix0 + dy * width; int pix1 = pix0 + dy * width; for (int dx = 0; dx < transform_size; dx++) { for (int dx = 0; dx < transform_size; dx++) { int px0 = tileX * transform_size + dx; int px0 = tileX * transform_size + dx; int pix = pix1 + dx; int pix = pix1 + dx; if (pix==dbg_pix) { System.out.println("updateFgAlpha().1 pix="+pix+", ns="+ns+", dx="+dx+", dy="+dy+ ", disp_fg="+slice_disparities[fnslice][tile]+", disp_bg="+slice_disparities[ns][tile]); } if (trim_pix[fnslice][pix]) { // assign for all trim_pix if (trim_pix[fnslice][pix]) { // assign for all trim_pix if (!transparent[fnslice][pix] && !opaque[fnslice][pix]) { if (!transparent[fnslice][pix] && !opaque[fnslice][pix]) { if ((alpha_pix[fnslice][pix] && en_patch) || (!alpha_pix[fnslice][pix] && en_cut)) { if ((alpha_pix[fnslice][pix] && en_patch) || (!alpha_pix[fnslice][pix] && en_cut)) { Loading @@ -4952,43 +4981,220 @@ public class TexturedModel { // consider spread normalize to sigma? // consider spread normalize to sigma? // how to normalize BG error // how to normalize BG error // Or do not normalize at all - compare absolute values? // Or do not normalize at all - compare absolute values? if (!valid_bg) { // lazy initialization for (int i = 0; i < transform_size; i++) { Arrays.fill(bg_disparity[i], null); } valid_bg = true; } if (bg_disparity[dy][dx] == null) { bg_disparity[dy][dx] = new double [num_sens]; Arrays.fill(bg_disparity[dy][dx], Double.NaN); } if (bg_value[dy][dx] == null) { // do not need to initialize bg_value[dy][dx] = new double [num_sens]; } for (int nsens = 0; nsens < pixel_offs.length; nsens++) if (offs_bg[nsens] != null) { for (int nsens = 0; nsens < pixel_offs.length; nsens++) if (offs_bg[nsens] != null) { // corresponding BG pixels // corresponding BG pixels double px = px0 + pixel_offs[nsens][0]; double bgx = px0 + pixel_offs[nsens][0]; double py = py0 + pixel_offs[nsens][1]; double bgy = py0 + pixel_offs[nsens][1]; int ipx = (int) Math.round(px); // here just center int ibgx = (int) Math.round(bgx); // here just center int ipy = (int) Math.round(py); int ibgy = (int) Math.round(bgy); int pix_bg = ipx + ipy * width; int bg_pix = ibgx + ibgy * width; if (alpha_pix[ns][bg_pix] && !Double.isNaN(textures[ns][bg_pix])) { if (!(bg_disparity[dy][dx][nsens] >= slice_disparities[ns][tile])) { // was NaN -> true bg_disparity[dy][dx][nsens] = slice_disparities[ns][tile]; bg_value[dy][dx][nsens] = textures[ns][bg_pix]; if (pix==dbg_pix) { System.out.println(String.format( "%2d: bg_pix=%6d ibgx=%3d ibgy=%3d bg_value=%8.2f", nsens, bg_pix, ibgx, ibgy, bg_value[dy][dx][nsens])); } } } } } } } } } } } // for (int ns = 0; ns < num_slices; ns++) { // now consider if (!transparent[fnslice][indx] && !opaque[fnslice][indx]), // use bg_value[][][], bg_disparity[][][] to calculate bg weighths, // calculate FG weights (same as VAR_INTER) // add num neibs - 4 weight and make decisions for (int dy = 0; dy < transform_size; dy++) { int pix1 = pix0 + dy * width; for (int dx = 0; dx < transform_size; dx++) { int pix = pix1 + dx; if (pix==dbg_pix) { System.out.println("updateFgAlpha().2 pix="+pix); } if (trim_pix[fnslice][pix]) { // assign for all trim_pix boolean new_transparent = false; boolean new_opaque = false; if (!transparent[fnslice][pix] && !opaque[fnslice][pix]) { if ((alpha_pix[fnslice][pix] && en_patch) || (!alpha_pix[fnslice][pix] && en_cut)) { // calculate number of sensors, visible from this FG pixel int smask = occluded_map[fnslice][pix]; int num_fg = 0; double s_fg=0, s2_fg = 0; for (int nsens = 0; nsens < num_sens; nsens++ ) { if ((smask & (1 << nsens)) == 0) { double d = sensor_texture[fnslice][nsens][pix]; s_fg += d; s2_fg += d * d; num_fg++; } } int num_bg=0; double s2_bg = 0; for (int nsens = 0; nsens < (best_dir_number-1); nsens++ ) { if (pix==dbg_pix) { System.out.println(String.format( "%2d: fg_value= %8.2f bg_value=%8.2f diff=%8.2f", nsens, sensor_texture[fnslice][nsens][pix], bg_value[dy][dx][nsens], sensor_texture[fnslice][nsens][pix] - bg_value[dy][dx][nsens])); } if (((smask & (1 << nsens)) == 0) && (bg_disparity[dy][dx] != null) && !Double.isNaN(bg_disparity[dy][dx][nsens])) { double db = sensor_texture[fnslice][nsens][pix] - bg_value[dy][dx][nsens]; s2_bg += db * db; num_bg ++; } } double best_cost_bg = Double.NaN; for (int i = 0; i < num_sens; i++ ) { int nsens_plus = (best_dir_number + i - 1) % num_sens; int nsens_minus = i; if (pix==dbg_pix) { System.out.println(String.format( "%2d: fg_value= %8.2f bg_value=%8.2f diff=%8.2f", nsens_plus, sensor_texture[fnslice][nsens_plus][pix], bg_value[dy][dx][nsens_plus], sensor_texture[fnslice][nsens_plus][pix] - bg_value[dy][dx][nsens_plus])); } if (((smask & (1 << nsens_plus)) == 0) && (bg_disparity[dy][dx] != null) && !Double.isNaN(bg_disparity[dy][dx][nsens_plus])) { double db = sensor_texture[fnslice][nsens_plus][pix] - bg_value[dy][dx][nsens_plus]; s2_bg += db * db; num_bg ++; } if (num_bg >= min_sensors_bg) { double avg2_bg = s2_bg/num_bg; double cost_bg= Math.sqrt(avg2_bg); if (!(cost_bg > best_cost_bg)) { best_cost_bg = cost_bg; } if (pix==dbg_pix) { System.out.print(String.format( "avg2_bg= %8.2f cost_bg=%8.2f -> ", avg2_bg, cost_bg)); } } if (i < (num_sens -1)) { if (((smask & (1 << nsens_minus)) == 0) && (bg_disparity[dy][dx] != null) && !Double.isNaN(bg_disparity[dy][dx][nsens_minus])) { double db = sensor_texture[fnslice][nsens_minus][pix] - bg_value[dy][dx][nsens_minus]; s2_bg -= db * db; num_bg --; } } } // calculate costs // maybe multiple backgrounds? Then combine them all // each sensor - single BG - common array of 16? // cost for FG - average w/o center, possibly tilt // consider spread normalize to sigma? // how to normalize BG error // Or do not normalize at all - compare absolute values? if (num_fg >= min_sensors) {// (do not touch if less) double avg_fg = s_fg/num_fg; double avg2_fg = s2_fg/num_fg; double cost_fg = Math.sqrt(avg2_fg-avg_fg*avg_fg); double cost_bg = best_cost_bg; // calculate number of opaque neighbors int n_opaque = 0, n_neibs=0; for (int dir = 0; dir < TileNeibs.DIRS; dir++) { int pix_n = pn.getNeibIndex(pix, dir); if (pix_n >=0) { if (alpha_pix[fnslice][pix_n]) { n_opaque++; } } n_neibs++; } // positive for more opaque, negative - for more transparent double cost_neibs = weight_neib * (n_opaque - 0.5* n_neibs); double cost = Double.NaN; if (Double.isNaN(cost_bg)) { new_opaque = true; } else { // cost > 0 -> opaque, cost < 0 -> transparent cost = weight_bg*cost_bg - cost_fg + cost_neibs; if (Math.abs(cost) > cost_min) { new_opaque = cost > 0; new_transparent = cost < 0; } } if (debug_costs != null) { debug_costs[fnslice][0][pix] = cost; debug_costs[fnslice][1][pix] = cost_fg; debug_costs[fnslice][2][pix] = cost_bg; if (pix==dbg_pix) { System.out.println(String.format( "cost= %8.2f cost_neibs=%8.2f cost_fg=%8.2f cost_bg=%8.2f", cost, cost_neibs, cost_fg, cost_bg)); } } } } } // if (num_vis >= min_sensors) { } } // process sure transparent/opaque pixels } else { // if (!transparent[fnslice][indx] && !opaque[fnslice][indx]) { } else { // if (!transparent[fnslice][indx] && !opaque[fnslice][indx]) { if (transparent[fnslice][pix]) { if (transparent[fnslice][pix]) { if (alpha_pix[fnslice][pix] && en_cut) { new_transparent = true; new_alpha[pix] = false; aminus.getAndIncrement(); } } else if (opaque[fnslice][pix]) { } else if (opaque[fnslice][pix]) { new_opaque = true; } } // if (!transparent[fnslice][pix] && !opaque[fnslice][pix]) if (new_opaque) { if (!alpha_pix[fnslice][pix] && en_patch) { if (!alpha_pix[fnslice][pix] && en_patch) { new_alpha[pix] = true; new_alpha[fnslice][pix] = true; aplus.getAndIncrement(); aplus.getAndIncrement(); } } } else if (new_transparent){ if (alpha_pix[fnslice][pix] && en_cut) { new_alpha[fnslice][pix] = false; aminus.getAndIncrement(); } } } } } } } } // for (int dx = 0; dx < transform_size; dx++) { } } // for (int dy = 0; dy < transform_size; dy++) } // for (int ns = 0; ns < num_slices; ns++) { } } } } } } }; }; } } ImageDtt.startAndJoin(threads); ImageDtt.startAndJoin(threads); if (debug_stats != null) { debug_stats[nslice] = new int[] {aplus.get(), aminus.get()}; } num_modified_pixels += aplus.get() + aminus.get(); } // replace boolean alphas with the new ones. for (int nslice = 0; nslice < num_slices; nslice++) { alpha_pix[nslice] = new_alpha[nslice]; } } return aplus.get() + aminus.get(); // consider using such method without preliminary methods with using // analog (semi-transparent) alpha that finally stick to 0/1 return num_modified_pixels; } } Loading Loading @@ -5601,9 +5807,7 @@ public class TexturedModel { // Sure values to set unconditionally transparent and unconditionally opaque FG // Sure values to set unconditionally transparent and unconditionally opaque FG final double seed_fom_sure = 5.0; final double seed_fom_sure = 5.0; final double seed_inter_sure = 150.0; // 13.0; final double seed_inter_sure = 150.0; // 13.0; final double trim_fom_sure = 2.0; final double trim_fom_sure = 10; // 2.0; temporary disabling it final double min_incr = 100; // temporary disable // 5; // 20.0; // 0.5; // only for sky? final double min_incr = 100; // temporary disable // 5; // 20.0; // 0.5; // only for sky? // final double thr_same = 16; // 20; // minimal value of vars_same to block propagation // final double thr_same = 16; // 20; // minimal value of vars_same to block propagation Loading Loading @@ -5848,20 +6052,31 @@ public class TexturedModel { final boolean en_cut = true; // enable change FG pixel to transparent from opaque final boolean en_cut = true; // enable change FG pixel to transparent from opaque final boolean en_patch = true; // enable change FG pixel to opaque from transparent final boolean en_patch = true; // enable change FG pixel to opaque from transparent final double fg_disp_diff = 1.0; // do not consider obscuring too close BG (1 pix or more?) final double fg_disp_diff = 1.0; // do not consider obscuring too close BG (1 pix or more?) int max_trim_iterations = 1; final int min_sensors = 4; // minimal number of sensors visible from the FG pixel final double weight_neib = 2.0; // 1.0; // weight of same neighbors - add to cost multiplied by num_neib-4 final double weight_bg = 0.9; // 0.8; // 1.0; // 15.0/16; // 1.0; // weight of BG cost relative to the FG one // final double weight_bg2 = 0.0; // fraction of BG variance cost (1-weight_bg2) - the BG true one final double best_dir_frac = 0.6; // for BG - use this fraction of all sensors in the best direction final double cost_min = 1.0; // minimal absolute value of the total cost to make changes int max_trim_iterations = 10; int [][] occluded_map = null; int [][] occluded_map = null; double [][] dbg_occluded_map = null; double [][] dbg_occluded_map = null; double [][] occluded_textures = null; double [][] occluded_textures = null; double [][] occluded_filled_textures = null; double [][] occluded_filled_textures = null; boolean [][] sure_transparent = null; boolean [][] sure_transparent = null; boolean [][] sure_opaque = null; boolean [][] sure_opaque = null; double [][] debug_cost = (dbg_prefix != null) ? new double [trim_pixels.length][] : null; double [][][] debug_costs = (dbg_prefix != null) ? new double [trim_pixels.length][][] : null; int [][] debug_stats = (dbg_prefix != null) ? new int [trim_pixels.length][] : null; boolean [][] debug_alpha = (dbg_prefix != null) ? new boolean [trim_pixels.length][] : null; boolean [][] trim_tiles = getTrimTiles( boolean [][] trim_tiles = getTrimTiles( trim_pixels, // boolean [][] trim_pix, trim_pixels, // boolean [][] trim_pix, width, // final int width, width, // final int width, transform_size); // final int transform_size); transform_size); // final int transform_size); int updated_tiles = 0; for (int niter = 0; niter < max_trim_iterations; niter++) { for (int niter = 0; niter < max_trim_iterations; niter++) { occluded_map = getOccludedMap( occluded_map = getOccludedMap( Loading Loading @@ -5891,6 +6106,8 @@ public class TexturedModel { 0.001, // final double max_change, 0.001, // final double max_change, width); // final int width) width); // final int width) // TODO: Break here from the cycle after updating BG if (niter < (max_trim_iterations-1)) { sure_transparent = getTrimSeeds( sure_transparent = getTrimSeeds( trim_pixels, // final boolean [][] trim_pix, // pixels that may be trimmed trim_pixels, // final boolean [][] trim_pix, // pixels that may be trimmed null, // final boolean [][] seed_pix_in, // FG edge, just outside of trim_pix. Will be modified. Or null null, // final boolean [][] seed_pix_in, // FG edge, just outside of trim_pix. Will be modified. Or null Loading @@ -5905,13 +6122,20 @@ public class TexturedModel { trim_fom_pix, // final double [][] data, trim_fom_pix, // final double [][] data, trim_fom_sure, // final double threshold, trim_fom_sure, // final double threshold, true); // final boolean greater) true); // final boolean greater) if (dbg_prefix != null) { for (int i = 0; i < unbound_alpha.length; i++) { debug_alpha[i] = unbound_alpha[i].clone(); } } int updated_tiles = updateFgAlpha( updated_tiles = updateFgAlpha( channel_pixel_offsets, // final double [][][][] channel_pixel_offsets, channel_pixel_offsets, // final double [][][][] channel_pixel_offsets, occluded_filled_textures, // final double [][] textures, occluded_filled_textures, // final double [][] textures, unbound_alpha, // final boolean [][] alpha_pix, unbound_alpha, // final boolean [][] alpha_pix, gcombo_texture, // final double [][] combo_texture, // gcombo_texture, // final double [][] combo_texture, sensor_texture, // final double [][][] sensor_texture, sensor_texture, // final double [][][] sensor_texture, occluded_map, // final int [][] occluded_map, // bitmap of blocked by FG sensors min_sensors, // final int min_sensors, // minimal number of sensors visible from the FG pixel slice_disparities, // final double [][] slice_disparities, slice_disparities, // final double [][] slice_disparities, tile_booleans[TILE_KEEP], // final boolean [][] tile_keep, // tiles that have at least one pixel tile_booleans[TILE_KEEP], // final boolean [][] tile_keep, // tiles that have at least one pixel tile_booleans[TILE_STITCH], // final boolean [][] tile_stitch, // tiles that have at least one pixel tile_booleans[TILE_STITCH], // final boolean [][] tile_stitch, // tiles that have at least one pixel Loading @@ -5923,13 +6147,57 @@ public class TexturedModel { en_patch, // final boolean en_patch, // enable change FG pixel to opaque from transparent en_patch, // final boolean en_patch, // enable change FG pixel to opaque from transparent fg_disp_diff, // final double min_disp_diff, // do not consider obscuring too close BG (1 pix or more?) fg_disp_diff, // final double min_disp_diff, // do not consider obscuring too close BG (1 pix or more?) // other parameters // other parameters debug_cost, // final double [][] debug_cost, // if not null, should be double [nslices][] - will return costs/NaN weight_neib, // final double weight_neib, // weight of same neighbors weight_bg, // final double weight_bg, // weight of BG cost relative to the FG one // weight_bg2, // final double weight_bg2, // fraction of BG variance cost (1-weight_bg2) - the BG true one best_dir_frac, // final double best_dir_frac, // for BG - use this fraction of all sensors in the best direction cost_min, // final double cost_min, // minimal absolute value of the total cost to make changes debug_costs, // final double [][] debug_cost, // if not null, should be double [nslices][] - will return costs/NaN debug_stats, // final int [][] debug_stats, // if not null, should be int [nslices][] - will return number of added/removed per slice width, // final int width, width, // final int width, transform_size); // final int transform_size){ transform_size); // final int transform_size){ } if (dbg_prefix != null) { if (dbg_prefix != null) { System.out.println("updateFgAlpha() -> "+updated_tiles); for (int nslice = 0; nslice < debug_stats.length; nslice++) { System.out.println (String.format("#%02d: %5d added, %5d removed (total %5d) opaque FG pixels", nslice, debug_stats[nslice][0], debug_stats[nslice][1], debug_stats[nslice][0]+debug_stats[nslice][1])); } } String [] dbg_titles0 = {"sure","before","after", "cost", "cost_fg", "cost_bg", "combo", "occluded-filed", "occluded"}; int dbg_len = width * height; int sublen = dbg_titles0.length; String [] dbg_titles = new String [sublen * num_slices]; double [][] dbg_img = new double [dbg_titles.length][]; for (int nslice = 0; nslice< num_slices; nslice++) { for (int i = 0; i < dbg_titles0.length; i++) { dbg_titles[nslice * sublen + i] = dbg_titles0[i]+"-"+nslice; } dbg_img[nslice * sublen + 0] = new double [dbg_len]; dbg_img[nslice * sublen + 1] = new double [dbg_len]; dbg_img[nslice * sublen + 2] = new double [dbg_len]; for (int i = 0; i < dbg_len; i++) { dbg_img[nslice * sublen + 0][i] = (sure_transparent[nslice][i]? 0 : 1) + (sure_opaque[nslice][i]? 2 : 0); dbg_img[nslice * sublen + 1][i] = (debug_alpha[nslice][i]? 3 : 0); dbg_img[nslice * sublen + 2][i] = (unbound_alpha[nslice][i]? 3 : 0); } dbg_img[nslice * sublen + 3] = debug_costs[nslice][0]; dbg_img[nslice * sublen + 4] = debug_costs[nslice][1]; dbg_img[nslice * sublen + 5] = debug_costs[nslice][2]; dbg_img[nslice * sublen + 6] = gcombo_texture[nslice]; dbg_img[nslice * sublen + 7] = occluded_filled_textures[nslice]; dbg_img[nslice * sublen + 8] = occluded_textures[nslice]; } ShowDoubleFloatArrays.showArrays( dbg_img, width, height, true, dbg_prefix+"-update_fg-"+niter, // +nslice, dbg_titles); System.out.println("updateFgAlpha() -> "+updated_tiles); } } } Loading