Commit b6b0e4d8 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Implemented 8bpp mode for ML output

parent a520cd7b
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ public class BiQuadParameters {
	public boolean ml_keep_hor_vert =          true; // include combined horizontal and vertical pairs data in the ML output
	public boolean ml_keep_debug=              true; // include debug layer(s) data in the ML output
	public boolean ml_8bit=                    true; // output in 8-bit format (default - 32-bit TIFF
	public double  ml_limit_extrim =           0.00001; // ignore lowest and highest values when converting to 8 bpp
	public boolean ml_show_ml =                true; // show each generated MLoutput file


@@ -185,6 +186,8 @@ public class BiQuadParameters {
				"Keep additional (debug) layers that may change for different file versions");
		gd.addCheckbox    ("Use 8 bpp TIFF (default - 32 bpp)",                                                   this.ml_8bit,
				"Reduce file size by lowering bpp");
		gd.addNumericField("When converting to 8bpp, limit fraction of extreme values",                           1E6 * this.ml_limit_extrim,  1,8,"ppm",
				"Use values histogram to find min/max values, ignoring(limiting) this fraction (parts per million) of pixels at both extremes");
		gd.addCheckbox    ("Show each generated ML file",                                                         this.ml_show_ml,
				"Use only for small number of generated files to reduce memory usage");

@@ -241,6 +244,7 @@ public class BiQuadParameters {
		this.ml_keep_hor_vert=              gd.getNextBoolean();
		this.ml_keep_debug=                 gd.getNextBoolean();
		this.ml_8bit=                       gd.getNextBoolean();
		this.ml_limit_extrim=               gd.getNextNumber() * 1E-6;
		this.ml_show_ml=                    gd.getNextBoolean();
	}

@@ -298,6 +302,7 @@ public class BiQuadParameters {
		properties.setProperty(prefix+"ml_keep_hor_vert",          this.ml_keep_hor_vert+"");
		properties.setProperty(prefix+"ml_keep_debug",             this.ml_keep_debug+"");
		properties.setProperty(prefix+"ml_8bit",                   this.ml_8bit+"");
		properties.setProperty(prefix+"ml_limit_extrim",           this.ml_limit_extrim+"");
		properties.setProperty(prefix+"ml_show_ml",                this.ml_show_ml+"");


@@ -353,6 +358,7 @@ public class BiQuadParameters {
		if (properties.getProperty(prefix+"ml_keep_hor_vert")!=null)        this.ml_keep_hor_vert=Boolean.parseBoolean(properties.getProperty(prefix+"ml_keep_hor_vert"));
		if (properties.getProperty(prefix+"ml_keep_debug")!=null)           this.ml_keep_debug=Boolean.parseBoolean(properties.getProperty(prefix+"ml_keep_debug"));
		if (properties.getProperty(prefix+"ml_8bit")!=null)                 this.ml_8bit=Boolean.parseBoolean(properties.getProperty(prefix+"ml_8bit"));
		if (properties.getProperty(prefix+"ml_limit_extrim")!=null)         this.ml_limit_extrim=Double.parseDouble(properties.getProperty(prefix+"ml_limit_extrim"));
		if (properties.getProperty(prefix+"ml_show_ml")!=null)              this.ml_show_ml=Boolean.parseBoolean(properties.getProperty(prefix+"ml_show_ml"));
	}
	@Override
@@ -408,9 +414,8 @@ public class BiQuadParameters {
		bqp.ml_keep_hor_vert=           this.ml_keep_hor_vert;
		bqp.ml_keep_debug=              this.ml_keep_debug;
		bqp.ml_8bit=                    this.ml_8bit;
		bqp.ml_limit_extrim=            this.ml_limit_extrim;
		bqp.ml_show_ml=                 this.ml_show_ml;
		return bqp;


	}
}
+47 −0
Original line number Diff line number Diff line
@@ -1162,7 +1162,54 @@ public class Correlation2d {
    	int oindex = tileY *tile_width * full_width  + tileX * tile_width + (ml_index/tile_width)*full_width + (ml_index%tile_width) ;
    	ml_data[ml_layer][oindex] = ml_value;
    }
    /**
     * Get a single value from the combined multi-layer ML array, viewable as an image
     * @param tileX horizontal tile index
     * @param tileY vertical tile index
     * @param ml_hwidth half-width of the preserved 2d correlation (0 - single point, 1 -> 3x3, 2 -> 5x5, 7 - all data)
     * @param ml_data multi-layer array, each layer matches an image of ((2 * ml_hwidth + 1) * tilesX) by ((2 * ml_hwidth + 1) * tilesY) in scanline order
     * Each tile corresponds to  (2 * ml_hwidth + 1) * (2 * ml_hwidth + 1) square in the image. Only selected tiles will be updated, so it is good to initialize array
     * with all Double.NaN values
     * @param ml_layer layer to save tile data
     * @param ml_index data index within tile
     * @param tilesX image width in tiles
     * @return value indexed by tileX, tileY, ml_layer and ml_index
     */
    public double restoreMlTilePixel(
    		int         tileX,
    		int         tileY,
    		int         ml_hwidth,
    		double [][] ml_data,
    		int         ml_layer,
    		int         ml_index,
    		int         tilesX) {
    	int tile_width = 2 * ml_hwidth + 1;
    	int full_width = tile_width * tilesX;
    	int oindex = tileY *tile_width * full_width  + tileX * tile_width + (ml_index/tile_width)*full_width + (ml_index%tile_width) ;
    	return ml_data[ml_layer][oindex];
    }

    /**
     * Get an index of the selected tile+index in a ML array layer
     * @param tileX horizontal tile index
     * @param tileY vertical tile index
     * @param ml_hwidth half-width of the preserved 2d correlation (0 - single point, 1 -> 3x3, 2 -> 5x5, 7 - all data)
     * @param ml_index data index within tile
     * @param tilesX image width in tiles
     * @return index of teh selected pixel in thye whole image (specified by  tileX, tileY, and ml_index)
     */

    public  int getMlTilePixelIndex(
    		int         tileX,
    		int         tileY,
    		int         ml_hwidth,
    		int         ml_index,
    		int         tilesX) {
    	int tile_width = 2 * ml_hwidth + 1;
    	int full_width = tile_width * tilesX;
    	int oindex = tileY *tile_width * full_width  + tileX * tile_width + (ml_index/tile_width)*full_width + (ml_index%tile_width) ;
    	return oindex;
    }



+158 −7
Original line number Diff line number Diff line
@@ -1400,6 +1400,11 @@ public class TwoQuadCLT {
		  String ml_directory= quadCLT_main.correctionsParameters.selectMlDirectory(
		  true,  // smart,
		  true);  //newAllowed, // save
			Correlation2d corr2d = new Correlation2d(
					clt_parameters.img_dtt,              // ImageDttParameters  imgdtt_params,
					clt_parameters.transform_size,             // int transform_size,
					2.0,                        //  double wndx_scale, // (wndy scale is always 1.0)
					(debugLevel > -1));   //   boolean debug)

		  for (int sweep_step = 0; sweep_step < clt_parameters.rig.ml_sweep_steps; sweep_step++){
			  double disparity_offset = 0; // clt_parameters.rig.ml_disparity_sweep * (2.0 * sweep_step/(clt_parameters.rig.ml_sweep_steps - 1.0) -1.0);
@@ -1422,6 +1427,9 @@ public class TwoQuadCLT {
	    			  disparity_offset,                         // double               disp_offset,
	    			  quadCLT_main,                             // QuadCLT              quadCLT_main,
	    			  quadCLT_aux,                              // QuadCLT              quadCLT_aux,
	    			  corr2d,                                   //Correlation2d        corr2d, // to access "other" layer
	    			  clt_parameters.rig.ml_8bit,               // boolean              use8bpp,
	    			  clt_parameters.rig.ml_limit_extrim,       // double               limit_extrim,
	    			  clt_parameters.rig.ml_keep_aux,           // boolean              keep_aux,
	    			  clt_parameters.rig.ml_keep_inter,         // boolean              keep_inter,
	    			  clt_parameters.rig.ml_keep_hor_vert,      // boolean              keep_hor_vert,
@@ -1441,6 +1449,9 @@ public class TwoQuadCLT {
			  double               disp_offset,
			  QuadCLT              quadCLT_main,
			  QuadCLT              quadCLT_aux,
			  Correlation2d        corr2d, // to access "other" layer
			  boolean              use8bpp,
			  double               limit_extrim,
			  boolean              keep_aux,
			  boolean              keep_inter,
			  boolean              keep_hor_vert,
@@ -1478,19 +1489,155 @@ public class TwoQuadCLT {
		  int [] dbg_indices = {
				  ImageDtt.ML_DBG1_INDEX        //18 - just debug data (first - auto phase correlation)
		  };
		  int [] non_corr_indices = {
				  ImageDtt.ML_OTHER_INDEX,      //17 - other data: 0 (top left tile corner) - preset disparity of the tile, 1: (next element) - ground trouth data, 2:
				  ImageDtt.ML_DBG1_INDEX        //18 - just debug data (first - auto phase correlation)
		  };

		  boolean [] skip_layers = new boolean [ImageDtt.ML_TITLES.length];
		  if (!keep_aux)       for (int nl:aux_indices)      skip_layers[nl] = true;
		  if (!keep_inter)     for (int nl:inter_indices)    skip_layers[nl] = true;
		  if (!keep_hor_vert)  for (int nl:hor_vert_indices) skip_layers[nl] = true;
		  if (!keep_debug)     for (int nl:dbg_indices)      skip_layers[nl] = true;

	      float [] fpixels;
		  ImageStack array_stack=new ImageStack(width,height);
		  double soft_mn = Double.NaN,soft_mx = Double.NaN;
		  if (use8bpp) {
			  int num_bins = 256;
			  boolean [] skip_histogram =   skip_layers.clone();
			  for (int nl:non_corr_indices) skip_histogram[nl] = true;
			  double mn = 0.0, mx = 0.0; // data has both positive and negative values
			  for (int nl = 0; nl < ml_data.length; nl++) if (!skip_histogram[nl]) {
				  for (int i = 0; i < ml_data[nl].length; i++) if (!Double.isNaN(ml_data[nl][i])){
					  if      (ml_data[nl][i] > mx) mx = ml_data[nl][i];
					  else if (ml_data[nl][i] < mn) mn = ml_data[nl][i];
				  }
			  }
			  if (debugLevel > -2) {
				  System.out.println("saveMlFile(): min="+mn+", max="+mx);
			  }
			  int [] histogram = new int [num_bins];
			  int num_values = 0;
			  for (int nl = 0; nl < ml_data.length; nl++) if (!skip_histogram[nl]) {
				  for (int i = 0; i < ml_data[nl].length; i++) if (!Double.isNaN(ml_data[nl][i])){
					  int bin = (int) Math.round(num_bins*(ml_data[nl][i] - mn)/(mx-mn));
					  // rounding errors?
					  if (bin < 0) bin = 0;
					  else if (bin >= num_bins) bin = num_bins-1;
					  histogram[bin]++;
					  num_values++;
				  }
			  }
			  double ignore_vals = limit_extrim*num_values;
			  soft_mn = mn;
			  soft_mx = mx;
			  {
				  double sl = 0.0;
				  int i = 0;
				  while (sl < ignore_vals) {
					  i++;
					  sl+= histogram[i];
					  soft_mn += (mx-mn)/num_bins;
				  }
				  double f = (sl - ignore_vals)/histogram[i];
				  soft_mn -= (mx-mn)/num_bins*(1.0 - f);

				  sl = 0.0;
				  i = num_bins-1;
				  while (sl < ignore_vals) {
					  i--;
					  sl+= histogram[i];
					  soft_mx -= (mx-mn)/num_bins;
				  }
				  f = (sl - ignore_vals)/histogram[i];
				  soft_mn += (mx-mn)/num_bins*(1.0 - f);
				  if (debugLevel > -2) {
					  System.out.println("saveMlFile(): soft min="+soft_mn+", soft max="+soft_mx);
				  }
			  }
			  // convert double data  to byte, so v<=soft_mn -> 1; v>= soft_mx -> 255, NaN -> 0
			  byte [][] iml_data = new byte [ml_data.length][];
			  for (int nl = 0; nl < ml_data.length; nl++) if (!skip_layers[nl]) {
				  iml_data[nl] = new byte [ml_data[nl].length];
				  if (nl == ImageDtt.ML_OTHER_INDEX) {
					  // special treatment - make 2 bytes of one disparity value
					  for (int tileY = 0; tileY < tilesY; tileY++) {
						  for (int tileX = 0; tileX < tilesX; tileX++) {
							  int nTile = tileY * tilesX + tileX;
							  double target_disparity = corr2d.restoreMlTilePixel(
							    		tileX,                            // int         tileX,
							    		tileY,                            // int         tileY,
							    		ml_hwidth,                        // int         ml_hwidth,
							    		ml_data,                          // double [][] ml_data,
							    		ImageDtt.ML_OTHER_INDEX,          // int         ml_layer,
							    		ImageDtt.ML_OTHER_TARGET ,        // int         ml_index,
							    		tilesX);                          // int         tilesX);
							  double gtruth_disparity = corr2d.restoreMlTilePixel(
							    		tileX,                            // int         tileX,
							    		tileY,                            // int         tileY,
							    		ml_hwidth,                        // int         ml_hwidth,
							    		ml_data,                          // double [][] ml_data,
							    		ImageDtt.ML_OTHER_INDEX,          // int         ml_layer,
							    		ImageDtt.ML_OTHER_GTRUTH ,        // int         ml_index,
							    		tilesX);                          // int         tilesX);
							  double gtruth_strength = corr2d.restoreMlTilePixel(
							    		tileX,                            // int         tileX,
							    		tileY,                            // int         tileY,
							    		ml_hwidth,                        // int         ml_hwidth,
							    		ml_data,                          // double [][] ml_data,
							    		ImageDtt.ML_OTHER_INDEX,          // int         ml_layer,
							    		ImageDtt.ML_OTHER_GTRUTH_STRENGTH ,     // int         ml_index,
							    		tilesX);                          // int         tilesX);
							  // converting disparity to 9.7 ( 1/128 pixel step, +/-256 pixels disparity range), 0x8000 - zero disparity
							  // converting strength to 2 bytes 0.16 fixed point
							  int itd = (int) Math.round(128 * target_disparity) + 0x8000;
							  int [] itarget_disparity = {itd >> 8, itd & 0xff};
							  int igt = (int) Math.round(128 * gtruth_disparity) + 0x8000;
							  int [] igtruth_disparity = {igt >> 8, igt & 0xff};
							  int igs = (int) Math.round(0x10000 * gtruth_strength);
							  int [] igtruth_strength =  {igs >> 8, igs & 0xff};
							  for (int nb = 0; nb<2; nb++) {
								  if (!Double.isNaN(target_disparity)) {
									  int indx =  corr2d.getMlTilePixelIndex(tileX,tileY, ml_hwidth, ImageDtt.ML_OTHER_TARGET + nb, tilesX);
									  iml_data[nl][indx] = (byte) itarget_disparity[nb];
								  }
								  if (!Double.isNaN(gtruth_disparity)) {
									  int indx =  corr2d.getMlTilePixelIndex(tileX,tileY, ml_hwidth, ImageDtt.ML_OTHER_GTRUTH + nb, tilesX);
									  iml_data[nl][indx] = (byte) igtruth_disparity[nb];
								  }
								  if (gtruth_strength > 0.0) {
									  int indx =  corr2d.getMlTilePixelIndex(tileX,tileY, ml_hwidth, ImageDtt.ML_OTHER_GTRUTH_STRENGTH + nb, tilesX);
									  iml_data[nl][indx] = (byte) igtruth_strength[nb];
								  }
							  }
						  }
					  }
				  } else {
					  double k = 254.0/(soft_mx-soft_mn);
					  for (int i = 0; i < ml_data[nl].length;i++) {
						  if (Double.isNaN(ml_data[nl][i])){
							  iml_data[nl][i] = 0; // -128;
						  } else {
							  int iv = (int) Math.round(k*(ml_data[nl][i]-soft_mn));
							  if      (iv < 0) iv = 0;
							  else if (iv > 254) iv = 254;
							  iml_data[nl][i] = (byte) iv; //  (iv - 127); // NaN will stay 0;
						  }
					  }
				  }
			  }
		      for (int nl = 0; nl< ml_data.length; nl++) if (!skip_layers[nl]) {
		            array_stack.addSlice(ImageDtt.ML_TITLES[nl], iml_data[nl]);
		      }
		  } else {
		      float [] fpixels;
		      for (int nl = 0; nl< ml_data.length; nl++) if (!skip_layers[nl]) {
		    	  fpixels=new float[ml_data[nl].length];
		    	  for (int j=0;j<fpixels.length;j++) fpixels[j]=(float) ml_data[nl][j];
		            array_stack.addSlice(ImageDtt.ML_TITLES[nl],    fpixels);
		      }
		  }

	      double disparityRadiusMain =  quadCLT_main.geometryCorrection.getDisparityRadius();
	      double disparityRadiusAux =   quadCLT_aux.geometryCorrection.getDisparityRadius();
	      double intercameraBaseline =  quadCLT_aux.geometryCorrection.getBaseline();
@@ -1505,12 +1652,16 @@ public class TwoQuadCLT {
	      imp_ml.setProperty("disparityRadiusMain",  ""+disparityRadiusMain);
	      imp_ml.setProperty("disparityRadiusAux",  ""+disparityRadiusAux);
	      imp_ml.setProperty("intercameraBaseline",  ""+intercameraBaseline);
	      imp_ml.setProperty("data_min",  ""+soft_mn);
	      imp_ml.setProperty("data_max",  ""+soft_mx);

	      imp_ml.setProperty("comment_tileWidth",   "Square tile size for each 2d correlation, always odd");
	      imp_ml.setProperty("comment_dispOffset",  "Tile target disparity minum ground truth disparity");
	      imp_ml.setProperty("comment_ML_OTHER_TARGET",  "Offset of the target disparity in the \"other\" layer tile");
	      imp_ml.setProperty("comment_ML_OTHER_GTRUTH",  "Offset of the ground truth disparity in the \"other\" layer tile");
	      imp_ml.setProperty("comment_ML_OTHER_GTRUTH_STRENGTH",  "Offset of the ground truth strength in the \"other\" layer tile");
	      imp_ml.setProperty("comment_data_min",  "Defined only for 8bpp mode - value, corresponding to -127 (-128 is NaN)");
	      imp_ml.setProperty("comment_data_max",  "Defined only for 8bpp mode - value, corresponding to +127 (-128 is NaN)");

	      imp_ml.setProperty("comment_disparityRadiusMain",  "Side of the square where 4 main camera subcameras are located (mm)");
	      imp_ml.setProperty("comment_disparityRadiusAux",  "Side of the square where 4 main camera subcameras are located (mm). Disparity is specified for the main camera");