Loading src/main/java/com/elphel/imagej/cameras/ColorProcParameters.java +51 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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+""); Loading Loading @@ -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")); Loading Loading @@ -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); Loading Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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; Loading src/main/java/com/elphel/imagej/correction/Eyesis_Correction.java +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading src/main/java/com/elphel/imagej/tileprocessor/QuadCLT.java +199 −15 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; } Loading Loading @@ -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); Loading Loading @@ -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 Loading @@ -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, Loading @@ -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 Loading Loading @@ -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( Loading Loading @@ -4471,6 +4642,8 @@ public class QuadCLT { } // double data public ImagePlus linearStackToColor( CLTParameters clt_parameters, ColorProcParameters colorProcParameters, Loading Loading @@ -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, Loading Loading
src/main/java/com/elphel/imagej/cameras/ColorProcParameters.java +51 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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+""); Loading Loading @@ -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")); Loading Loading @@ -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); Loading Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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; Loading
src/main/java/com/elphel/imagej/correction/Eyesis_Correction.java +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
src/main/java/com/elphel/imagej/tileprocessor/QuadCLT.java +199 −15 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; } Loading Loading @@ -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); Loading Loading @@ -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 Loading @@ -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, Loading @@ -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 Loading Loading @@ -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( Loading Loading @@ -4471,6 +4642,8 @@ public class QuadCLT { } // double data public ImagePlus linearStackToColor( CLTParameters clt_parameters, ColorProcParameters colorProcParameters, Loading Loading @@ -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, Loading