Commit 96a9bb0d authored by Andrey Filippov's avatar Andrey Filippov

Row/col correction

parent 86e73701
......@@ -251,6 +251,7 @@ public class Cuas {
double [][] ref_combo_dsi, // DSI data for the reference scene (or null to read it from file)
boolean condition_dsi,
int sensor_mask, // -1 - all;
boolean new_average,
int debugLevel) {
//TODO: verify it still works with new reference_scene
boolean batch_run = clt_parameters.batch_run;
......@@ -422,8 +423,10 @@ public class Cuas {
int tilesX = center_CLT.getTilesX();
int tilesY = center_CLT.getTilesY();
double dts = center_CLT.getTimeStamp();
CuasData cuasData = null;
// here we need cumulative parent data
CuasData cuasData = CuasData.getCuasData( // may result in null !
if (!new_average) {
cuasData = CuasData.getCuasData( // may result in null !
true, // boolean try_cumul, // and save as such if only old style existed
cumulative_parent_dir_path, // String full_path, // ends with /vxx
num_colors, // int num_colors, // only used if restored from tiff, ignored for .cuas
......@@ -437,6 +440,7 @@ public class Cuas {
System.out.println("createCenterClt(): FAILED to read cumulative parent data from "+cumulative_parent_dir_path);
}
}
}
CuasData newCuasData = getTDComboSceneSequence(
clt_parameters, // CLTParameters clt_parameters,
......
......@@ -2880,7 +2880,6 @@ public class ImageDttCPU {
}
// TODO: use correction after disparity applied (to work for large disparity values)
if (fine_corr != null){
for (int ip = 0; ip < centersXY.length; ip++){
double [] tXY = geometryCorrection.getRelativeCoords(centersXY[ip]);
for (int d = 0; d <2; d++) {
......@@ -2909,9 +2908,6 @@ public class ImageDttCPU {
for (int i = 0; i < numSensors; i++) {
clt_data[i][ncol][tileY][tileX] = new double [4][];
// if ((i==9) && (tileY>=18) && (tileY<=20) && (tileX >= 23) && (tileX <= 29)) {
// System.out.println("sensor="+i+", tileY="+tileY+", tileX="+tileX);
// }
// Extract image tiles and kernels, correct aberrations, return (ut do not apply) fractional shifts
fract_shiftsXY[i] = extract_correct_tile( // return a pair of residual offsets
image_data[i],
......
......@@ -666,9 +666,14 @@ min_str_neib_fpn 0.35
public boolean cuas_step = true; // recalculate template image after each fitting step
public boolean cuas_subtract_fpn= true; // Subtract FPN
public boolean cuas_calc_fpn = false; // Recalculate+save FPN unconditionally, if false - try to read saved one
public boolean cuas_calc_fpn = false; // Recalculate+save FPN unconditionally, if false - try to read saved one first
public double cuas_rot_period = 175.0; // rotation period of te gimbal mount (in scenes)
public boolean cuas_subtract_rowcol= true; // Subtract row/column noise
public boolean cuas_calc_rowcol= true; // Recalculate+save row/column noise, if false - try to read saved one first
public double cuas_um_sigma = 20.0; // Apply Unsharp Mask filter sigma when calculating row/column noise
public double cuas_max_abs_rowcol = 100.0; // consider pixels with abs(UM difference) does not exceed this value
public double cuas_outliers_rowcol = 0.001; // scale weight of the outliers with high difference (to prevent undefined values
public boolean cuas_reset_first= false; // Reset average in first scene (for large diffirence in unfinished row/col)
public boolean cuas_debug = false; // save debug images (and show them if not in batch mode)
public boolean cuas_step_debug = false; // save debug images during per-step cuas recalculation (and show them if not in batch mode)
......@@ -2000,12 +2005,27 @@ min_str_neib_fpn 0.35
"Filter tile CLT variants that keep fraction of the total weight.");
gd.addCheckbox ("Recalculate after each tuning step", this.cuas_step,
"Recalciulate correlation pattern after each position/orientation and disparity adjustment step.");
gd.addMessage("=== Subtract FPN ===");
gd.addCheckbox ("Subtract FPN", this.cuas_subtract_fpn,
"Subtract FPN from the channel images.");
gd.addCheckbox ("(Re)calculate FPN", this.cuas_calc_fpn,
"Recalculate+save FPN unconditionally, if false - try to read saved one.");
gd.addNumericField("Rotation period", this.cuas_rot_period, 5,7,"scene periods",
"Used for averaging FPN for integer number of rotation periods. TODO: calculate from the actual rotation.");
gd.addMessage("=== Row/column noise (on top of the FPN) ===");
gd.addCheckbox ("Subtract row/column noise", this.cuas_subtract_rowcol,
"Subtract per-scene row/column noise (on top of the per scene sequence FPN).");
gd.addCheckbox ("(Re)calculate row/column noise", this.cuas_calc_rowcol,
"Recalculate per-scene row column noise even if it exists. If false, try to read first.");
gd.addNumericField("Row/column unsharp mask filter", this.cuas_um_sigma, 5,7,"pix",
"Apply Unsharp mask filter to the difference between individual scenes and per-sequence FPN before calculating row/column noise.");
gd.addNumericField("Row/column maximal difference", this.cuas_max_abs_rowcol, 5,7,"counts",
"Consider pixels were abs(UM difference) does not exceed this value during row/column noise calcualtion.");
gd.addNumericField("Row/column scale outliers", this.cuas_outliers_rowcol, 5,7,"x",
"Scale weight of the outliers with high difference than above (to prevent undefined values).");
gd.addCheckbox ("Reset average on first sequence", this.cuas_reset_first,
"Reset average in first scene (for large diffirence in unfinished row/col.");
gd.addMessage("=== Debug ===");
gd.addCheckbox ("Save/show debug images", this.cuas_debug,
"Save CUAS-related debug images and show them in non-batch mode.");
......@@ -2912,6 +2932,13 @@ min_str_neib_fpn 0.35
this.cuas_calc_fpn = gd.getNextBoolean();
this.cuas_rot_period = gd.getNextNumber();
this.cuas_subtract_rowcol = gd.getNextBoolean();
this.cuas_calc_rowcol = gd.getNextBoolean();
this.cuas_um_sigma = gd.getNextNumber();
this.cuas_max_abs_rowcol = gd.getNextNumber();
this.cuas_outliers_rowcol = gd.getNextNumber();
this.cuas_reset_first = gd.getNextBoolean();
this.cuas_debug = gd.getNextBoolean();
this.cuas_step_debug = gd.getNextBoolean();
......@@ -3745,6 +3772,12 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"cuas_calc_fpn", this.cuas_calc_fpn+""); // boolean
properties.setProperty(prefix+"cuas_rot_period", this.cuas_rot_period+""); // double
properties.setProperty(prefix+"cuas_subtract_rowcol", this.cuas_subtract_rowcol+"");// boolean
properties.setProperty(prefix+"cuas_calc_rowcol", this.cuas_calc_rowcol+""); // boolean
properties.setProperty(prefix+"cuas_um_sigma", this.cuas_um_sigma+""); // double
properties.setProperty(prefix+"cuas_max_abs_rowcol", this.cuas_max_abs_rowcol+""); // double
properties.setProperty(prefix+"cuas_outliers_rowcol", this.cuas_outliers_rowcol+"");// double
properties.setProperty(prefix+"cuas_reset_first", this.cuas_reset_first+""); // boolean
properties.setProperty(prefix+"cuas_debug", this.cuas_debug+""); // boolean
properties.setProperty(prefix+"cuas_step_debug", this.cuas_step_debug+""); // boolean
......@@ -4552,6 +4585,13 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"cuas_calc_fpn")!=null) this.cuas_calc_fpn=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_calc_fpn"));
if (properties.getProperty(prefix+"cuas_rot_period")!=null) this.cuas_rot_period=Double.parseDouble(properties.getProperty(prefix+"cuas_rot_period"));
if (properties.getProperty(prefix+"cuas_subtract_rowcol")!=null) this.cuas_subtract_rowcol=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_subtract_rowcol"));
if (properties.getProperty(prefix+"cuas_calc_rowcol")!=null) this.cuas_calc_rowcol=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_calc_rowcol"));
if (properties.getProperty(prefix+"cuas_um_sigma")!=null) this.cuas_um_sigma=Double.parseDouble(properties.getProperty(prefix+"cuas_um_sigma"));
if (properties.getProperty(prefix+"cuas_max_abs_rowcol")!=null) this.cuas_max_abs_rowcol=Double.parseDouble(properties.getProperty(prefix+"cuas_max_abs_rowcol"));
if (properties.getProperty(prefix+"cuas_outliers_rowcol")!=null) this.cuas_outliers_rowcol=Double.parseDouble(properties.getProperty(prefix+"cuas_outliers_rowcol"));
if (properties.getProperty(prefix+"cuas_reset_first")!=null) this.cuas_reset_first=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_reset_first"));
if (properties.getProperty(prefix+"cuas_debug")!=null) this.cuas_debug=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_debug"));
if (properties.getProperty(prefix+"cuas_step_debug")!=null) this.cuas_step_debug=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_step_debug"));
......@@ -5360,6 +5400,13 @@ min_str_neib_fpn 0.35
imp.cuas_calc_fpn = this.cuas_calc_fpn;
imp.cuas_rot_period = this.cuas_rot_period;
imp.cuas_subtract_rowcol = this.cuas_subtract_rowcol;
imp.cuas_calc_rowcol = this.cuas_calc_rowcol;
imp.cuas_um_sigma = this.cuas_um_sigma;
imp.cuas_max_abs_rowcol = this.cuas_max_abs_rowcol;
imp.cuas_outliers_rowcol = this.cuas_outliers_rowcol;
imp.cuas_reset_first = this.cuas_reset_first;
imp.cuas_debug = this.cuas_debug;
imp.cuas_step_debug = this.cuas_step_debug;
......
......@@ -4846,8 +4846,16 @@ public class OpticalFlow {
boolean cuas_subtract_fpn = clt_parameters.imp.cuas_subtract_fpn;
boolean cuas_calc_fpn = clt_parameters.imp.cuas_calc_fpn;
double cuas_rot_period = clt_parameters.imp.cuas_rot_period;
boolean cuas_subtract_rowcol=clt_parameters.imp.cuas_subtract_rowcol;// Subtract row/column noise
boolean cuas_calc_rowcol= clt_parameters.imp.cuas_calc_rowcol; // Recalculate+save row/column noise, if false - try to read saved one first
double cuas_um_sigma = clt_parameters.imp.cuas_um_sigma; // Apply Unsharp Mask filter sigma when calculating row/column noise
double cuas_max_abs_rowcol= clt_parameters.imp.cuas_max_abs_rowcol; // consider pixels with abs(UM difference) does not exceed this value
double cuas_outliers_rowcol=clt_parameters.imp.cuas_outliers_rowcol;// scale weight of the outliers with high difference (to prevent undefined values
boolean cuas_debug = clt_parameters.imp.cuas_debug; // save debug images (and show them if not in batch mode)
boolean cuas_step_debug = clt_parameters.imp.cuas_step_debug;
boolean cuas_reset_first=clt_parameters.imp.cuas_reset_first && first_in_series;
double [] ref_blue_sky = null; // turn off "lma" in the ML output
......@@ -5163,8 +5171,9 @@ public class OpticalFlow {
} // while (blue_sky == null)
if ((center_CLT != null) && center_CLT.hasCenterClt()) {
int fpn_width = center_CLT.getTilesX() * center_CLT.getTileSize(); // see if center_CLT can be used
if (cuas_subtract_fpn) {
double [][][] fpn = null;
boolean show_fpn = cuas_debug && !clt_parameters.batch_run; //
if (cuas_subtract_fpn) {
boolean changed = quadCLT_main.isPhotometricUpdatedAndReset();
if (changed) {
System.out.println ("00.re-spawning with updated photogrammetric calibration of reference scene.");
......@@ -5184,8 +5193,7 @@ public class OpticalFlow {
debugLevel-2);
}
}
double [][][] fpn = center_CLT.getCorrectionFPN().readImageFPN ( -1); // int sens_mask);
fpn = center_CLT.getCorrectionFPN().readImageFPN ( -1); // int sens_mask);
if ((fpn == null) || cuas_calc_fpn) {
if (debugLevel >-3) {
System.out.println("Calculating FPN.");
......@@ -5199,16 +5207,17 @@ public class OpticalFlow {
rot_range, // final int [] range, // required
-1, // final int sensor_mask,
debugLevel); // final int debugLevel)
int dbg_sens = 12;
int dbg_sens = -12; // disable testing
if (cuas_debug && (dbg_sens >= 0)) {
double um_sigma_fpn = 10.0;
center_CLT.getCorrectionFPN().debugFPN(
quadCLTs, // QuadCLT [] quadCLTs,
fpn, // double [][][] fpn,
rot_range, // int [] range,
dbg_sens, // int nsens,
um_sigma_fpn, // double um_sigma = 10.0;
cuas_um_sigma, // double um_sigma = 10.0;
cuas_max_abs_rowcol, // double max_abs, // = 100.0;
cuas_outliers_rowcol,// double weight_outlier, // = 0.001;
show_fpn); // boolean show) {
}
......@@ -5226,6 +5235,7 @@ public class OpticalFlow {
center_CLT.getCorrectionFPN().setApplyFPN(
quadCLTs, // QuadCLT [] quadCLTs,
fpn);// double [][][] fpn)
} else {
if (debugLevel >-3) {
System.out.println("Skipping FPN.");
......@@ -5235,6 +5245,46 @@ public class OpticalFlow {
quadCLTs, // QuadCLT [] quadCLTs,
null);// double [][][] fpn)
}
if (cuas_subtract_rowcol) {
/// read/calculate Row/Column noise correction
boolean is_new = false;
double [][][][] row_col = null;
if (!cuas_calc_rowcol) {
if (debugLevel >-3) {
System.out.println("Reading row/column noise per-scene data.");
}
row_col = center_CLT.getCorrectionFPN().readImageRowCol();
}
if (row_col == null) {
if (debugLevel >-3) {
System.out.println("Calculating row/column noise per-scene data.");
}
row_col= CorrectionFPN.calculateRowCol(
quadCLTs, // final QuadCLT [] quadCLTs,
fpn, // final double [][][] fpn, // if null - already applied
fpn_width, // final int width,
cuas_um_sigma, // final double um_sigma,
cuas_max_abs_rowcol, // final double max_abs, // = 100.0;
cuas_outliers_rowcol); // final double weight_outlier // = 0.001;)
is_new = (row_col != null);
}
center_CLT.getCorrectionFPN().saveShowRowCol(
row_col[0], // final double [][][] rows, // [scene][sensor][width]
row_col[1], // final double [][][] cols, // [scene][sensor][height]
is_new, //final boolean save,
show_fpn); // final boolean show)
// TODO: apply to all scenes here ! *************************************
CorrectionFPN.setApplyRowCol(
quadCLTs, // final QuadCLT [] scenes,
row_col[0], //final double [][][] rows,
row_col[1]); // final double [][][] cols )
} else { // reset row/col correction
CorrectionFPN.setApplyRowCol(
quadCLTs, // final QuadCLT [] scenes,
null, //final double [][][] rows,
null); // final double [][][] cols )
}
}
......@@ -5422,7 +5472,7 @@ public class OpticalFlow {
} else {// if (build_orientations) {
if (center_CLT != null) {
if (!reuse_video) { // reuse_video only uses reference scene
boolean changed = quadCLTs[ref_index].isPhotometricUpdatedAndReset();
boolean changed = false; // quadCLTs[ref_index].isPhotometricUpdatedAndReset(); //*** It should use quadCLT_main.isPhotometricUpdatedAndReset()
if (changed) {
System.out.println ("0.re-spawning with updated photogrammetric calibration of reference scene.");
} else {
......@@ -5970,6 +6020,8 @@ public class OpticalFlow {
/*
QuadCLT center_CLT = QuadCLT.restoreCenterClt(quadCLTs[ref_index]); // QuadCLT ref_clt);
*/
// if (cuas_reset_first)
boolean dbg_created=false;
int sensor_mask_clt = -1; // all
if (center_CLT == null) {
......@@ -5985,6 +6037,7 @@ public class OpticalFlow {
combo_dsn_final, // double [][] ref_dsi, // DSI data for the reference scene (or null to read it from file)
condition_dsi, // boolean condition_dsi,
sensor_mask_clt, // int sensor_mask, // -1 - all;
true, // boolean // new_average,
debugLevel); // int debugLevel)
if (cuas_centers != null) {
cuas_centers[1] = center_CLT.getImagePath();
......@@ -6009,6 +6062,7 @@ public class OpticalFlow {
combo_dsn_final, // double [][] ref_dsi, // DSI data for the reference scene (or null to read it from file)
condition_dsi, // boolean condition_dsi,
sensor_mask_clt, // int sensor_mask, // -1 - all;
cuas_reset_first, // boolean // new_average,
debugLevel); // int debugLevel)
if (cuas_centers != null) {
cuas_centers[1] = center_CLT.getImagePath();
......
......@@ -139,6 +139,7 @@ public class QuadCLTCPU {
public static final String CENTER_DIR_SUFFIX = "-CENTER";
public static final String CENTER_CLT_SUFFIX = "-CLT";
public static final String CENTER_FPN_SUFFIX = "-FPN";
public static final String CENTER_ROWCOL_SUFFIX = "-ROWCOL";
// public GPUTileProcessor.GpuQuad gpuQuad = null;
......@@ -174,6 +175,10 @@ public class QuadCLTCPU {
public double [][][] image_fpn_applied = null; // [channel][color][pixel] // when applying different instance, the old will be unapplied
public double [][] image_row_avg = null; //[nsens][width] integrated by columns, lwir-only (single-color)
public double [][] image_col_avg = null; //[nsens][height] integrated by rows, lwir-only (single-color)
public double [][] image_row_avg_applied = null; //[nsens][width] integrated by columns, lwir-only (single-color)
public double [][] image_col_avg_applied = null; //[nsens][height] integrated by rows, lwir-only (single-color)
boolean new_image_data = false;
boolean [][] saturation_imp = null; // (near) saturated pixels or null
boolean is_aux = false;
......@@ -6301,6 +6306,15 @@ public class QuadCLTCPU {
if ((imp == null) || (imp.getTitle() == null) || (imp.getTitle().equals(""))) {
return null;
}
return readFloatArray(
imp, // ImagePlus imp,
num_slices, //int num_slices, // (0 - all)
wh); // int [] wh)
/*
ImageStack imageStack = imp.getStack();
int nChn=imageStack.getSize();
if ((num_slices > 0) && (num_slices < nChn)) {
......@@ -6315,6 +6329,75 @@ public class QuadCLTCPU {
wh[1] = imp.getHeight();
}
return result;
*/
}
public static double [][] readDoubleArray(
ImagePlus imp,
int num_slices, // (0 - all)
int [] wh) {
float [][] fdata = readFloatArray(
imp, // ImagePlus imp,
num_slices, // int num_slices, // (0 - all)
wh); // int [] wh)
if (fdata == null) {
return null;
}
double [][] result = new double [fdata.length][];
for (int n = 0; n < fdata.length; n++) if (fdata[n]!=null) {
result[n] = new double [fdata[n].length];
for (int i = 0; i < fdata[n].length; i++) {
result[n][i] = fdata[n][i];
}
}
return result;
}
public static float [][] readFloatArray(
ImagePlus imp,
int num_slices, // (0 - all)
int [] wh) {
if ((imp == null) || (imp.getTitle() == null) || (imp.getTitle().equals(""))) {
return null;
}
ImageStack imageStack = imp.getStack();
int nChn=imageStack.getSize();
if ((num_slices > 0) && (num_slices < nChn)) {
nChn = num_slices;
}
float [][] result = new float [nChn][];
for (int n = 0; n < nChn; n++) {
result[n] = (float[]) imageStack.getPixels(n + 1);
}
if (wh != null) {
wh[0] = imp.getWidth();
wh[1] = imp.getHeight();
}
return result;
}
public ImagePlus readImagePlusFromModelDirectory(
String suffix)
{
// String x3d_path = getX3dDirectory();
String x3d_path = readX3dDirectory(correctionsParameters.getModelName(image_name));
String file_name = image_name + suffix;
String file_path = x3d_path + Prefs.getFileSeparator() + file_name + ".tiff";
ImagePlus imp = null;
try {
imp = new ImagePlus(file_path);
} catch (Exception e) {
System.out.println ("Failed to open "+file_path+", maybe will generate it");
}
if ((imp == null) || (imp.getTitle() == null) || (imp.getTitle().equals(""))) {
return null;
}
return imp;
}
......@@ -6487,9 +6570,6 @@ public class QuadCLTCPU {
return image_data;
}
public double [][][] getImageFpnApplied(){
return image_fpn_applied;
}
public void setImageData(double [][][] data) {
image_data = data;
......@@ -9920,6 +10000,52 @@ public class QuadCLTCPU {
this.image_fpn = fpn;
}
public void resetRowCol() {
setRowCol(null,null);
}
public void setRowCol(
double [][] row,
double [][] col) {
image_row_avg = row;
image_col_avg = col;
}
public double [][] getRowCorr(){
return image_row_avg;
}
public double [][] getColCorr(){
return image_col_avg;
}
public double [][] getRowApplied(){
return image_row_avg_applied;
}
public double [][] getColApplied(){
return image_col_avg_applied;
}
public void setRowColApplied(
double [][] row,
double [][] col) {
image_row_avg_applied = row;
image_col_avg_applied = col;
}
public boolean rowColDiffers(
double [][] row,
double [][] col) {
return (image_row_avg_applied != row) || (image_col_avg_applied != col);
}
public boolean rowColDiffers() {
return rowColDiffers(
image_row_avg, // double [][] row,
image_col_avg); // double [][] col)
}
public void processCLTQuadCorrs( // not used in lwir
CLTParameters clt_parameters,
......@@ -10005,6 +10131,12 @@ public class QuadCLTCPU {
public void applyFPN() {
getCorrectionFPN().applyFPN(this.image_fpn);
}
public void applyRowCol() {
CorrectionFPN.applyRowCol(
(QuadCLT) this, //final QuadCLT scene,
getRowCorr(), // final double [][] row,
getColCorr()); // final double [][] col )
}
public void processCLTQuadCorrsTestERS(
......
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