Commit 04a6a7dd authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Autoranging for lwir images/texture tiles

parent ea60a595
Loading
Loading
Loading
Loading
+51 −5
Original line number Diff line number Diff line
@@ -11,6 +11,9 @@ public class ColorProcParameters {
	public boolean lwir_islwir =        false;
	public double  lwir_low =           27000;
	public double  lwir_high    =       31000;
	public boolean lwir_autorange =      true;
	public double  lwir_too_cold =       100.0; // discard this number of pixels too cold
	public double  lwir_too_hot =          3.0; // discard this number of pixels too hot
	public int     lwir_palette =           0; // 0 - white - hot, 1 - black - hot, 2+ - colored
	public boolean lwir_subtract_dc   = false;
	public boolean lwir_eq_chn   =      true;  // adjust average temperature between channels
@@ -68,12 +71,20 @@ public class ColorProcParameters {
	public boolean isMonochrome() {
		return lwir_islwir; // for now it is the only reason to be monochrome
	}
	public boolean isLwir() {
		return lwir_islwir;
	}

	private ColorProcParameters() {}
	public ColorProcParameters(
			boolean lwir_islwir,        // false;
			double  lwir_low,           // 27000;
			double  lwir_high,          // 31000;

			boolean lwir_autorange,     //  true;
			double  lwir_too_cold,      //   100.0; // discard this number of pixels too cold
			double  lwir_too_hot,       //     3.0; // discard this number of pixels too hot

			int     lwir_palette,       //  0 - white - hot, 1 - black - hot, 2+ - colored
			boolean lwir_subtract_dc,   //   = false;
			boolean lwir_eq_chn,        // true
@@ -128,6 +139,11 @@ public class ColorProcParameters {
		this.lwir_islwir = lwir_islwir;
		this.lwir_low = lwir_low;
		this.lwir_high = lwir_high;

		this.lwir_autorange = lwir_autorange;
		this.lwir_too_cold =  lwir_too_cold;
		this.lwir_too_hot =   lwir_too_hot;

		this.lwir_palette = lwir_palette;
		this.lwir_subtract_dc = lwir_subtract_dc;
		this.lwir_eq_chn =lwir_eq_chn;
@@ -183,6 +199,11 @@ public class ColorProcParameters {
		properties.setProperty(prefix+"lwir_islwir",        this.lwir_islwir+"");
		properties.setProperty(prefix+"lwir_low",           this.lwir_low+"");
		properties.setProperty(prefix+"lwir_high",          this.lwir_high+"");

		properties.setProperty(prefix+"lwir_autorange",     this.lwir_autorange+"");
		properties.setProperty(prefix+"lwir_too_cold",      this.lwir_too_cold+"");
		properties.setProperty(prefix+"lwir_too_hot",       this.lwir_too_hot+"");

		properties.setProperty(prefix+"lwir_palette",       this.lwir_palette+"");
		properties.setProperty(prefix+"lwir_subtract_dc",   this.lwir_subtract_dc+"");
		properties.setProperty(prefix+"lwir_eq_chn",        this.lwir_eq_chn+"");
@@ -247,6 +268,11 @@ public class ColorProcParameters {
		if (properties.getProperty(prefix+"lwir_islwir")!=null)    this.lwir_islwir=Boolean.parseBoolean(properties.getProperty(prefix+"lwir_islwir"));
		if (properties.getProperty(prefix+"lwir_low")!=null)       this.lwir_low=Double.parseDouble(properties.getProperty(prefix+"lwir_low"));
		if (properties.getProperty(prefix+"lwir_high")!=null)      this.lwir_high=Double.parseDouble(properties.getProperty(prefix+"lwir_high"));

		if (properties.getProperty(prefix+"lwir_autorange")!=null) this.lwir_autorange=Boolean.parseBoolean(properties.getProperty(prefix+"lwir_autorange"));
		if (properties.getProperty(prefix+"lwir_too_cold")!=null)  this.lwir_too_cold=Double.parseDouble(properties.getProperty(prefix+"lwir_too_cold"));
		if (properties.getProperty(prefix+"lwir_too_hot")!=null)   this.lwir_too_hot=Double.parseDouble(properties.getProperty(prefix+"lwir_too_hot"));

		if (properties.getProperty(prefix+"lwir_palette")!=null) this.lwir_palette=Integer.parseInt(properties.getProperty(prefix+"lwir_palette"));
		if (properties.getProperty(prefix+"lwir_subtract_dc")!=null) this.lwir_subtract_dc=Boolean.parseBoolean(properties.getProperty(prefix+"lwir_subtract_dc"));
		if (properties.getProperty(prefix+"lwir_eq_chn")!=null) this.lwir_eq_chn=Boolean.parseBoolean(properties.getProperty(prefix+"lwir_eq_chn"));
@@ -316,8 +342,13 @@ public class ColorProcParameters {
		}
		gd.addMessage("--- Parameters related to thermal imaging ---");
		gd.addCheckbox    ("These sensors are thermal vision with absolute temperature",    this.lwir_islwir);
		gd.addNumericField("Lowest value (temperature) to display",                         this.lwir_low,     3); //0.53
		gd.addNumericField("Highest value (temperature) to display",                        this.lwir_high,     3); //0.53
		gd.addNumericField("Lowest value (temperature) to display",                         this.lwir_low,      6); //0.53
		gd.addNumericField("Highest value (temperature) to display",                        this.lwir_high,     6); //0.53

		gd.addCheckbox    ("Autorange LWIR low/high temperatures (within limits above)",    this.lwir_autorange);   // true
		gd.addNumericField("Number of too cold pixels/image to ignore during autorange",    this.lwir_too_cold, 4); // 100.0
		gd.addNumericField("Number of too hot pixels/image to ignore during autorange",     this.lwir_too_hot,  4); //  0.53

		gd.addNumericField("LWIR pallet (0-white hot, 1-black hot, 2+ - pseudo colors ",    this.lwir_palette,    0);
		gd.addCheckbox    ("Subtract each image DC when conditioning",                      this.lwir_subtract_dc);
		gd.addCheckbox    ("Adjust average temperature between cameras",                    this.lwir_eq_chn);
@@ -401,6 +432,11 @@ public class ColorProcParameters {
		this.lwir_islwir=              gd.getNextBoolean();
		this.lwir_low=                 gd.getNextNumber();
		this.lwir_high=                gd.getNextNumber();

		this.lwir_autorange =          gd.getNextBoolean();
		this.lwir_too_cold=            gd.getNextNumber();
		this.lwir_too_hot=             gd.getNextNumber();

		this.lwir_palette=       (int) gd.getNextNumber();
		this.lwir_subtract_dc=         gd.getNextBoolean();
		this.lwir_eq_chn=              gd.getNextBoolean();
@@ -462,6 +498,11 @@ public class ColorProcParameters {
		cp.lwir_islwir =             this.lwir_islwir;
		cp.lwir_low =                this.lwir_low;
		cp.lwir_high =               this.lwir_high;

		cp.lwir_autorange =          this.lwir_autorange;
		cp.lwir_too_cold =           this.lwir_too_cold;
		cp.lwir_too_hot =            this.lwir_too_hot;

		cp.lwir_palette =            this.lwir_palette;
		cp.lwir_subtract_dc =        this.lwir_subtract_dc;
		cp.lwir_eq_chn =             this.lwir_eq_chn;
@@ -521,6 +562,11 @@ public class ColorProcParameters {
		this.lwir_islwir =             cp.lwir_islwir;
		this.lwir_low =                cp.lwir_low;
		this.lwir_high =               cp.lwir_high;

		this.lwir_autorange =          cp.lwir_autorange;
		this.lwir_too_cold =           cp.lwir_too_cold;
		this.lwir_too_hot =            cp.lwir_too_hot;

		this.lwir_palette =            cp.lwir_palette;
		this.lwir_subtract_dc =        cp.lwir_subtract_dc;
		this.lwir_eq_chn =             cp.lwir_eq_chn;
+4 −1
Original line number Diff line number Diff line
@@ -245,7 +245,10 @@ private Panel panel1,
		false, //     boolean lwir_islwir,        // false;
		27000, //     double  lwir_low,           // 27000;
		31000, //     double  lwir_high,          // 31000;
		0,     //     int     lwir_palette,       //  0 - white - hot, 1 - black - hot, 2+ - colored
		true,  //     boolean lwir_autorange,     //  true;
		100.0, //     double  lwir_too_cold,      //   100.0; // discard this number of pixels too cold
		3.0,   //     double  lwir_too_hot,       //     3.0; // discard this number of pixels too hot
		1,     //     int     lwir_palette,       //  0 - white - hot, 1 - black - hot, 2+ - pseudocolored
		false, //     boolean lwir_subtract_dc,   //   = false;
		true,  // 	  boolean lwir_eq_chn   =      true;  // adjust average temperature between channels
		true,  //     boolean correct_vignetting, //  = true;
+199 −15
Original line number Diff line number Diff line
@@ -96,6 +96,10 @@ public class QuadCLT {
    boolean                                                is_mono = false; // Use clt_kernels?
    double  []                                             lwir_offsets = null; // per image subtracted values
    double                                                 lwir_offset =  Double.NaN; // average of lwir_offsets[]
    // hot and cold are calculated during autoranging (when generating 4 images for restored (added lwir_offset)
    // absolute temperatures to be used instead of colorProcParameters lwir_low and lwir_high if autoranging
    // is enabled
    double []                                              lwir_cold_hot = null;
//    int []                                                 woi_tops; // used to calculate scanline timing


@@ -104,6 +108,18 @@ public class QuadCLT {
    public boolean isLwir() {return !Double.isNaN(lwir_offset);} // clt_kernels
    public double  getLwirOffset() {return lwir_offset;}

    public double [] getColdHot() {
    	return lwir_cold_hot;
    }
    public void setColdHot(double [] cold_hot) {
    	lwir_cold_hot = cold_hot;
    }
    public void setColdHot(double cold, double hot) {
    	lwir_cold_hot = new double[2];
    	lwir_cold_hot[0] = cold;
    	lwir_cold_hot[1] = hot;
    }

    public void    resetGroundTruthByRig() {
    	tp.rig_disparity_strength = null;
    }
@@ -4255,9 +4271,9 @@ public class QuadCLT {
				  }
			  }
		  }

		  double [][][] iclt_data = new double [clt_data.length][][];
		  if (!infinity_corr && (clt_parameters.gen_chn_img || clt_parameters.gen_4_img || clt_parameters.gen_chn_stacks)) {
			  ImagePlus [] imps_RGB = new ImagePlus[clt_data.length];
//			  ImagePlus [] imps_RGB = new ImagePlus[clt_data.length];
			  for (int iQuad = 0; iQuad < clt_data.length; iQuad++){

				  String title=name+"-"+String.format("%02d", iQuad);
@@ -4296,10 +4312,11 @@ public class QuadCLT {
								  results[iQuad].getTitle()+"-CLT-D"+clt_parameters.disparity);
					  }
				  }
				  double [][] iclt_data = new double [clt_data[iQuad].length][];
				  for (int chn=0; chn<iclt_data.length;chn++) if (clt_data[iQuad][chn] != null) {
					  iclt_data[chn] = image_dtt.iclt_2d(
							  clt_data[iQuad][chn],           // scanline representation of dcd data, organized as dct_size x dct_size tiles
				  iclt_data[iQuad] = new double [clt_data[iQuad].length][];

				  for (int ncol=0; ncol<iclt_data[iQuad].length;ncol++) if (clt_data[iQuad][ncol] != null) {
					  iclt_data[iQuad][ncol] = image_dtt.iclt_2d(
							  clt_data[iQuad][ncol],           // scanline representation of dcd data, organized as dct_size x dct_size tiles
							  clt_parameters.transform_size,  // final int
							  clt_parameters.clt_window,      // window_type
							  15,                             // clt_parameters.iclt_mask,       //which of 4 to transform back
@@ -4308,14 +4325,61 @@ public class QuadCLT {
							  debugLevel);

				  }

				  if (clt_parameters.gen_chn_stacks) sdfa_instance.showArrays(iclt_data,
				  if (clt_parameters.gen_chn_stacks) sdfa_instance.showArrays(
//				  if (clt_parameters.gen_chn_stacks || true) sdfa_instance.showArrays(
						  iclt_data[iQuad],
						  (tilesX + 0) * clt_parameters.transform_size,
						  (tilesY + 0) * clt_parameters.transform_size,
						  true,
						  results[iQuad].getTitle()+"-ICLT-RGB-D"+clt_parameters.disparity);
				  /*
				  if (!clt_parameters.gen_chn_img) continue;
				  imps_RGB[iQuad] = linearStackToColor(
						  clt_parameters,
						  colorProcParameters,
						  rgbParameters,
						  title, // String name,
						  "-D"+clt_parameters.disparity, //String suffix, // such as disparity=...
						  toRGB,
						  !this.correctionsParameters.jpeg, // boolean bpp16, // 16-bit per channel color mode for result
						  !batch_mode, // true, // boolean saveShowIntermediate, // save/show if set globally
						  false, // boolean saveShowFinal,        // save/show result (color image?)
						  iclt_data[iQuad],
						  tilesX *  clt_parameters.transform_size,
						  tilesY *  clt_parameters.transform_size,
						  scaleExposures[iQuad], // double scaleExposure, // is it needed?
						  debugLevel );
                 */
			  } // end of generating shifted channel images


			  // Use iclt_data here for LWIR autorange
			  if (colorProcParameters.isLwir() && colorProcParameters.lwir_autorange) {
				  double rel_low =  colorProcParameters.lwir_low;
				  double rel_high = colorProcParameters.lwir_high;
				  if (!Double.isNaN(getLwirOffset())) {
					  rel_low -=  getLwirOffset();
					  rel_high -= getLwirOffset();
				  }
				  double [] cold_hot =  autorange(
						  iclt_data, // double [][][] iclt_data, //  [iQuad][ncol][i] - normally only [][2][] is non-null
						  rel_low, // double hard_cold,// matches data, DC (this.lwir_offset)  subtracted
						  rel_high, // double hard_hot, // matches data, DC (this.lwir_offset)  subtracted
						  colorProcParameters.lwir_too_cold, // double too_cold, // pixels per image
						  colorProcParameters.lwir_too_hot, // double too_hot,  // pixels per image
						  1024); // int num_bins)
				  if (cold_hot != null) {
					  if (!Double.isNaN(getLwirOffset())) {
						  cold_hot[0] += getLwirOffset();
						  cold_hot[1] += getLwirOffset();
					  }
				  }
				  setColdHot(cold_hot); // will be used for shifted images and for texture tiles
			  }
			  ImagePlus [] imps_RGB = new ImagePlus[clt_data.length];
				  for (int iQuad = 0; iQuad < clt_data.length; iQuad++){
					  if (!clt_parameters.gen_chn_img) continue;
					  String title=name+"-"+String.format("%02d", iQuad);
					  imps_RGB[iQuad] = linearStackToColor(
							  clt_parameters,
							  colorProcParameters,
@@ -4326,13 +4390,14 @@ public class QuadCLT {
							  !this.correctionsParameters.jpeg, // boolean bpp16, // 16-bit per channel color mode for result
							  !batch_mode, // true, // boolean saveShowIntermediate, // save/show if set globally
							  false, // boolean saveShowFinal,        // save/show result (color image?)
						  iclt_data,
							  iclt_data[iQuad],
							  tilesX *  clt_parameters.transform_size,
							  tilesY *  clt_parameters.transform_size,
							  scaleExposures[iQuad], // double scaleExposure, // is it needed?
							  debugLevel );
				  }


			  } // end of generating shifted channel images
			  if (clt_parameters.gen_chn_img) {
				  // combine to a sliced color image
				  int [] slice_seq = {0,1,3,2}; //clockwise
@@ -4420,6 +4485,112 @@ public class QuadCLT {
		  }
		  return rslt;
	  }
	  public int [] getLwirHistogram(
			  double [] data,
			  double    hard_cold,
			  double    hard_hot,
			  int       num_bins) {
			  int [] hist = new int [num_bins];
			  double k = num_bins / (hard_hot - hard_cold);
			  for (double d:data) {
				  int bin = (int) ((d - hard_cold)*k);
				  if (bin < 0) bin = 0;
				  else if (bin >= num_bins) bin = (num_bins -1);
				  hist[bin]++;
			  }
			  return hist;
		  }
		  public int [] addHist(
				  int [] this_hist,
				  int [] other_hist) {
			  for (int i = 0; i < this_hist.length; i++) {
				  this_hist[i] += other_hist[i];
			  }
			  return this_hist;
		  }
		  // get low/high (soft min/max) from the histogram
		  // returns value between 0.0 (low histogram limit and 1.0 - high histgram limit
		  public double getMarginFromHist(
				  int [] hist, // histogram
				  double cumul_val, // cummulative number of items to be ignored
				  boolean high_marg) { // false - find low margin(output ~0.0) , true - find high margin (output ~1.0)
			  int n = 0;
			  int n_prev = 0;
			  int bin;
			  double s = 1.0 / hist.length;
			  double v;
			  if (high_marg) {
				  for (bin = hist.length -1; bin >= 0; bin--) {
					  n_prev = n;
					  n+= hist[bin];
					  if (n > cumul_val) break;
				  }
				  if (n <= cumul_val) {
					  v =  0.0; // cumul_val > total number of samples
				  } else {
					  v = s* (bin + 1 - (cumul_val - n_prev)/(n - n_prev));
				  }

			  } else {
				  for (bin = 0; bin < hist.length; bin++) {
					  n_prev = n;
					  n+= hist[bin];
					  if (n > cumul_val) break;
				  }
				  if (n <= cumul_val) {
					  v =  1.0; // cumul_val > total number of samples
				  } else {
					  v = s * (bin + (cumul_val - n_prev)/(n - n_prev));
				  }
			  }
			  return v;
		  }

		  public double [] autorange(
				  double [][][] iclt_data, //  [iQuad][ncol][i] - normally only [][2][] is non-null
				  double hard_cold,// matches data, DC (this.lwir_offset)  subtracted
				  double hard_hot, // matches data, DC (this.lwir_offset)  subtracted
				  double too_cold, // pixels per image
				  double too_hot,  // pixels per image
				  int num_bins) {
			  int ncol;
			  for (ncol = 0; ncol < iclt_data[0].length; ncol++) {
				  if (iclt_data[0][ncol] != null) break;
			  }
			  too_cold *= iclt_data.length;
			  too_hot *= iclt_data.length;
			  int [] hist = null;
			  for (int iQuad = 0; iQuad < iclt_data.length; iQuad++) {
				  int [] this_hist = getLwirHistogram(
						  iclt_data[iQuad][ncol], // double [] data,
						  hard_cold,
						  hard_hot,
						  num_bins);
				  if (hist == null) {
					  hist = this_hist;
				  } else {
					  addHist(
							  hist,
							  this_hist);
				  }
			  }
			  double [] rel_lim = {
					  getMarginFromHist(
							  hist, // histogram
							  too_cold, // double cumul_val, // cummulative number of items to be ignored
							  false), // boolean high_marg)
					  getMarginFromHist(
							  hist, // histogram
							  too_hot, // double cumul_val, // cummulative number of items to be ignored
							  true)}; // boolean high_marg)
			  double [] abs_lim = {
					  rel_lim[0] * (hard_hot - hard_cold) + hard_cold,
					  rel_lim[1] * (hard_hot - hard_cold) + hard_cold,
			  };
			  return abs_lim;
		  }



	  // float
	  public ImagePlus linearStackToColor(
@@ -4471,6 +4642,8 @@ public class QuadCLT {

	  }
	  // double data


	  public ImagePlus linearStackToColor(
			  CLTParameters         clt_parameters,
			  ColorProcParameters   colorProcParameters,
@@ -4509,9 +4682,20 @@ public class QuadCLT {
			  String [] rgba_titles = {"red","green","blue","alpha"};
			  String [] titles = (alpha == null) ? rgb_titles : rgba_titles;
			  int num_slices = (alpha == null) ? 3 : 4;
			  double mn = colorProcParameters.lwir_low;
			  double mx = colorProcParameters.lwir_high;
			  double [] cold_hot = getColdHot();
			  if (cold_hot != null) {
				  mn = cold_hot[0];
				  mx = cold_hot[1];
			  }

			  double offset = getLwirOffset();
			  double mn = colorProcParameters.lwir_low - offset;
			  double mx = colorProcParameters.lwir_high - offset;
			  if (!Double.isNaN(offset)) {
				  mn -=  offset;
				  mx -=  offset;
			  }

			  ThermalColor tc = new ThermalColor(
					  colorProcParameters.lwir_palette,
					  mn,