Commit 904ad2bc authored by Andrey Filippov's avatar Andrey Filippov

implemented/debugged photometric sensors matching

parent 5a125530
......@@ -475,7 +475,7 @@ public class IntersceneMatchParameters {
String [] stereo_choices = new String [stereo_views.length + 1];
stereo_choices[0] = "--none--";
for (int i = 0; i < stereo_views.length; i++) {
stereo_choices[i+1] = doublesToString(stereo_views[i])+" mm";
stereo_choices[i+1] = doublesToString(stereo_views[i],"%.0f")+" mm";
}
gd. addChoice("Remove stereo-view (base, up, back)", stereo_choices, stereo_choices[0],
"Remove selected stereo-view, consisting of streo-base, viewpoint above camera, viewpoint behing camera - all in mm");
......@@ -1031,7 +1031,7 @@ public class IntersceneMatchParameters {
*/
properties.setProperty(prefix+"stereo_views_num", this.stereo_views.length+""); // int
for (int i = 0; i < this.stereo_views.length; i++) {
properties.setProperty(prefix+"stereo_views_"+i, doublesToString(this.stereo_views[i])); // String
properties.setProperty(prefix+"stereo_views_"+i, doublesToString(this.stereo_views[i],"%.0f")); // String
properties.setProperty(prefix+"generate_stereo_var_"+i, this.generate_stereo_var[i]+""); // boolean
}
......@@ -1785,12 +1785,16 @@ public class IntersceneMatchParameters {
return doublesToString(data, null);
}
public static String doublesToString(double [] data, String fmt) {
if ((fmt == null) || (fmt.trim().length()==0)) {
fmt = "%.0f";
}
// if ((fmt == null) || (fmt.trim().length()==0)) {
// fmt = "%.0f";
// }
String s = "";
for (int i = 0; i < data.length; i++) {
s+=String.format(fmt,data[i]);
if (fmt==null) {
s += data[i]; // unformatted
} else {
s+=String.format(fmt,data[i]);
}
if (i < (data.length - 1)) {
s+= ", ";
}
......
......@@ -4044,7 +4044,8 @@ public class OpticalFlow {
boolean export_images = clt_parameters.imp.export_images;
boolean export_dsi_image = clt_parameters.imp.export_ranges;
boolean export_ml_files = clt_parameters.imp.export_ml_files;
boolean export_ml_files = clt_parameters.imp.export_ml_files;
boolean calibrate_photometric = true;
boolean show_dsi_image = clt_parameters.imp.show_ranges && !batch_mode;
boolean show_images = clt_parameters.imp.show_images && !batch_mode;
......@@ -4424,7 +4425,9 @@ public class OpticalFlow {
} else {// if (build_orientations) {
if (!reuse_video) { // reuse_video only uses reference scene
for (int scene_index = ref_index - 1; scene_index >= earliest_scene ; scene_index--) {
quadCLTs[scene_index] = (QuadCLT) quadCLT_main.spawnNoModelQuadCLT( // restores image data
// quadCLTs[scene_index] = (QuadCLT) quadCLT_main.spawnNoModelQuadCLT( // restores image data
// to include ref scene photometric calibration
quadCLTs[scene_index] = quadCLTs[ref_index].spawnNoModelQuadCLT( // restores image data
set_channels[scene_index].set_name,
clt_parameters,
colorProcParameters, //
......@@ -4504,6 +4507,62 @@ public class OpticalFlow {
}
}
if (calibrate_photometric) {
if (combo_dsn_final == null) { // always re-read?
combo_dsn_final =quadCLTs[ref_index].readDoubleArrayFromModelDirectory( // always re-read?
"-INTER-INTRA-LMA", // String suffix,
0, // int num_slices, // (0 - all)
null); // int [] wh);
}
double [][] combo_dsn_final_filtered =
conditionComboDsnFinal(
true, // boolean use_conf, // use configuration parameters, false - use following
clt_parameters, // CLTParameters clt_parameters,
combo_dsn_final, // double [][] combo_dsn_final, // dls,
quadCLTs[ref_index], // QuadCLT scene,
debugLevel); // int debugLevel);// > 0
QuadCLT.calibratePhotometric(
clt_parameters, // CLTParameters clt_parameters,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
0.0, // final double min_strength,
100.0, // final double max_diff, // 30.0
2, // final int num_refines, // 2
combo_dsn_final_filtered, // final double [][] combo_dsn_final, // double [][] combo_dsn_final, // dls,
threadsMax, // int threadsMax,
true); //final boolean debug)
// copy offsets to the current to be saved with other properties. Is it correct/needed?
quadCLTs[ref_index].saveInterProperties( // save properties for interscene processing (extrinsics, ers, ...)
null, // String path, // full name with extension or w/o path to use x3d directory
debugLevel+1);
quadCLT_main.setLwirOffsets(quadCLTs[ref_index].getLwirOffsets());
quadCLT_main.setLwirScales(quadCLTs[ref_index].getLwirScales());
// Re-read reference and other scenes using new offsets
quadCLTs[ref_index] = (QuadCLT) quadCLT_main.spawnQuadCLT( // restores dsi from "DSI-MAIN"
set_channels[ref_index].set_name,
clt_parameters,
colorProcParameters, //
threadsMax,
debugLevel);
quadCLTs[ref_index].setDSRBG(
clt_parameters, // CLTParameters clt_parameters,
threadsMax, // int threadsMax, // maximal number of threads to launch
updateStatus, // boolean updateStatus,
debugLevel); // int debugLevel)
ers_reference = quadCLTs[ref_index].getErsCorrection();
if (!reuse_video) { // reuse_video only uses reference scene
for (int scene_index = ref_index - 1; scene_index >= earliest_scene ; scene_index--) {
// quadCLTs[scene_index] = (QuadCLT) quadCLT_main.spawnNoModelQuadCLT( // restores image data
// to include ref scene photometric calibration
quadCLTs[scene_index] = quadCLTs[ref_index].spawnNoModelQuadCLT( // restores image data
set_channels[scene_index].set_name,
clt_parameters,
colorProcParameters, //
threadsMax,
debugLevel-2);
}
}
}
if (test_ers) { // only debug feature
test_ers0 = quadCLTs.length -1; // make it always == reference !
......@@ -5025,6 +5084,7 @@ public class OpticalFlow {
quadCLTs[ref_index], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
true, // toRGB, // final boolean toRGB,
clt_parameters.imp.show_color_nan, // boolean show_nan
"GPU-SHIFTED-D"+clt_parameters.disparity, // String suffix,
threadsMax, // int threadsMax,
debugLevel); // int debugLevel)
......@@ -5042,6 +5102,7 @@ public class OpticalFlow {
quadCLTs[ref_index], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
false, // toRGB, // final boolean toRGB,
clt_parameters.imp.show_mono_nan, // boolean show_nan
"GPU-SHIFTED-D"+clt_parameters.disparity, // String suffix,
threadsMax, // int threadsMax,
debugLevel); // int debugLevel)
......@@ -5121,6 +5182,7 @@ public class OpticalFlow {
quadCLTs[ref_index], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
true, // toRGB, // final boolean toRGB,
clt_parameters.imp.show_color_nan,
scenes_suffix+"GPU-SHIFTED-FOREGROUND", // String suffix,
threadsMax, // int threadsMax,
debugLevel); // int debugLevel)
......@@ -5138,6 +5200,7 @@ public class OpticalFlow {
quadCLTs[ref_index], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
false, // toRGB, // final boolean toRGB,
clt_parameters.imp.show_mono_nan,
scenes_suffix+"GPU-SHIFTED-FOREGROUND", // String suffix,
threadsMax, // int threadsMax,
debugLevel); // int debugLevel)
......@@ -5164,6 +5227,7 @@ public class OpticalFlow {
quadCLTs[ref_index], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
true, // final boolean toRGB,
clt_parameters.imp.show_color_nan,
"GPU-SHIFTED-BACKGROUND", // String suffix,
threadsMax, // int threadsMax,
debugLevel); // int debugLevel)
......@@ -5181,6 +5245,7 @@ public class OpticalFlow {
quadCLTs[ref_index], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
false, // final boolean toRGB,
clt_parameters.imp.show_mono_nan,
"GPU-SHIFTED-BACKGROUND", // String suffix,
threadsMax, // int threadsMax,
debugLevel); // int debugLevel)
......@@ -5244,6 +5309,7 @@ public class OpticalFlow {
}
}
if (export_ml_files) {
if (combo_dsn_final == null) { // always re-read?
combo_dsn_final =quadCLTs[ref_index].readDoubleArrayFromModelDirectory( // always re-read?
......@@ -5381,6 +5447,8 @@ public class OpticalFlow {
quadCLTs[nscene], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
true, // final boolean toRGB,
clt_parameters.imp.show_color_nan,
"", // String suffix, no suffix here
threadsMax, // int threadsMax,
debugLevel); // int debugLevel)
......@@ -5403,6 +5471,7 @@ public class OpticalFlow {
quadCLTs[nscene], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
false, // final boolean toRGB,
clt_parameters.imp.show_mono_nan,
"", // String suffix, no suffix here
threadsMax, // int threadsMax,
debugLevel); // int debugLevel)
......@@ -5516,6 +5585,7 @@ public class OpticalFlow {
quadCLTs[nscene], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
true, // final boolean toRGB,
clt_parameters.imp.show_color_nan,
"", // String suffix, no suffix here
threadsMax, // int threadsMax,
debugLevel); // int debugLevel)
......@@ -5538,6 +5608,7 @@ public class OpticalFlow {
quadCLTs[nscene], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
false, // final boolean toRGB,
clt_parameters.imp.show_mono_nan,
"", // String suffix, no suffix here
threadsMax, // int threadsMax,
debugLevel); // int debugLevel)
......@@ -5702,6 +5773,7 @@ public class OpticalFlow {
quadCLTs[nscene], // final QuadCLT scene,
quadCLTs[ref_index], // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
toRGB, // final boolean toRGB,
(toRGB? clt_parameters.imp.show_color_nan : clt_parameters.imp.show_mono_nan),
"", // String suffix, no suffix here
QuadCLT.THREADS_MAX, // int threadsMax,
debugLevel); // int debugLevel)
......
......@@ -2169,6 +2169,175 @@ public class QuadCLT extends QuadCLTCPU {
IJ.d2s(0.000000001*(System.nanoTime()-this.startTime),3)+" sec, --- Free memory3="+Runtime.getRuntime().freeMemory()+" (of "+Runtime.getRuntime().totalMemory()+")");
}
public static boolean calibratePhotometric(
CLTParameters clt_parameters,
final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
final double min_strength,
final double max_diff, // 30.0
final int num_refines, // 2
final double [][] combo_dsn_final, // double [][] combo_dsn_final, // dls,
int threadsMax,
final boolean debug)
{
// filter disparity by LMA only, same bg and fg
double [] disparity_ref= combo_dsn_final[OpticalFlow.COMBO_DSN_INDX_DISP].clone();
for (int i = 00; i < disparity_ref.length; i++) {
if (combo_dsn_final[OpticalFlow.COMBO_DSN_INDX_STRENGTH][i] < min_strength) {
disparity_ref[i] = Double.NaN;
} else if (combo_dsn_final[OpticalFlow.COMBO_DSN_INDX_DISP_BG_ALL][i] !=
combo_dsn_final[OpticalFlow.COMBO_DSN_INDX_DISP][i]) {
disparity_ref[i] = Double.NaN;
}
}
ImagePlus img_ref = renderGPUFromDSI(
-1, // final int sensor_mask,
false, // final boolean merge_channels,
null, // final Rectangle full_woi_in, // show larger than sensor WOI in tiles (or null)
clt_parameters, // CLTParameters clt_parameters,
disparity_ref, // double [] disparity_ref,
OpticalFlow.ZERO3, // final double [] scene_xyz, // camera center in world coordinates
OpticalFlow.ZERO3, // final double [] scene_atr, // camera orientation relative to world frame
ref_scene, // final QuadCLT scene,
ref_scene, // final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
false, // final boolean toRGB,
true, // final boolean show_nan,
"PHOTOMETRIC", // String suffix,
threadsMax, // int threadsMax,
-2); // final int debugLevel);
img_ref.show();
ImageStack imageStack = img_ref.getStack();
int num_sens=imageStack.getSize();
float [] fpixels;
double [][] dpixels = new double [num_sens][];
for (int n = 00; n < num_sens; n++) {
fpixels = (float[]) imageStack.getPixels(n + 1);
dpixels[n] = new double [fpixels.length];
for (int i = 0; i < fpixels.length; i++) {
dpixels[n][i] = fpixels[i];
}
}
// double [][] dpix_orig = new double[num_sens][];
// for (int n = 0; n < num_sens; n++) {
// dpix_orig[n] = dpixels[n].clone();
// }
int width = img_ref.getWidth();
int height = img_ref.getHeight();
int len = width* height;
double [] avg_pix = new double [len];
double [] offsets = new double[dpixels.length];
double [] scales = new double[dpixels.length];
double s0 = 0.0;
double sx= 0.0;
double sx2 = 0.0;
double [] sy = new double[num_sens];
double [] sxy = new double[num_sens];
boolean [] good_pix = new boolean[len];
Arrays.fill(good_pix, true);
for (int nref = 0; nref < num_refines; nref++) {
Arrays.fill(avg_pix, 0.0);
for (int i = 0; i < len; i++) {
for (int n = 0; n < num_sens; n++) {
avg_pix[i]+=dpixels[n][i];
good_pix[i] &= !Double.isNaN(dpixels[n][i]);
}
avg_pix[i] /= dpixels.length;
}
Arrays.fill(offsets,0.0);
Arrays.fill(scales,0.0);
s0 = 0.0;
sx= 0.0;
sx2 = 0.0;
Arrays.fill(sy,0.0);
Arrays.fill(sxy,0.0);
for (int i = 0; i < len; i++) if (good_pix[i]) { // !Double.isNaN(avg_pix[i])){
s0 += 1.0;
sx += avg_pix[i];
sx2 += avg_pix[i] * avg_pix[i];
for (int n = 0; n < num_sens; n++) {
sy[n] += dpixels[n][i];
sxy[n] += dpixels[n][i] * avg_pix[i];
}
}
for (int n = 0; n < num_sens; n++) {
double d = s0 * sx2 + sx * sy[n];
scales[n] = (sxy[n] * s0 + sy[n] * sy[n]) / d;
offsets[n] = (sy[n] * sx2 -sxy[n]*sx) / d;
}
if (debug) {
System.out.println("calibratePhotometric() nref="+nref);
for (int n = 0; n < num_sens; n++) {
System.out.println(String.format("%2d: %8.4f %8.6f", n,offsets[n],scales[n]));
}
System.out.println();
double [][] diffs = new double [num_sens][len];
for (int n = 0; n < num_sens; n++) {
Arrays.fill(diffs[n], Double.NaN);
}
for (int i = 0; i < len; i++) if (good_pix[i]) { // if (!Double.isNaN(avg_pix[i])){
for (int n = 0; n < num_sens; n++) {
diffs[n][i] = dpixels[n][i] - (scales[n] * avg_pix[i] + offsets[n]);
}
}
(new ShowDoubleFloatArrays()).showArrays( // out of boundary 15
diffs,
width,
height,
true,
"photometric-err"+nref);
// dpix_orig[n] = dpixels[n].clone();
double [][] corrected = new double [num_sens][len];
for (int n = 0; n < num_sens; n++) {
Arrays.fill(corrected[n], Double.NaN);
for (int i = 0; i < len; i++) if (!Double.isNaN(dpixels[n][i])){
corrected[n][i] = (dpixels[n][i] - offsets[n])/scales[n];
}
}
(new ShowDoubleFloatArrays()).showArrays( // out of boundary 15
corrected,
width,
height,
true,
"photometric-corr"+nref);
}
//max_diff
if (nref < (num_refines-1)) {
for (int i = 0; i < len; i++) if (good_pix[i]) { // !Double.isNaN(avg_pix[i])){
for (int n = 0; n < num_sens; n++) {
double diff = Math.abs(dpixels[n][i] - (scales[n] * avg_pix[i] + offsets[n]));
if (diff > max_diff) {
// dpixels[n][i] = Double.NaN;
good_pix[i] = false;
break;
}
}
}
}
}
double [] offsets_old = ref_scene.getLwirOffsets();
double [] scales_old = ref_scene.getLwirScales();
double [] offsets_new = new double[num_sens];
double [] scales_new = new double[num_sens];
for (int n = 0; n < num_sens; n++) {
scales_new[n] = scales_old[n]/scales[n];
// offsets_new[n] = offsets_old[n] - offsets[n] / scales_old[n];
offsets_new[n] = offsets_old[n] + offsets[n] / scales_old[n];
}
System.out.println("calibratePhotometric() Updated calibration:");
for (int n = 0; n < num_sens; n++) {
System.out.println(String.format("%2d: %8.4f %8.6f", n,offsets_new[n],scales_new[n]));
}
System.out.println();
ref_scene.setLwirOffsets(offsets_new);
ref_scene.setLwirScales (scales_new);
return true;
}
public static ImagePlus renderGPUFromDSI(
final int sensor_mask,
final boolean merge_channels,
......@@ -2182,10 +2351,11 @@ public class QuadCLT extends QuadCLTCPU {
final QuadCLT scene,
final QuadCLT ref_scene, // now - may be null - for testing if scene is rotated ref
final boolean toRGB,
final boolean show_nan,
String suffix,
int threadsMax,
final int debugLevel){
boolean show_nan = toRGB? clt_parameters.imp.show_color_nan : clt_parameters.imp.show_mono_nan;
// boolean show_nan = toRGB? clt_parameters.imp.show_color_nan : clt_parameters.imp.show_mono_nan;
double [][] pXpYD =OpticalFlow.transformToScenePxPyD( // now should work with offset ref_scene
full_woi_in, // final Rectangle [] extra_woi, // show larger than sensor WOI (or null)
disparity_ref, // final double [] disparity_ref, // invalid tiles - NaN in disparity
......
......@@ -151,6 +151,7 @@ public class QuadCLTCPU {
boolean [][] saturation_imp = null; // (near) saturated pixels or null
boolean is_aux = false;
double [] lwir_offsets = null; // per image subtracted values
double [] lwir_scales = null; // per image scales
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
......@@ -261,6 +262,7 @@ public class QuadCLTCPU {
this.is_aux = qParent.is_aux;
// this.is_mono = qParent.is_mono;
this.lwir_offsets = ErsCorrection.clone1d(qParent.lwir_offsets);
this.lwir_scales = ErsCorrection.clone1d(qParent.lwir_scales);
this.lwir_offset = qParent.lwir_offset;
this.lwir_cold_hot = ErsCorrection.clone1d(qParent.lwir_cold_hot);
this.ds_from_main = ErsCorrection.clone2d(qParent.ds_from_main);
......@@ -1477,6 +1479,37 @@ public class QuadCLTCPU {
public boolean isMonochrome() {return geometryCorrection.isMonochrome();} // clt_kernels // USED in lwir
public double getLwirOffset() {return lwir_offset;} // USED in lwir
public boolean isLwirCalibrated() {
return lwir_offsets != null;
}
public double [] getLwirOffsets() {
if (lwir_offsets == null) {
lwir_offsets = new double [getNumSensors()];
}
return lwir_offsets;
}
public double [] getLwirScales() {
if (lwir_scales == null) {
lwir_scales = new double [getNumSensors()];
Arrays.fill(lwir_scales, 1.0);
}
return lwir_scales;
}
public void setLwirOffsets(double [] offsets) {
lwir_offsets = offsets; // will need to update properties!
if (offsets != null) {
double s = 0;
for (double offset:offsets) s+=offset;
lwir_offset = s/offsets.length;
} else {
lwir_offset = Double.NaN;
}
}
public void setLwirScales(double [] scales) {
lwir_scales = scales; // will need to update properties!
}
public double [] getColdHot() { // USED in lwir
return lwir_cold_hot;
......@@ -1668,7 +1701,15 @@ public class QuadCLTCPU {
}
properties.setProperty(prefix+"num_orient", this.num_orient+"");
properties.setProperty(prefix+"num_accum", this.num_accum+"");
if (this.lwir_offsets != null) {
properties.setProperty(prefix+"lwir_offsets",
IntersceneMatchParameters.doublesToString(this.lwir_offsets));
}
if (this.lwir_scales != null) {
properties.setProperty(prefix+"lwir_scales",
IntersceneMatchParameters.doublesToString(this.lwir_scales));
}
}
......@@ -1697,7 +1738,19 @@ public class QuadCLTCPU {
this.num_accum = Integer.parseInt(other_properties.getProperty(other_prefix+"num_accum"));
properties.setProperty(this_prefix+"num_accum", this.num_accum+"");
}
// copy offsets and scales
if (other_properties.getProperty(other_prefix+"lwir_offsets")!=null) {
this.lwir_offsets= IntersceneMatchParameters.StringToDoubles(
other_properties.getProperty(other_prefix+"lwir_offsets"),0);
properties.setProperty(this_prefix+"lwir_offsets",
IntersceneMatchParameters.doublesToString(this.lwir_offsets));
}
if (other_properties.getProperty(other_prefix+"lwir_scales")!=null) {
this.lwir_scales= IntersceneMatchParameters.StringToDoubles(
other_properties.getProperty(other_prefix+"lwir_scales"),0);
properties.setProperty(this_prefix+"lwir_scales",
IntersceneMatchParameters.doublesToString(this.lwir_scales));
}
/*
......@@ -1803,8 +1856,24 @@ public class QuadCLTCPU {
geometryCorrection.setRigOffsetFromProperies(prefix, properties);
}
// inter-frame properties only make sense for, well, scenes. So they will only be read
if (properties.getProperty(prefix+"num_orient")!=null) this.num_orient=Integer.parseInt(properties.getProperty(prefix+"num_orient"));
if (properties.getProperty(prefix+"num_accum")!=null) this.num_accum= Integer.parseInt(properties.getProperty(prefix+"num_accum"));
if (properties.getProperty(prefix+"num_orient")!=null) {
this.num_orient=Integer.parseInt(properties.getProperty(prefix+"num_orient"));
}
if (properties.getProperty(prefix+"num_accum")!=null) {
this.num_accum= Integer.parseInt(properties.getProperty(prefix+"num_accum"));
}
if (properties.getProperty(prefix+"lwir_offsets")!=null) {
this.lwir_offsets= IntersceneMatchParameters.StringToDoubles(
properties.getProperty(prefix+"lwir_offsets"),0);
}
if (properties.getProperty(prefix+"lwir_scales")!=null) {
this.lwir_scales= IntersceneMatchParameters.StringToDoubles(
properties.getProperty(prefix+"lwir_scales"),0);
}
}
public void setKernelImageFile(ImagePlus img_kernels){ // not used in lwir
......@@ -4889,6 +4958,7 @@ public class QuadCLTCPU {
boolean lwir_subtract_dc = colorProcParameters.lwir_subtract_dc;
boolean lwir_eq_chn = colorProcParameters.lwir_eq_chn;
boolean correct_vignetting = colorProcParameters.correct_vignetting;
boolean recalc_lwir_offsets = false;
final Thread[] threads = ImageDtt.newThreadArray(threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
......@@ -5176,23 +5246,36 @@ public class QuadCLTCPU {
debugLevel);
}
if (is_lwir && (lwir_subtract_dc || lwir_eq_chn)) {
this.lwir_offsets = channelLwirEqualize(
channelFiles,
imp_srcs,
lwir_subtract_dc, // boolean remove_dc,
set_name, // just for debug messages == setNames.get(nSet)
threadsMax,
debugLevel);
int num_avg = 0;
this.lwir_offset = 0.0;
for (int srcChannel=0; srcChannel < channelFiles.length; srcChannel++){
int nFile=channelFiles[srcChannel];
if (nFile >=0){
this.lwir_offset += this.lwir_offsets[srcChannel];
num_avg++;
}
}
this.lwir_offset /= num_avg;
if (recalc_lwir_offsets || !isLwirCalibrated()) {
// this.lwir_offsets =
setLwirOffsets(
channelLwirEqualize( // now only calculates offsets, does not apply
channelFiles,
imp_srcs,
lwir_subtract_dc, // boolean remove_dc,
set_name, // just for debug messages == setNames.get(nSet)
threadsMax,
debugLevel));
int num_avg = 0;
this.lwir_offset = 0.0;
for (int srcChannel=0; srcChannel < channelFiles.length; srcChannel++){
int nFile=channelFiles[srcChannel];
if (nFile >=0){
this.lwir_offset += this.lwir_offsets[srcChannel];
num_avg++;
}
}
this.lwir_offset /= num_avg;
}
double [] offsets = getLwirOffsets();
double [] scales = getLwirScales();
channelLwirApplyEqualize( // now apply (was part of channelLwirEqualize() )
channelFiles, // int [] channelFiles,
imp_srcs, // ImagePlus [] imp_srcs,
offsets, // double [] offsets,
scales, // double [] scales,
threadsMax,
debugLevel);
}
// 08/12/2020 common part moved here, from getRigImageStacks()
image_name = (String) imp_srcs[0].getProperty("name");
......@@ -5686,6 +5769,7 @@ public class QuadCLTCPU {
}
}
}
public static double [] channelLwirEqualize( // USED in lwir
int [] channelFiles,
ImagePlus [] imp_srcs,
......@@ -5705,11 +5789,7 @@ public class QuadCLTCPU {
public void run() {
double [] wnd_x;
double [] wnd_y;
// for (int srcChannel=0; srcChannel<channelFiles.length; srcChannel++){
for (int srcChannel = ai.getAndIncrement(); srcChannel < channelFiles.length; srcChannel = ai.getAndIncrement()) {
// for (int srcChannel=0; srcChannel < channelFiles.length; srcChannel++){
int nFile=channelFiles[srcChannel];
if (nFile >=0){
avr_pix[srcChannel][0] = 0.0;
......@@ -5717,18 +5797,14 @@ public class QuadCLTCPU {
float [] pixels=(float []) imp_srcs[srcChannel].getProcessor().getPixels();
int width = imp_srcs[srcChannel].getWidth();
int height = imp_srcs[srcChannel].getHeight();
// if (wnd_x.length != width) {
wnd_x = new double[width];
for (int i = 0; i < width; i++) {
wnd_x[i] = 0.5 - 0.5*Math.cos(2*Math.PI * (i+1) / (width + 1));
}
// }
// if (wnd_y.length != height) {
wnd_y = new double[height];
for (int i = 0; i < height; i++) {
wnd_y[i] = 0.5 - 0.5*Math.cos(2*Math.PI * (i+1) / (height + 1));
}
// }
int indx = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
......@@ -5737,8 +5813,6 @@ public class QuadCLTCPU {
avr_pix[srcChannel][1] += w;
}
}
// total_s += avr_pix[srcChannel][0];
// total_w += avr_pix[srcChannel][1];
atotal_s.accumulate(avr_pix[srcChannel][0]);
atotal_w.accumulate(avr_pix[srcChannel][1]);
avr_pix[srcChannel][0]/=avr_pix[srcChannel][1]; // weighted average
......@@ -5748,7 +5822,6 @@ public class QuadCLTCPU {
};
}
ImageDtt.startAndJoin(threads);
// double avg = total_s/total_w;
double avg = atotal_s.get()/atotal_w.get();
if (!remove_dc) { // not used in lwir
......@@ -5766,12 +5839,41 @@ public class QuadCLTCPU {
for (int srcChannel = ai.getAndIncrement(); srcChannel < channelFiles.length; srcChannel = ai.getAndIncrement()) {
int nFile=channelFiles[srcChannel];
if (nFile >=0) {
// offsets[srcChannel]= (avr_pix[srcChannel][0] - (remove_dc ? 0.0: avg));
offsets[srcChannel]= avr_pix[srcChannel][0];
// float fd = (float)offsets[srcChannel];
// float [] pixels = (float []) imp_srcs[srcChannel].getProcessor().getPixels();
// for (int i = 0; i < pixels.length; i++) {
// pixels[i] -= fd;
// }
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return offsets;
}
public static void channelLwirApplyEqualize(
int [] channelFiles,
ImagePlus [] imp_srcs,
double [] offsets,
double [] scales,
final int threadsMax,
int debugLevel){
final Thread[] threads = ImageDtt.newThreadArray(threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int srcChannel = ai.getAndIncrement(); srcChannel < channelFiles.length; srcChannel = ai.getAndIncrement()) {
int nFile=channelFiles[srcChannel];
if (nFile >=0) {
float fd = (float)offsets[srcChannel];
float fscale = (float) scales[srcChannel];
float [] pixels = (float []) imp_srcs[srcChannel].getProcessor().getPixels();
for (int i = 0; i < pixels.length; i++) {
pixels[i] -= fd;
pixels[i] = (pixels[i] - fd) * fscale;
}
}
}
......@@ -5779,9 +5881,10 @@ public class QuadCLTCPU {
};
}
ImageDtt.startAndJoin(threads);
return offsets;
}
}
// public ImagePlus [] processCLTQuadCorrCPU( // USED in lwir
public void processCLTQuadCorrCPU( // USED in lwir
// ImagePlus [] imp_quad, // should have properties "name"(base for saving results), "channel","path"
......
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