Commit 5de61cce authored by Andrey Filippov's avatar Andrey Filippov

improving/fixing bugs in the sensors calibration.

parent 9230dca4
......@@ -515,6 +515,7 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
0.3, // public double weightBad = 0.3; // reduce contrast of bad nodes
0.05, // public double weightWorst = 0.05; // reduce contrast of bad, local worst nodes
0.1, // double badNodeThreshold=0.1; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
0.2, // public double badNodeThresholdLWIR=0.2; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
1, // int maxBadNeighb; // maximal number of bad nodes around the corrected one to fix
10, // int minimalValidNodes
1, // int weightMultiImageMode=1; // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set)
......@@ -1037,6 +1038,7 @@ if (MORE_BUTTONS) {
addButton("Import Subsystem", panelLWIR,color_configure);
addButton("Select LWIR grids", panelLWIR,color_configure);
addButton("Grid offset", panelLWIR,color_process);
addButton("EO Offsets", panelLWIR,color_process);
addButton("LWIR to EO", panelLWIR,color_process);
addButton("Manual hint", panelLWIR,color_configure);
......@@ -9420,6 +9422,13 @@ if (MORE_BUTTONS) {
offsetGrids(0, 0, null, null);
return;
}
/* ======================================================================== */
if (label.equals("EO Offsets")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EOoffsets();
return;
}
/* ======================================================================== */
if (label.equals("LWIR to EO")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
......@@ -9435,6 +9444,141 @@ if (MORE_BUTTONS) {
}
/* ===== Other methods ==================================================== */
//();
public boolean EOoffsets() {
if (LENS_DISTORTIONS == null) {
System.out.println("LENS_DISTORTIONS is null");
return false;
}
if (PATTERN_PARAMETERS == null) {
System.out.println("PATTERN_PARAMETERS is null");
return false;
}
DistortionCalibrationData dcd = LENS_DISTORTIONS.getDistortionCalibrationData();
if (dcd == null) {
dcd = DISTORTION_CALIBRATION_DATA;
}
if (dcd == null) {
System.out.println("dcd is null");
return false;
}
int min_set = 0;
int max_set = dcd.getNumSets()-1;
double maximalRMS = 1.0;
double maximalGridErr = 0.2;
boolean adjustAttitude = true;
// int extra_search = 2;
// double sigma = 5;
GenericDialog gd = new GenericDialog("Initial alignment of the secondary camera to the reference one");
// gd.addMessage("This command used Fitting Strategy[last] that should be set with all parameters but\n"+
// "GXYZ0 and GXYZ1 are set to 'fixed', and GXYZ0 and GXYZ1 are set to 'individual'.\n"+
// "Each selected set should already have GXYZ set correctly (e.g. by reference cameras)");
gd.addMessage("This command uses Fitting Strategy[last] and set parameters but\n"+
"GXYZ0 and GXYZ1 to 'individual', all others - to 'fixed'.\n"+
"Each selected set should already have GXYZ set correctly (e.g. by reference cameras)");
gd.addNumericField("Image set start", min_set, 0);
gd.addNumericField("Image set last", max_set, 0);
gd.addNumericField("Maximal RMS to accept", maximalRMS, 3 ,7, "");
gd.addNumericField("Maximal grid errot to accept", maximalGridErr, 3 ,7, "");
gd.addCheckbox("Adjust set attitude after grid offsets", adjustAttitude);
// gd.addNumericField("Extra search for the non-LMA method", extra_search, 0);
// gd.addNumericField("Sigma for the non-LMA method", sigma, 3 ,7, "");
gd.showDialog();
if (gd.wasCanceled()) return false;
min_set = (int) gd.getNextNumber();
max_set = (int) gd.getNextNumber();
maximalRMS = gd.getNextNumber();
maximalGridErr = gd.getNextNumber();
// extra_search = (int) gd.getNextNumber();
// sigma = gd.getNextNumber();
adjustAttitude = gd.getNextBoolean();
if (!dcd.hasSmallSensors()) {
String msg="This system does not have any LWIR or other dependent sub-cameras";
IJ.showMessage("Error",msg);
return false;
}
for (int num_set = min_set; num_set <=max_set; num_set++) if
((dcd.gIS[num_set] != null) && (dcd.gIS[num_set].imageSet != null)) {
ArrayList<Integer> num_imgs_list = new ArrayList<Integer>();
for (int nc = 0; nc < dcd.getNumChannels(); nc++) {
if (dcd.gIS[num_set].imageSet[nc]!= null) {
int num_img = dcd.gIS[num_set].imageSet[nc].imgNumber;
if (dcd.isSmallSensor(num_img)) {
continue;
}
double [] stats = new double [3];
int [] uvr = LENS_DISTORTIONS.findImageGridOffset(
num_img, // image num
-1, // use last series int ser_num, // number of series to reprogram
true, // boolean adjust_attitude, // true for eo, false for lwir (uses exact attitude from eo)
true, // boolean even, For first time - use parameter and parity of uv_rot
PATTERN_PARAMETERS,
stats); // rms, dU, dV
if (uvr == null) {
if (DEBUG_LEVEL > 0) {
System.out.println("LMA failed for set = "+ num_set +", channel = "+nc);
}
continue;
}
if (DEBUG_LEVEL > 0) {
System.out.println(num_img+ "("+num_set+"."+nc+"): uv_shift = "+uvr[0]+":"+uvr[1]);
System.out.println(num_img+ "("+num_set+"."+nc+"): errors: rms= "+stats[0]+", dU="+stats[1]+", dV="+stats[2]);
}
if ((maximalRMS > 0.0) && (stats[0] >maximalRMS)) {
if (DEBUG_LEVEL > 0) {
System.out.println("LMA RMS for set = "+ num_set +", channel = "+nc+" is too high: "+stats[0]+" > "+maximalRMS);
}
continue;
}
double grid_err =Math.max(Math.abs(stats[1]), Math.abs(stats[2]));
if ((maximalGridErr > 0.0) && (grid_err > maximalGridErr)) {
if (DEBUG_LEVEL > 0) {
System.out.println("Adjusted grid error for set = "+ num_set +", channel = "+nc+" is too high: "+
grid_err+" > "+maximalGridErr);
}
continue;
}
num_imgs_list.add(num_img);
if ((uvr[0] == 0) || (uvr[1] == 0)) {
if (DEBUG_LEVEL > 0) {
System.out.println("Grid alignment for set = "+ num_set +", channel = "+nc+" was correct, nothing to do");
}
continue;
}
int [] uv_shift_rot = {uvr[0],uvr[1],0};
// int [] new_uv_shift_rots =
dcd.offsetGrid(
num_img, // int img_num,
uv_shift_rot,
PATTERN_PARAMETERS);
if (DEBUG_LEVEL > 0) {
System.out.println("Grid for set = "+ num_set +", channel = "+nc+" adjusted by "+uvr[0]+":"+uvr[1]);
}
// num_imgs_list.add(num_img);
}
}
if (adjustAttitude && !num_imgs_list.isEmpty()) {
int [] num_imgs = new int[num_imgs_list.size()];
for (int i = 0; i < num_imgs.length; i++) {
num_imgs[i] = num_imgs_list.get(i);
}
LENS_DISTORTIONS.adjustAttitudeAfterOffset(
num_imgs,
-1, // number of series to reprogram
PATTERN_PARAMETERS);
}
}
return true;
}
public boolean lwirToEo() {
if (LENS_DISTORTIONS == null) {
......@@ -71,6 +71,8 @@ import ij.text.TextWindow;
public static final int INDEX_B = 7;
public static final double SMALL_FRACTION = 0.8; // consider sensor to be a "small" if average grid period < this fraction of the large
public static final int MAX_LWIR_WIDTH = 1023; // Consider smaller sensors to be low-res
Goniometer.GoniometerParameters goniometerParameters = null;
public String pathName=null;
public EyesisCameraParameters eyesisCameraParameters; // has "cartesian"
......@@ -967,7 +969,6 @@ import ij.text.TextWindow;
}
this.goniometerParameters = goniometerParameters;
boolean ignore_LWIR_pointers = true; // skip LWIR absolute marks, use them later
int max_lwir_width = 1023; // use LWIR class
setupIndices();
this.eyesisCameraParameters=eyesisCameraParameters;
int numSubCameras=(eyesisCameraParameters==null)?1:eyesisCameraParameters.eyesisSubCameras[0].length;
......@@ -1034,7 +1035,7 @@ import ij.text.TextWindow;
this.gIP[numFile].setNumber = nis;
this.gIP[numFile].gridImageSet = this.gIS[nis];
this.gIS[nis].imageSet[nc]=this.gIP[numFile];
boolean is_small = getImagePlusProperty(imp_grid,"WOI_WIDTH",0) <= MAX_LWIR_WIDTH;
//numFile
if (first_in_set || read_grids) {
if (read_grids) {
......@@ -1064,10 +1065,14 @@ import ij.text.TextWindow;
this.gIS[nis].motors= this.gIP[numFile].motors.clone();
this.gIP[numFile].matchedPointers = getUsedPonters(imp_grid);
if (this.gIP[numFile].matchedPointers > 0) {
System.out.print("<"+(this.gIP[numFile].matchedPointers));
// Not using LWIR pointers here!
if (!ignore_LWIR_pointers || (getImagePlusProperty(imp_grid,"WOI_TOP",0) > max_lwir_width)) {
// if (!ignore_LWIR_pointers || (getImagePlusProperty(imp_grid,"WOI_TOP",0) > MAX_LWIR_WIDTH)) {
if (!ignore_LWIR_pointers || !is_small) {
with_pointers = numFile;
System.out.print("|"+numFile);
}
System.out.print(">");
}
double [] saturations=new double [4];
for (int i=0;i<saturations.length;i++) {
......@@ -1108,7 +1113,8 @@ import ij.text.TextWindow;
int [] numBadNodes = new int [2];
if (this.eyesisCameraParameters.badNodeThreshold>0.0){
double badNodeThreshold = is_small? this.eyesisCameraParameters.badNodeThresholdLWIR : this.eyesisCameraParameters.badNodeThreshold;
if (badNodeThreshold > 0.0){
boolean thisDebug =false;
// thisDebug|= (fileNumber== 720); // chn 25
numBadNodes=fixBadGridNodes(
......@@ -1118,7 +1124,7 @@ import ij.text.TextWindow;
this.eyesisCameraParameters.removeWorst,
this.eyesisCameraParameters.weightBad,
this.eyesisCameraParameters.weightWorst,
this.eyesisCameraParameters.badNodeThreshold,
badNodeThreshold,
this.eyesisCameraParameters.maxBadNeighb,
this.debugLevel+(thisDebug?3:0),
thisDebug?("fixBad-"+numFile):null
......@@ -1241,7 +1247,7 @@ import ij.text.TextWindow;
5.0, // 2.0, // sigma
sensor_wh,
false); // true);
System.out.print(" {"+uv_shift_rot[0]+":"+uv_shift_rot[1]+"->");
System.out.print(" {{"+uv_shift_rot[0]+":"+uv_shift_rot[1]+"->");
int [] combinedUVShiftRot=MatchSimulatedPattern.combineUVShiftRot(
this.gIS[nis].imageSet[base_channel].getUVShiftRot(),
uv_shift_rot);
......@@ -3880,6 +3886,7 @@ import ij.text.TextWindow;
this.gIP[fileNumber].gridImage = imp_grid;
}
}
boolean is_small = getImagePlusProperty(imp_grid,"WOI_WIDTH",0) <= MAX_LWIR_WIDTH;
this.gIP[fileNumber].woi = new Rectangle(
getImagePlusProperty(imp_grid,"WOI_LEFT",0),
getImagePlusProperty(imp_grid,"WOI_TOP",0),
......@@ -3922,8 +3929,10 @@ import ij.text.TextWindow;
woi_compensated = true;
}
double badNodeThreshold = is_small? this.eyesisCameraParameters.badNodeThresholdLWIR : this.eyesisCameraParameters.badNodeThreshold;
// TODO: maybe adjust threshold to grid period, not the sensor type?
if (this.eyesisCameraParameters.badNodeThreshold>0.0){
if (badNodeThreshold>0.0){
boolean thisDebug =false;
// thisDebug|= (fileNumber== 720); // chn 25
int [] numBadNodes=fixBadGridNodes(
......@@ -3933,7 +3942,7 @@ import ij.text.TextWindow;
this.eyesisCameraParameters.removeWorst,
this.eyesisCameraParameters.weightBad,
this.eyesisCameraParameters.weightWorst,
this.eyesisCameraParameters.badNodeThreshold,
badNodeThreshold,
this.eyesisCameraParameters.maxBadNeighb,
this.debugLevel+(thisDebug?3:0),
thisDebug?("fixBad-"+fileNumber):null
......@@ -3941,11 +3950,11 @@ import ij.text.TextWindow;
if (this.debugLevel>-1) {
if ((numBadNodes[0] + numBadNodes [1])>0) {
if (this.eyesisCameraParameters.removeWorst) {
System.out.print(" -- removed "+numBadNodes[0]+"("+numBadNodes[1]+") locally worst grid nodes,");
System.out.print(" --- removed "+numBadNodes[0]+"("+numBadNodes[1]+") locally worst grid nodes,");
} else if (this.eyesisCameraParameters.replaceBad){
System.out.print(" -- replaced "+numBadNodes[0]+"("+numBadNodes[1]+") bad grid nodes,");
System.out.print(" --- replaced "+numBadNodes[0]+"("+numBadNodes[1]+") bad grid nodes,");
} else {
System.out.print(" -- scaled "+numBadNodes[0]+"("+numBadNodes[1]+") bad grid nodes,");
System.out.print(" --- scaled "+numBadNodes[0]+"("+numBadNodes[1]+") bad grid nodes,");
}
}
......@@ -5119,6 +5128,13 @@ import ij.text.TextWindow;
double sigma=sigmaUV;
if(sigma<0) sigma*=-rAverage;
gb.blurDouble(this.sensorMasks[chNum], dWidth, dHeight, sigma/decimate, sigma/decimate, 0.01);
if (this.debugLevel >1) {
(new ShowDoubleFloatArrays()).showArrays(
this.sensorMasks[chNum],
dWidth,
dHeight,
"SensorMask"+chNum);
}
}
return this.sensorMasks;
}
......
......@@ -8130,6 +8130,7 @@ List calibration
if (!LMA_OK) {
return null; // LMA did not converge
}
// DistortionCalibrationData dcd = this.fittingStrategy.distortionCalibrationData;
// find indices of GXYZ0 and GXYZ1 in the vector
int index_GXYZ0 = this.fittingStrategy.reverseParameterMap[num_img][par_index_GXYZ0];
......@@ -8169,11 +8170,26 @@ List calibration
int num_img,
int ser_num, // number of series to reprogram
PatternParameters patternParameters) {
int [] num_imgs = {num_img};
return adjustAttitudeAfterOffset(
num_imgs,
ser_num, // number of series to reprogram
patternParameters);
}
public boolean adjustAttitudeAfterOffset(
int [] num_imgs,
int ser_num, // number of series to reprogram
PatternParameters patternParameters) {
if (ser_num < 0) {
ser_num = fittingStrategy.parameterMode.length + ser_num; // use from the last one
}
if (this.debugLevel > 0) {
System.out.println("Will use/modify fitting series "+ser_num+" for to adjust az, tilt of image "+num_img);
System.out.print("Will use/modify fitting series "+ser_num+" for to adjust az, tilt of images: ");
for (int num_img: num_imgs) {
System.out.print(" "+num_img);
}
System.out.println();
System.out.println("Will adjust goniometerHorizontal, and goniometerAxial");
}
int was_seriesNumber = seriesNumber;
......@@ -8188,7 +8204,9 @@ List calibration
fittingStrategy.parameterMode[ser_num][par_index_goniometerAxial] = FittingStrategy.modeIndividual; // 3
boolean [] selection = fittingStrategy.selectAllImages(ser_num); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
selection[num_img]=true;
for (int num_img:num_imgs) {
selection[num_img]=true;
}
fittingStrategy.setImageSelection(ser_num,selection);
seriesNumber= ser_num; // start from 0;
initFittingSeries(false, filterForAll,ser_num); // will set this.currentVector, will build parameter map too
......
......@@ -77,7 +77,8 @@ import ij.gui.GenericDialog;
public boolean removeWorst = false; // remove completely locally worst nodes
public double weightBad = 0.3; // reduce contrast of bad nodes
public double weightWorst = 0.05; // reduce contrast of bad, local worst nodes
public double badNodeThreshold=0.1; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
public double badNodeThreshold=0.1; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
public double badNodeThresholdLWIR=0.2; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
public int maxBadNeighb= 1; // maximal number of bad nodes around the corrected one to fix
public int minimalValidNodes=10; // do not use images with less than this number of non-zero nodes (after all applicable weight masks)
public int weightMultiImageMode=1; // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set to weightMultiExponent power)
......@@ -353,6 +354,7 @@ import ij.gui.GenericDialog;
double weightBad,
double weightWorst,
double badNodeThreshold, // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
double badNodeThresholdLWIR, // same for the low-res sensors
int maxBadNeighb, // maximal number of bad nodes around the corrected one to fix
int minimalValidNodes,
int weightMultiImageMode, // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set)
......@@ -394,6 +396,7 @@ import ij.gui.GenericDialog;
weightBad,
weightWorst,
badNodeThreshold, // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
badNodeThresholdLWIR, // same for the low-res sensors
maxBadNeighb, // maximal number of bad nodes around the corrected one to fix
minimalValidNodes,
weightMultiImageMode, // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set)
......@@ -435,6 +438,7 @@ import ij.gui.GenericDialog;
double weightBad,
double weightWorst,
double badNodeThreshold, // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
double badNodeThresholdLWIR, // same for the low-res sensors
int maxBadNeighb, // maximal number of bad nodes around the corrected one to fix
int minimalValidNodes,
int weightMultiImageMode, // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set)
......@@ -475,6 +479,7 @@ import ij.gui.GenericDialog;
weightBad,
weightWorst,
badNodeThreshold, // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
badNodeThresholdLWIR, // same for the low-res sensors
maxBadNeighb, // maximal number of bad nodes around the corrected one to fix
minimalValidNodes,
weightMultiImageMode, // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set)
......@@ -516,6 +521,7 @@ import ij.gui.GenericDialog;
double weightBad,
double weightWorst,
double badNodeThreshold, // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
double badNodeThresholdLWIR, // same for the low-res sensors
int maxBadNeighb, // maximal number of bad nodes around the corrected one to fix
int minimalValidNodes,
int weightMultiImageMode, // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set)
......@@ -544,6 +550,7 @@ import ij.gui.GenericDialog;
this.weightBad = weightBad;
this.weightWorst = weightWorst;
this.badNodeThreshold=badNodeThreshold; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
this.badNodeThresholdLWIR=badNodeThresholdLWIR; // same for the low-res sensors
this.maxBadNeighb=maxBadNeighb; // maximal number of bad nodes around the corrected one to fix
this.minimalValidNodes=minimalValidNodes;
this.weightMultiImageMode=weightMultiImageMode; // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set)
......@@ -612,6 +619,7 @@ import ij.gui.GenericDialog;
destination.weightBad = source.weightBad;
destination.weightWorst = source.weightWorst;
destination.badNodeThreshold=source.badNodeThreshold; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
destination.badNodeThresholdLWIR=source.badNodeThresholdLWIR; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
destination.maxBadNeighb=source.maxBadNeighb; // maximal number of bad nodes around the corrected one to fix
destination.minimalValidNodes=source.minimalValidNodes;
destination.weightMultiImageMode=source.weightMultiImageMode; // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set)
......@@ -674,6 +682,7 @@ import ij.gui.GenericDialog;
properties.setProperty(prefix+"weightBad", this.weightBad+"");
properties.setProperty(prefix+"weightWorst",this.weightWorst+"");
properties.setProperty(prefix+"badNodeThreshold",this.badNodeThreshold+"");
properties.setProperty(prefix+"badNodeThresholdLWIR",this.badNodeThresholdLWIR+"");
properties.setProperty(prefix+"maxBadNeighb",this.maxBadNeighb+"");
properties.setProperty(prefix+"minimalValidNodes",this.minimalValidNodes+"");
properties.setProperty(prefix+"weightMultiImageMode",this.weightMultiImageMode+"");
......@@ -743,9 +752,10 @@ import ij.gui.GenericDialog;
this.weightBad=Double.parseDouble(properties.getProperty(prefix+"weightBad"));
if (properties.getProperty(prefix+"weightWorst")!=null)
this.weightWorst=Double.parseDouble(properties.getProperty(prefix+"weightWorst"));
if (properties.getProperty(prefix+"badNodeThreshold")!=null)
this.badNodeThreshold=Double.parseDouble(properties.getProperty(prefix+"badNodeThreshold"));
if (properties.getProperty(prefix+"badNodeThresholdLWIR")!=null)
this.badNodeThresholdLWIR=Double.parseDouble(properties.getProperty(prefix+"badNodeThresholdLWIR"));
if (properties.getProperty(prefix+"maxBadNeighb")!=null)
this.maxBadNeighb=Integer.parseInt(properties.getProperty(prefix+"maxBadNeighb"));
if (properties.getProperty(prefix+"minimalValidNodes")!=null)
......@@ -930,6 +940,7 @@ import ij.gui.GenericDialog;
gd.addNumericField("Scale weight of bad, locally worst nodes", this.weightWorst, 3,6,"");
gd.addNumericField("Filter out grid nodes with difference from quadratically predicted from 8 neighbors", this.badNodeThreshold, 2,6,"pix");
gd.addNumericField("Same for the low-res (LWIR) sensors", this.badNodeThresholdLWIR, 2,6,"pix");
gd.addNumericField("Maximal number of bad nodes around the corrected one to fix", this.maxBadNeighb, 0);
gd.addNumericField("Minimal number of valid (with all filters applied) nodes in each image",this.minimalValidNodes, 0);
gd.addNumericField("Increase weight of the multi-image sets (0 - do not increase, 1 - multiply by number of images in a set (to power ), 2 - same but remove single-image ",this.weightMultiImageMode, 0);
......@@ -988,6 +999,7 @@ import ij.gui.GenericDialog;
this.weightBad= gd.getNextNumber();
this.weightWorst= gd.getNextNumber();
this.badNodeThreshold= gd.getNextNumber();
this.badNodeThresholdLWIR= gd.getNextNumber();
this.maxBadNeighb= (int) gd.getNextNumber();
this.minimalValidNodes= (int) gd.getNextNumber();
this.weightMultiImageMode=(int) gd.getNextNumber();
......
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