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

Autoranging for lwir images/texture tiles

parent ea60a595
......@@ -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+"");
......@@ -244,9 +265,14 @@ public class ColorProcParameters {
}
public boolean getProperties(String prefix,Properties properties){
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_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;
......
......@@ -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;
......
......@@ -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;
}
......@@ -3812,8 +3828,8 @@ public class QuadCLT {
boolean [][] saturation_imp, // (near) saturated pixels or null
CLTParameters clt_parameters,
EyesisCorrectionParameters.DebayerParameters debayerParameters,
ColorProcParameters colorProcParameters,
CorrectionColorProc.ColorGainsParameters channelGainParameters,
ColorProcParameters colorProcParameters,
CorrectionColorProc.ColorGainsParameters channelGainParameters,
EyesisCorrectionParameters.RGBParameters rgbParameters,
// int convolveFFTSize, // 128 - fft size, kernel size should be size/2
double [] scaleExposures, // probably not needed here
......@@ -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,15 @@ 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,
......@@ -4326,13 +4344,60 @@ 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
// 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,
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 );
}
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,
......
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