Commit deb75ee0 authored by Andrey Filippov's avatar Andrey Filippov

Working on smooth ground surface

parent ab8d3318
...@@ -468,6 +468,17 @@ public class CLTParameters { ...@@ -468,6 +468,17 @@ public class CLTParameters {
public boolean gltf_alpha_blend = false; // true; // Use alpha blend (false - opaque) public boolean gltf_alpha_blend = false; // true; // Use alpha blend (false - opaque)
// parameters for ground maps generation // parameters for ground maps generation
// discard vegetation (tall objects), LPF ground surface. Especially needed for low quality depth map (no SfM)
public boolean gsmth_use_lma = true; // use only LMA-generated depth tiles
public double gsmth_discard_low = 0.2; // discard % of the lowest tiles (holes?)
public double gsmth_discard_high = 0.3; // discard % of the tallest tiles (high objects)
public int gsmth_stile_hstep = 4; // use supertiles twice larger
public double gsmth_stile_radius = 8.0; // fit planes to the data within this radius of the supertile center
public double gsmth_sigma = 4.0; // Additionally LPF after fitting planes
public int gsmth_radius_levels = 4; // increase radius twice multiple time if there are no enough tiles
public int gsmth_min_non_empty = 10; // minimal number of non-empty tiles for fitting planes
public int gsmth_border_level = 1; // 1 - start with twice larger radius for forder supertiles
public boolean gmap_render_hdr = true; // generate textures w/o normalization to generate undistorted public boolean gmap_render_hdr = true; // generate textures w/o normalization to generate undistorted
public boolean gmap_en = true; // generate ground map from a drone (enables gmap_render_hdr) public boolean gmap_en = true; // generate ground map from a drone (enables gmap_render_hdr)
public boolean gmap_parallel_proj = true; // Use parallel projection (map) public boolean gmap_parallel_proj = true; // Use parallel projection (map)
...@@ -1626,6 +1637,16 @@ public class CLTParameters { ...@@ -1626,6 +1637,16 @@ public class CLTParameters {
properties.setProperty(prefix+"gltf_emissive", this.gltf_emissive+""); properties.setProperty(prefix+"gltf_emissive", this.gltf_emissive+"");
properties.setProperty(prefix+"gltf_alpha_blend", this.gltf_alpha_blend+""); properties.setProperty(prefix+"gltf_alpha_blend", this.gltf_alpha_blend+"");
properties.setProperty(prefix+"gsmth_use_lma", this.gsmth_use_lma+ ""); // boolean
properties.setProperty(prefix+"gsmth_discard_low", this.gsmth_discard_low+ ""); // double
properties.setProperty(prefix+"gsmth_discard_high", this.gsmth_discard_high+ ""); // double
properties.setProperty(prefix+"gsmth_stile_hstep", this.gsmth_stile_hstep+ ""); // int
properties.setProperty(prefix+"gsmth_stile_radius", this.gsmth_stile_radius+ ""); // double
properties.setProperty(prefix+"gsmth_sigma", this.gsmth_sigma+ ""); // double
properties.setProperty(prefix+"gsmth_radius_levels", this.gsmth_radius_levels+""); // int
properties.setProperty(prefix+"gsmth_min_non_empty", this.gsmth_min_non_empty+""); // int
properties.setProperty(prefix+"gsmth_border_level", this.gsmth_border_level+ ""); // int
properties.setProperty(prefix+"gmap_render_hdr", this.gmap_render_hdr+""); // boolean properties.setProperty(prefix+"gmap_render_hdr", this.gmap_render_hdr+""); // boolean
properties.setProperty(prefix+"gmap_en", this.gmap_en+""); // boolean properties.setProperty(prefix+"gmap_en", this.gmap_en+""); // boolean
properties.setProperty(prefix+"gmap_parallel_proj", this.gmap_parallel_proj+""); // boolean properties.setProperty(prefix+"gmap_parallel_proj", this.gmap_parallel_proj+""); // boolean
...@@ -2659,6 +2680,16 @@ public class CLTParameters { ...@@ -2659,6 +2680,16 @@ public class CLTParameters {
if (properties.getProperty(prefix+"gltf_emissive")!=null) this.gltf_emissive=Boolean.parseBoolean(properties.getProperty(prefix+"gltf_emissive")); if (properties.getProperty(prefix+"gltf_emissive")!=null) this.gltf_emissive=Boolean.parseBoolean(properties.getProperty(prefix+"gltf_emissive"));
if (properties.getProperty(prefix+"gltf_alpha_blend")!=null) this.gltf_alpha_blend=Boolean.parseBoolean(properties.getProperty(prefix+"gltf_alpha_blend")); if (properties.getProperty(prefix+"gltf_alpha_blend")!=null) this.gltf_alpha_blend=Boolean.parseBoolean(properties.getProperty(prefix+"gltf_alpha_blend"));
if (properties.getProperty(prefix+"gsmth_use_lma")!=null) this.gsmth_use_lma =Boolean.parseBoolean(properties.getProperty(prefix+ "gsmth_use_lma" ));
if (properties.getProperty(prefix+"gsmth_discard_low")!=null) this.gsmth_discard_low =Double.parseDouble(properties.getProperty(prefix+ "gsmth_discard_low" ));
if (properties.getProperty(prefix+"gsmth_discard_high")!=null) this.gsmth_discard_high =Double.parseDouble(properties.getProperty(prefix+ "gsmth_discard_high" ));
if (properties.getProperty(prefix+"gsmth_stile_hstep")!=null) this.gsmth_stile_hstep =Integer.parseInt(properties.getProperty(prefix+ "gsmth_stile_hstep" ));
if (properties.getProperty(prefix+"gsmth_stile_radius")!=null) this.gsmth_stile_radius =Double.parseDouble(properties.getProperty(prefix+ "gsmth_stile_radius" ));
if (properties.getProperty(prefix+"gsmth_sigma")!=null) this.gsmth_sigma =Double.parseDouble(properties.getProperty(prefix+ "gsmth_sigma" ));
if (properties.getProperty(prefix+"gsmth_radius_levels")!=null) this.gsmth_radius_levels=Integer.parseInt(properties.getProperty(prefix+ "gsmth_radius_levels"));
if (properties.getProperty(prefix+"gsmth_min_non_empty")!=null) this.gsmth_min_non_empty=Integer.parseInt(properties.getProperty(prefix+ "gsmth_min_non_empty"));
if (properties.getProperty(prefix+"gsmth_border_level")!=null) this.gsmth_border_level =Integer.parseInt(properties.getProperty(prefix+ "gsmth_border_level" ));
if (properties.getProperty(prefix+"gmap_render_hdr")!=null) this.gmap_render_hdr=Boolean.parseBoolean(properties.getProperty(prefix+ "gmap_render_hdr")); if (properties.getProperty(prefix+"gmap_render_hdr")!=null) this.gmap_render_hdr=Boolean.parseBoolean(properties.getProperty(prefix+ "gmap_render_hdr"));
if (properties.getProperty(prefix+"gmap_en")!=null) this.gmap_en=Boolean.parseBoolean(properties.getProperty(prefix+ "gmap_en")); if (properties.getProperty(prefix+"gmap_en")!=null) this.gmap_en=Boolean.parseBoolean(properties.getProperty(prefix+ "gmap_en"));
if (properties.getProperty(prefix+"gmap_parallel_proj")!=null) this.gmap_parallel_proj=Boolean.parseBoolean(properties.getProperty(prefix+"gmap_parallel_proj")); if (properties.getProperty(prefix+"gmap_parallel_proj")!=null) this.gmap_parallel_proj=Boolean.parseBoolean(properties.getProperty(prefix+"gmap_parallel_proj"));
...@@ -3921,6 +3952,26 @@ public class CLTParameters { ...@@ -3921,6 +3952,26 @@ public class CLTParameters {
gd.addMessage ("glTF export"); gd.addMessage ("glTF export");
gd.addCheckbox ("glTF use emissive textures", this.gltf_emissive); gd.addCheckbox ("glTF use emissive textures", this.gltf_emissive);
gd.addCheckbox ("glTF use alpha blend", this.gltf_alpha_blend); gd.addCheckbox ("glTF use alpha blend", this.gltf_alpha_blend);
gd.addMessage ("Extract smooth ground surface");
gd.addCheckbox ("Use only LMA disparity for ground", this.gsmth_use_lma,
"Use only LMA-generated disparity to find the ground plane to project the map.");
gd.addNumericField("Discard low fraction", this.gmap_discard_low, 4,6,"",
"Discard lowest tiles (ditches) up to this fraction of all available tiles when finding the ground plane for the map projection.");
gd.addNumericField("Discard high fraction", this.gsmth_discard_high, 4,6,"",
"Discard highest tiles (vegetation, structure) up to this fraction of all available tiles when finding the ground plane for the map projection.");
gd.addNumericField("Half-pitch of the supertiles", this.gsmth_stile_hstep, 0,3,"tiles",
"Supertiles centers will be at 1x, 3x, 5x, ... this value in each of the ortho directions.");
gd.addNumericField("Plane-fitting radius", this.gsmth_stile_radius, 4,6,"tiles",
"Fit a plane to each supertile using tiles within this radius around the center.");
gd.addNumericField("LPF sigma", this.gsmth_sigma, 4,6,"tiles",
"Use Gaussian blur to additionally blur the surface of the fitted planes.");
gd.addNumericField("Number of radius levels", this.gsmth_radius_levels, 0,3,"pix",
"Number of times to double fitting radius when there are insufficient tiles for plane fitting.");
gd.addNumericField("Minimal tiles for fitting", this.gsmth_min_non_empty, 0,3,"pix",
"Minimal number of tiles needed for plane fitting.");
gd.addNumericField("Border radius level", this.gsmth_border_level, 0,3,"pix",
"Start with higher radius level for border supertiles (1 - use twice larger radius.");
gd.addMessage ("Ground map export"); gd.addMessage ("Ground map export");
gd.addMessage ("Use of IMS/GNSS data is "+(imp.ims_use? "ENABLED":"DISABLED")+" (see 'IMS' configuration tab)"); gd.addMessage ("Use of IMS/GNSS data is "+(imp.ims_use? "ENABLED":"DISABLED")+" (see 'IMS' configuration tab)");
...@@ -5184,6 +5235,16 @@ public class CLTParameters { ...@@ -5184,6 +5235,16 @@ public class CLTParameters {
this.gltf_emissive= gd.getNextBoolean(); this.gltf_emissive= gd.getNextBoolean();
this.gltf_alpha_blend= gd.getNextBoolean(); this.gltf_alpha_blend= gd.getNextBoolean();
this.gsmth_use_lma= gd.getNextBoolean();
this.gsmth_discard_low= gd.getNextNumber();
this.gsmth_discard_high= gd.getNextNumber();
this.gsmth_stile_hstep= (int) gd.getNextNumber();
this.gsmth_stile_radius= gd.getNextNumber();
this.gsmth_sigma= gd.getNextNumber();
this.gsmth_radius_levels= (int) gd.getNextNumber();
this.gsmth_min_non_empty= (int) gd.getNextNumber();
this.gsmth_border_level= (int) gd.getNextNumber();
this.gmap_render_hdr= gd.getNextBoolean(); this.gmap_render_hdr= gd.getNextBoolean();
this.gmap_en= gd.getNextBoolean(); this.gmap_en= gd.getNextBoolean();
this.gmap_parallel_proj= gd.getNextBoolean(); this.gmap_parallel_proj= gd.getNextBoolean();
......
...@@ -5429,7 +5429,7 @@ public class OpticalFlow { ...@@ -5429,7 +5429,7 @@ public class OpticalFlow {
} }
} }
// quadCLTs[ref_index].getSmoothGround(clt_parameters); quadCLTs[ref_index].getSmoothGround(clt_parameters, debugLevel);
// later move to the right place // later move to the right place
if (adjust_imu_orient) { // (quadCLTs[ref_index].getNumOrient() >= clt_parameters.imp.mb_all_index)) { if (adjust_imu_orient) { // (quadCLTs[ref_index].getNumOrient() >= clt_parameters.imp.mb_all_index)) {
......
...@@ -1682,18 +1682,19 @@ public class QuadCLTCPU { ...@@ -1682,18 +1682,19 @@ public class QuadCLTCPU {
debug_level); debug_level);
} }
} }
public double [] getSmoothGround(final CLTParameters clt_parameters) { public double [] getSmoothGround(
final boolean use_lma = true; // false, or there will be too many gaps? CLTParameters clt_parameters,
final double discard_low = 0.1; // fraction of all pixels int debugLevel) {
final double discard_high = 0.5; // fraction of all pixels boolean use_lma = clt_parameters.gsmth_use_lma;
// final double discard_adisp, // discard above/below this fraction of average height double discard_low = clt_parameters.gsmth_discard_low;
// final double discard_rdisp, // discard above/below this fraction of average height double discard_high = clt_parameters.gsmth_discard_high;
final int stile_hstep = 4; int stile_hstep = clt_parameters.gsmth_stile_hstep;
final double stile_radius = 8.0; // double stile_radius = clt_parameters.gsmth_stile_radius;
final double sigma = 2.0; double sigma = clt_parameters.gsmth_sigma;
final int radius_levels = 4; int radius_levels = clt_parameters.gsmth_radius_levels;
final int min_non_empty = 10; // minimal number of non-empty tiles for fitting planes int min_non_empty = clt_parameters.gsmth_min_non_empty;
final int debugLevel = 3; int border_start_lev= clt_parameters.gsmth_border_level;
debugLevel = 3;
return getSmoothGround( return getSmoothGround(
clt_parameters, // final CLTParameters clt_parameters, clt_parameters, // final CLTParameters clt_parameters,
use_lma, // final boolean use_lma, // false, or there will be too many gaps? use_lma, // final boolean use_lma, // false, or there will be too many gaps?
...@@ -1704,24 +1705,26 @@ public class QuadCLTCPU { ...@@ -1704,24 +1705,26 @@ public class QuadCLTCPU {
sigma, // final double sigma, sigma, // final double sigma,
radius_levels, // final int radius_levels, radius_levels, // final int radius_levels,
min_non_empty, // final int min_non_empty, // minimal number of non-empty tiles for fitting planes min_non_empty, // final int min_non_empty, // minimal number of non-empty tiles for fitting planes
border_start_lev, // final int border_start_lev0,
debugLevel); // final int debugLevel); debugLevel); // final int debugLevel);
} }
public double [] getSmoothGround( public double [] getSmoothGround(
final CLTParameters clt_parameters, final CLTParameters clt_parameters,
final boolean use_lma, // false, or there will be too many gaps? final boolean use_lma, // false, or there will be too many gaps?
final double discard_low, // fraction of all pixels final double discard_low, // fraction of all pixels
final double discard_high, // fraction of all pixels final double discard_high, // fraction of all pixels
// final double discard_adisp, // discard above/below this fraction of average height
// final double discard_rdisp, // discard above/below this fraction of average height
final int stile_hstep, final int stile_hstep,
final double stile_radius, final double stile_radius,
final double sigma, final double sigma,
final int radius_levels, final int radius_levels,
final int min_non_empty, // minimal number of non-empty tiles for fitting planes final int min_non_empty, // minimal number of non-empty tiles for fitting planes
final int border_start_lev0,
final int debugLevel) { final int debugLevel) {
final int border_start_lev = Math.min(border_start_lev0,radius_levels-1);
final int stile_step = 2 * stile_hstep; final int stile_step = 2 * stile_hstep;
final int num_bins = 1000; final int num_bins = 1000;
final double normal_damping = 0.001; // pull to horizontal if not enough data final double normal_damping = 0.000001; // 0.001; // pull to horizontal if not enough data
final double hist_rlow = 0.5; final double hist_rlow = 0.5;
final double hist_rhigh = 2.0; final double hist_rhigh = 2.0;
// allow strong/high, but not near the edges // allow strong/high, but not near the edges
...@@ -1734,6 +1737,8 @@ public class QuadCLTCPU { ...@@ -1734,6 +1737,8 @@ public class QuadCLTCPU {
final double [][][] wnd= new double[radius_levels][][]; // ][irad][irad]; final double [][][] wnd= new double[radius_levels][][]; // ][irad][irad];
final double [] rad = new double [radius_levels]; final double [] rad = new double [radius_levels];
final int [] irada = new int [radius_levels]; final int [] irada = new int [radius_levels];
final double [][] dbg2_img= (debugLevel > 0) ? new double [2][tilesX*tilesY]: null;
for (int nlev = 0; nlev < radius_levels; nlev++ ) { for (int nlev = 0; nlev < radius_levels; nlev++ ) {
if (nlev==0) { if (nlev==0) {
rad[nlev] = stile_radius; rad[nlev] = stile_radius;
...@@ -1779,16 +1784,23 @@ public class QuadCLTCPU { ...@@ -1779,16 +1784,23 @@ public class QuadCLTCPU {
int stileX = nstile % stilesX; int stileX = nstile % stilesX;
int stileY = nstile / stilesX; int stileY = nstile / stilesX;
int nlev = 0; int nlev = 0;
if ((stileX == 0) || (stileY==0) || (stileX == (stilesX-1)) || (stileY == (stilesY-1))) {
nlev = border_start_lev; // start from the second level
}
int num_non_empty; // fill data arrays and the histogram int num_non_empty; // fill data arrays and the histogram
int tileXC = stile_hstep + stile_step * stileX; // center tiles int tileXC = stile_hstep + stile_step * stileX; // center tiles
int tileYC = stile_hstep + stile_step * stileY; int tileYC = stile_hstep + stile_step * stileY;
int ntileC = tileXC + tilesX * tileYC; int ntileC = tileXC + tilesX * tileYC;
int numgood = 0;
int irad=0;
int idia=0;
double [] stile_d=null;
double [] stile_w=null;
for (; nlev < radius_levels; nlev++) { for (; nlev < radius_levels; nlev++) {
int irad = irada[nlev]; irad = irada[nlev];
int idia = 2 * irad - 1; idia = 2 * irad - 1;
double [] stile_d = new double [idia*idia]; stile_d = new double [idia*idia];
double [] stile_w = new double [idia*idia]; stile_w = new double [idia*idia];
// Arrays.fill(stile_w, 0.0); // not all elements may be filled // Arrays.fill(stile_w, 0.0); // not all elements may be filled
Arrays.fill(hist, 0.0); Arrays.fill(hist, 0.0);
double sw=0; // , swd=0; double sw=0; // , swd=0;
...@@ -1842,7 +1854,7 @@ public class QuadCLTCPU { ...@@ -1842,7 +1854,7 @@ public class QuadCLTCPU {
} }
shp = sh- hist[indx]; shp = sh- hist[indx];
double thr_high = hist_low+ (indx + (sh - dh)/(sh-shp))/num_bins *(hist_high-hist_low); double thr_high = hist_low+ (indx + (sh - dh)/(sh-shp))/num_bins *(hist_high-hist_low);
int numgood = 0; numgood = 0;
// boolean [] good = new boolean[ds[0].length]; // boolean [] good = new boolean[ds[0].length];
sw = 0.0; sw = 0.0;
// swd = 0.0; // swd = 0.0;
...@@ -1860,8 +1872,13 @@ public class QuadCLTCPU { ...@@ -1860,8 +1872,13 @@ public class QuadCLTCPU {
} }
} }
if (numgood < min_non_empty) { if (numgood >= min_non_empty) {
continue; // go to the next radius level break; // go to the next radius level
}
}
if (dbg2_img != null) {
dbg2_img[0][ntileC] = nlev;
dbg2_img[1][ntileC] = numgood;
} }
// fit plane // fit plane
double [][][] mdata = new double [numgood][][]; double [][][] mdata = new double [numgood][][];
...@@ -1893,7 +1910,7 @@ public class QuadCLTCPU { ...@@ -1893,7 +1910,7 @@ public class QuadCLTCPU {
stiles_coeff[nstile][0] = approx2d[0][2]; // offset stiles_coeff[nstile][0] = approx2d[0][2]; // offset
stiles_coeff[nstile][1] = approx2d[0][0]; // tiltX stiles_coeff[nstile][1] = approx2d[0][0]; // tiltX
stiles_coeff[nstile][2] = approx2d[0][1]; // tiltY stiles_coeff[nstile][2] = approx2d[0][1]; // tiltY
}
} }
} }
}; };
...@@ -1929,12 +1946,14 @@ public class QuadCLTCPU { ...@@ -1929,12 +1946,14 @@ public class QuadCLTCPU {
ImageDtt.startAndJoin(threads); ImageDtt.startAndJoin(threads);
// Maybe use Gaussian? to additionally smooth "seams" // Maybe use Gaussian? to additionally smooth "seams"
double [][] dbg_img = null; double [][] dbg_img = null;
if (debugLevel > 0 ) { if (dbg2_img !=null ) {
dbg_img = new double[5][]; dbg_img = new double[7][];
dbg_img[0] = dls[2]; // strt dbg_img[0] = dls[2]; // strt
dbg_img[1] = dls[0]; // disp dbg_img[1] = dls[0]; // disp
dbg_img[2] = dls[1]; // lma dbg_img[2] = dls[1]; // lma
dbg_img[3] = smooth_disparity.clone(); dbg_img[3] = smooth_disparity.clone();
dbg_img[5] = dbg2_img[0]; // nlev
dbg_img[6] = dbg2_img[1]; // numgood
} }
if (sigma > 0) { if (sigma > 0) {
...@@ -1942,13 +1961,13 @@ public class QuadCLTCPU { ...@@ -1942,13 +1961,13 @@ public class QuadCLTCPU {
} }
if (dbg_img != null) { if (dbg_img != null) {
dbg_img[4] = smooth_disparity; dbg_img[4] = smooth_disparity;
String [] dbg_titles = {"str", "disp", "lma", "smooth", "blur"}; String [] dbg_titles = {"str", "disp", "lma", "smooth", "blur", "nlev","numgood"};
ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays(
dbg_img, dbg_img,
tp.getTilesX(), tp.getTilesX(),
tp.getTilesY(), tp.getTilesY(),
true, true,
getImageName()+"-smooth-ground.tiff ", getImageName()+"-smooth-ground.tiff",
dbg_titles); dbg_titles);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment