Commit 33dacb9c authored by Andrey Filippov's avatar Andrey Filippov

upgraded 'Re-calibrate Set'

parent 8ff8e638
......@@ -31,6 +31,7 @@ import java.awt.Color;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
......@@ -49,6 +50,8 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
......@@ -6069,211 +6072,7 @@ if (MORE_BUTTONS) {
return;
}
LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
GenericDialog gd=new GenericDialog ("Select image set to re-calibrate");
gd.addNumericField("Image set number", 0, 0);
gd.addCheckbox ("Set image set parameters from closest, (re-)estimate orientation", true);
gd.showDialog();
if (gd.wasCanceled()) return;
int imageSetNumber=(int) gd.getNextNumber();
boolean reEstimate=gd.getNextBoolean();
if (imageSetNumber<0) return;
if (reEstimate){
// boolean OK=
LENS_DISTORTIONS.setSetFromClosestAndEstimateOrientation(
imageSetNumber,
null, //boolean [] selectedImages,
null, //boolean [] parameterMask,
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData,
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.eyesisCameraParameters);
}
double tiltCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
double axialCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
double interCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle;
int tiltNumSteps=1;
int axialNumSteps=21;
double tiltStep=0.25;
double axialStep=0.25;
boolean processAllImages=true;
boolean ignoreLaserPointers=false;
double hintGridTolerance=200.0;
boolean useSetsData= true;
gd=new GenericDialog ("Image set # "+imageSetNumber+" re-calibration without laser pointers");
gd.addMessage("Strategy 0 should have all parameters but 2 goniometer axes disabled");
gd.addMessage("Imgages belonging to the set will be selected, possible to check with \"Remove Outliers\" for strategy 0");
gd.addNumericField("Mismatch tolerance of match between the predicted and acquired grid", hintGridTolerance, 1,4,"fraction of grid half-period");
gd.addCheckbox("Ignore laser pointers", ignoreLaserPointers);
gd.addNumericField("Image set tilt", tiltCenter, 2,6,"degrees");
gd.addNumericField("Image set axial", axialCenter, 2,6,"degrees");
gd.addNumericField("Image set inter-axis", interCenter, 2,6,"degrees");
gd.addNumericField("Tilt number of steps", tiltNumSteps, 0,3,"");
gd.addNumericField("Axial number of steps", axialNumSteps, 0,3,"");
gd.addNumericField("Tilt scan step", tiltStep, 2,5,"degrees");
gd.addNumericField("Axial scan step", axialStep, 2,5,"degrees");
gd.addCheckbox ("Use image sets data if available (false - use camera data)", useSetsData);
gd.addCheckbox("process all images (false - enabled only)", processAllImages);
gd.showDialog();
if (gd.wasCanceled()) return;
hintGridTolerance= gd.getNextNumber();
ignoreLaserPointers= gd.getNextBoolean();
tiltCenter= gd.getNextNumber();
axialCenter= gd.getNextNumber();
interCenter= gd.getNextNumber();
tiltNumSteps= (int) gd.getNextNumber();
axialNumSteps= (int) gd.getNextNumber();
tiltStep= gd.getNextNumber();
axialStep= gd.getNextNumber();
useSetsData= gd.getNextBoolean();
processAllImages= gd.getNextBoolean();
double [] initialTilt = new double [tiltNumSteps];
double [] initialAxial= new double [axialNumSteps];
double [][] finalTilt = new double [tiltNumSteps][axialNumSteps];
double [][] finalAxial= new double [tiltNumSteps][axialNumSteps];
double [][] finalInter= new double [tiltNumSteps][axialNumSteps];
double [][] finalError= new double [tiltNumSteps][axialNumSteps];
for (int tiltIndex=0; tiltIndex<tiltNumSteps;tiltIndex++) initialTilt[tiltIndex]=tiltCenter+tiltStep*(tiltIndex-0.5*(tiltNumSteps-1));
for (int axialIndex=0;axialIndex<axialNumSteps;axialIndex++) initialAxial[axialIndex]=axialCenter+axialStep*(axialIndex-0.5*(axialNumSteps-1));
for (int tiltIndex=0; tiltIndex<tiltNumSteps;tiltIndex++) for (int axialIndex=0;axialIndex<axialNumSteps;axialIndex++) {
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt=initialTilt[tiltIndex];
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial=initialAxial[axialIndex];
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle=interCenter; // no scanning, just use center value
if (DEBUG_LEVEL>0) System.out.println("Image Set #"+imageSetNumber+
" Initial tilt="+initialTilt[tiltIndex]+
" Initial inter="+interCenter);
int [][] imageSets=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.listImages(!processAllImages);
int [] imageSet=imageSets[imageSetNumber];
if (imageSet==null){
IJ.showMessage("Image set #"+imageSetNumber+" is empty");
return;
}
for (int i=0;i<imageSet.length;i++){
int imageNumber=imageSet[i];
LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
hintGridTolerance, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //processAll, //boolean processAll, // if true - process all images, false - only disabled
ignoreLaserPointers, //true, //ignoreLaserPointers,
true, //processBlind,
imageNumber,
useSetsData,
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
}
// set series 0 to this set images
boolean [] selection =LENS_DISTORTIONS.fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
for (int i=0;i<imageSet.length;i++) selection[imageSet[i]]=true;
LENS_DISTORTIONS.fittingStrategy.setImageSelection(0,selection);
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
LENS_DISTORTIONS.fittingStrategy.stopAfterThis[0]=true;
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.stopOnFailure=false;
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0]; // 0.001; // why it does not use fitting series lambda?
boolean LMA_OK=LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
if (LMA_OK) {
finalTilt[tiltIndex][axialIndex]=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
finalAxial[tiltIndex][axialIndex]=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
finalInter[tiltIndex][axialIndex]=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle;
finalError[tiltIndex][axialIndex]=LENS_DISTORTIONS.currentRMS;
} else {
finalTilt[tiltIndex][axialIndex]=initialTilt[tiltIndex];
finalAxial[tiltIndex][axialIndex]=initialAxial[axialIndex];
finalInter[tiltIndex][axialIndex]=interCenter;
finalError[tiltIndex][axialIndex]=Double.NaN;
if (DEBUG_LEVEL>0) System.out.println("----------------- LMA FAILED -------------------------");
}
}
int bestTiltIndex=0;
int bestAxialIndex=0;
double bestRMS=finalError[bestTiltIndex][bestAxialIndex];
for (int tiltIndex=0; tiltIndex<tiltNumSteps;tiltIndex++) for (int axialIndex=0;axialIndex<axialNumSteps;axialIndex++) {
if (Double.isNaN(bestRMS) || (bestRMS>finalError[tiltIndex][axialIndex])){
bestTiltIndex=tiltIndex;
bestAxialIndex=axialIndex;
bestRMS=finalError[bestTiltIndex][bestAxialIndex];
}
}
if (DEBUG_LEVEL>0) System.out.println("================ Image Set #"+imageSetNumber+" rms="+IJ.d2s(bestRMS, 6)+
" final tilt="+finalTilt[bestTiltIndex][bestAxialIndex]+" ("+tiltCenter+": "+initialTilt[bestTiltIndex]+") " +
" final axial="+finalAxial[bestTiltIndex][bestAxialIndex]+" ("+axialCenter+": "+initialAxial[bestAxialIndex]+")"+
" final inter="+finalInter[bestTiltIndex][bestAxialIndex]+" ("+interCenter+": "+interCenter+")");
// repeat with the best indices
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt=finalTilt[bestTiltIndex][bestAxialIndex]; //initialTilt[bestTiltIndex];
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial=finalAxial[bestTiltIndex][bestAxialIndex]; //initialAxial[bestAxialIndex];
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle=finalInter[bestTiltIndex][bestAxialIndex];
if (DEBUG_LEVEL>0) System.out.println(
"Image Set #"+imageSetNumber+
" Initial tilt="+finalTilt[bestTiltIndex][bestAxialIndex]+
" Initial axial="+finalAxial[bestTiltIndex][bestAxialIndex]+
" Initial inter="+finalInter[bestTiltIndex][bestAxialIndex]
);
int [][] imageSets=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.listImages(!processAllImages);
int [] imageSet=imageSets[imageSetNumber];
if (imageSet==null){
IJ.showMessage("Image set #"+imageSetNumber+" is empty");
return;
}
for (int i=0;i<imageSet.length;i++){
int imageNumber=imageSet[i];
LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
hintGridTolerance, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //processAll, //boolean processAll, // if true - process all images, false - only disabeld
ignoreLaserPointers, //ignoreLaserPointers,
true, //processBlind,
imageNumber,
useSetsData,
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
}
// set series 0 to this set images
boolean [] selection =LENS_DISTORTIONS.fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
for (int i=0;i<imageSet.length;i++) selection[imageSet[i]]=true;
LENS_DISTORTIONS.fittingStrategy.setImageSelection(0,selection);
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
LENS_DISTORTIONS.fittingStrategy.stopAfterThis[0]=true;
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
// save safe settings to run LMA manually
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
LENS_DISTORTIONS.stopEachSeries= true; // will not ask for confirmation after done
LENS_DISTORTIONS.stopOnFailure=true;
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
if (DEBUG_LEVEL>0) System.out.println("================ Image Set #"+imageSetNumber+" rms="+IJ.d2s(bestRMS, 6)+
" final tilt="+finalTilt[bestTiltIndex][bestAxialIndex]+" ("+tiltCenter+": "+initialTilt[bestTiltIndex]+") " +
" final axial="+finalAxial[bestTiltIndex][bestAxialIndex]+" ("+axialCenter+": "+initialAxial[bestAxialIndex]+")" +
" final inter="+finalInter[bestTiltIndex][bestAxialIndex]+" ("+interCenter+")");
recalibrateSet();
return;
}
......@@ -9730,6 +9529,318 @@ if (MORE_BUTTONS) {
}
public boolean recalibrateSet() {
GenericDialog gd=new GenericDialog ("Select image set to re-calibrate");
gd.addNumericField("Image set number", 0, 0);
gd.addCheckbox ("Set image set parameters from closest, (re-)estimate orientation", true);
gd.showDialog();
if (gd.wasCanceled()) return false;
int imageSetNumber=(int) gd.getNextNumber();
boolean reEstimate=gd.getNextBoolean();
if (imageSetNumber<0) return false;
if (reEstimate){
// boolean OK=
LENS_DISTORTIONS.setSetFromClosestAndEstimateOrientation(
imageSetNumber,
null, //boolean [] selectedImages,
null, //boolean [] parameterMask,
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData,
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.eyesisCameraParameters);
}
double tiltCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
double axialCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
double interCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle;
double tiltHalfRange = 2.0; // degrees
double axialHalfRange = 15.0; // degrees
int scanHalfV = 10; // can be large - actual will be limited by angular range
int scanHalfU = 10; // can be large - actual will be limited by angular range
double stopRMS = 1.0; // exit when RMS falls below
boolean processAllImages=true;
boolean ignoreLaserPointers=false;
double hintGridTolerance=200.0;
boolean useSetsData= true;
gd=new GenericDialog ("Image set # "+imageSetNumber+" re-calibration without laser pointers");
gd.addMessage("Strategy 0 should have all parameters but 2 goniometer axes disabled");
gd.addMessage("Imgages belonging to the set will be selected, possible to check with \"Remove Outliers\" for strategy 0");
gd.addNumericField("Mismatch tolerance of match between the predicted and acquired grid", hintGridTolerance, 1,4,"fraction of grid half-period");
gd.addCheckbox("Ignore laser pointers", ignoreLaserPointers);
gd.addNumericField("Image set center tilt", tiltCenter, 2,6,"degrees");
gd.addNumericField("Image set center axial", axialCenter, 2,6,"degrees");
gd.addNumericField("Image set inter-axis", interCenter, 2,6,"degrees");
gd.addNumericField("Tilt scan half-range", tiltHalfRange, 2,6,"degrees");
gd.addNumericField("Axial scan half-range", axialHalfRange, 2,6,"degrees");
gd.addNumericField("Half scan in U (almost horizontal) grid nodes (large will be limited by angular range)", scanHalfU, 0,3,"");
gd.addNumericField("Half scan in V (almost vertical) grid nodes (large will be limited by angular range)", scanHalfV, 0,3,"");
gd.addNumericField("Stop RMS - exit scan when RMS falls below", stopRMS, 2,6,"pixels");
gd.addCheckbox ("Use image sets data if available (false - use camera data)", useSetsData);
gd.addCheckbox("process all images (false - enabled only)", processAllImages);
gd.showDialog();
if (gd.wasCanceled()) return false;
hintGridTolerance= gd.getNextNumber();
ignoreLaserPointers= gd.getNextBoolean();
tiltCenter= gd.getNextNumber();
axialCenter= gd.getNextNumber();
interCenter= gd.getNextNumber();
tiltHalfRange= gd.getNextNumber();
axialHalfRange= gd.getNextNumber();
scanHalfV= (int) gd.getNextNumber();
scanHalfU= (int) gd.getNextNumber();
stopRMS = gd.getNextNumber();
useSetsData= gd.getNextBoolean();
processAllImages= gd.getNextBoolean();
// Find channel with most weight
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt=tiltCenter;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial=axialCenter;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle=interCenter;
// Run once with center position or Goniometer angles to determine average derivatives
int [][] imageSets=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.listImages(!processAllImages);
int [] imageSet=imageSets[imageSetNumber];
if (imageSet==null){
IJ.showMessage("Image set #"+imageSetNumber+" is empty");
return false;
}
for (int i=0;i<imageSet.length;i++){
int imageNumber=imageSet[i];
LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
hintGridTolerance, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //processAll, //boolean processAll, // if true - process all images, false - only disabeld
ignoreLaserPointers, //ignoreLaserPointers,
true, //processBlind,
imageNumber,
useSetsData,
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
}
boolean [] selection =LENS_DISTORTIONS.fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
for (int i=0;i<imageSet.length;i++) selection[imageSet[i]]=true;
LENS_DISTORTIONS.fittingStrategy.setImageSelection(0,selection);
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
LENS_DISTORTIONS.fittingStrategy.stopAfterThis[0]=true;
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
Distortions distortions_dbg = LENS_DISTORTIONS;
LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false, // new: dry_run use it here?
true);
double [][] dTA_dUV = LENS_DISTORTIONS.getDtaDuv();
if (DEBUG_LEVEL > 0) {
System.out.println(
"Grid dTilt/dU = "+dTA_dUV[0][0]+"\n"+
"Grid dAxial/dU = "+dTA_dUV[1][0]+"\n"+
"Grid dTilt/dV = "+dTA_dUV[0][1]+"\n"+
"Grid dAxial/dV = "+dTA_dUV[1][1]);
}
// update center angles
tiltCenter= LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
axialCenter= LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
interCenter = LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle;
double rms_last= LENS_DISTORTIONS.currentRMS;
double tilt_last = tiltCenter;
double axial_last = axialCenter;
double inter_last = interCenter;
double best_rms = rms_last;
double best_tilt = tilt_last;
double best_axial = axial_last;
double best_inter = inter_last;
Point best_pnt = new Point(0,0);
if (best_rms > stopRMS) { // do nothing if the original center is already OK
ArrayList<Point> nodeList = new ArrayList<Point>();
for (int dv = -scanHalfV; dv <= scanHalfV; dv++) {
for (int du = -scanHalfU; du <= scanHalfU; du++) {
if ((((dv+du) % 2) == 0) && ((dv !=0) || (du != 0))){
double dtilt = dTA_dUV[0][0]*du + dTA_dUV[0][1]*dv;
double daxial = dTA_dUV[1][0]*du + dTA_dUV[1][1]*dv;
if ((Math.abs(dtilt) <= tiltHalfRange) && (Math.abs(daxial) <= axialHalfRange)) {
nodeList.add(new Point(du,dv));
}
}
}
}
// sort list
Collections.sort(nodeList, new Comparator<Point>() {
@Override
public int compare(Point lhs, Point rhs) {
double rhsl2 = rhs.getX()*rhs.getX() + rhs.getY()*rhs.getY();
double lhsl2 = lhs.getX()*lhs.getX() + lhs.getY()*lhs.getY();
return (rhsl2 > lhsl2) ? -1 : (rhsl2 < lhsl2) ? 1 : 0;
}
});
for (Point pnt:nodeList) {
double dtilt = dTA_dUV[0][0]*pnt.getX() + dTA_dUV[0][1]*pnt.getY();
double daxial = dTA_dUV[1][0]*pnt.getX() + dTA_dUV[1][1]*pnt.getY();
double tilt0 = tiltCenter + dtilt;
double axial0 = axialCenter + daxial;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt = tilt0;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial = axial0;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle = interCenter; // no scanning, just use center value
if (DEBUG_LEVEL>0) System.out.println("Image Set #"+imageSetNumber+
" Initial tilt=" + tilt0+
" Initial axial=" + axial0+
" Initial inter=" + interCenter);
imageSets=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.listImages(!processAllImages);
imageSet=imageSets[imageSetNumber];
if (imageSet==null){
IJ.showMessage("Image set #"+imageSetNumber+" is empty");
return false;
}
for (int i=0;i<imageSet.length;i++){
int imageNumber=imageSet[i];
LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
hintGridTolerance, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //processAll, //boolean processAll, // if true - process all images, false - only disabled
ignoreLaserPointers, //true, //ignoreLaserPointers,
true, //processBlind,
imageNumber,
useSetsData,
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
}
selection =LENS_DISTORTIONS.fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
for (int i=0;i<imageSet.length;i++) selection[imageSet[i]]=true;
LENS_DISTORTIONS.fittingStrategy.setImageSelection(0,selection);
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
LENS_DISTORTIONS.fittingStrategy.stopAfterThis[0]=true;
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.stopOnFailure=false;
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0]; // 0.001; // why it does not use fitting series lambda?
boolean LMA_OK=LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false, // new: dry_run use it here?
false); // no need to calculate dTA_dUV
if (LMA_OK) {
tilt_last = LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
axial_last = LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
inter_last = LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle;
rms_last = LENS_DISTORTIONS.currentRMS;
if (rms_last < best_rms) { // no Double.NaN for best_rms here
best_rms = rms_last;
best_tilt = tilt_last;
best_axial = axial_last;
best_inter = inter_last;
best_pnt = pnt;
}
if (best_rms <= stopRMS) {
break;
}
} else {
if (DEBUG_LEVEL>0) System.out.println("----------------- LMA FAILED -------------------------");
}
}
if (DEBUG_LEVEL>0) System.out.println("================ Image Set #"+imageSetNumber+" rms="+IJ.d2s(best_rms, 6)+
" final tilt= "+best_tilt+ " ("+tiltCenter+")\n" +
" final axial="+best_axial+" ("+axialCenter+")\n"+
" final inter="+best_inter+" ("+interCenter+")");
if (best_rms != rms_last) {
// Restore best position if it was not the last
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt= best_tilt;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial=best_axial;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle= best_inter;
if (DEBUG_LEVEL>0) System.out.println(
"Repeating with the best variant for Image Set #"+imageSetNumber+
" Initial tilt="+best_tilt+
" Initial axial="+best_axial+
" Initial inter="+best_inter
);
imageSets=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.listImages(!processAllImages);
imageSet=imageSets[imageSetNumber];
if (imageSet==null){
IJ.showMessage("Image set #"+imageSetNumber+" is empty");
return false;
}
for (int i=0;i<imageSet.length;i++){
int imageNumber=imageSet[i];
LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
hintGridTolerance, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //processAll, //boolean processAll, // if true - process all images, false - only disabeld
ignoreLaserPointers, //ignoreLaserPointers,
true, //processBlind,
imageNumber,
useSetsData,
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
}
// set series 0 to this set images
selection =LENS_DISTORTIONS.fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
for (int i=0;i<imageSet.length;i++) selection[imageSet[i]]=true;
LENS_DISTORTIONS.fittingStrategy.setImageSelection(0,selection);
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
LENS_DISTORTIONS.fittingStrategy.stopAfterThis[0]=true;
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
}
}
//save safe settings to run LMA manually
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
LENS_DISTORTIONS.stopEachSeries= true; // will not ask for confirmation after done
LENS_DISTORTIONS.stopOnFailure=true;
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
if (DEBUG_LEVEL > -1) System.out.println("================ Image Set #"+imageSetNumber+" rms="+IJ.d2s(best_rms, 6)+
" final tilt="+best_tilt+" ("+tiltCenter+") " +
" final axial="+best_axial+" ("+axialCenter+")" +
" final inter="+best_inter+" ("+interCenter+")" +
" final UV offset = ("+best_pnt.getX()+","+best_pnt.getY()+")");
return true;
}
public boolean lwirToEo() {
if (LENS_DISTORTIONS == null) {
System.out.println("LENS_DISTORTIONS is null");
......@@ -96,6 +96,7 @@ import ij.text.TextWindow;
return (eyesisCameraParameters==null)?0:eyesisCameraParameters.getNumStations();
}
public double getPixelSize(int station, int channel) {
return this.eyesisCameraParameters.eyesisSubCameras[station][channel].getPixelSize();
}
......
......@@ -36,6 +36,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.SwingUtilities;
import com.elphel.imagej.calibration.DistortionCalibrationData.GridImageParameters;
import com.elphel.imagej.calibration.hardware.CamerasInterface;
import com.elphel.imagej.cameras.EyesisCameraParameters;
import com.elphel.imagej.cameras.EyesisSubCameraParameters;
......@@ -78,6 +79,7 @@ public class Distortions {
public double [] Y=null; // array of "y" - for each grid image, each defined grid node - 2 elements
public int [] imageStartIndex=null; // elements containing index of the start point of the selected image, first element 0, last - total number of points.
public double [] weightFunction=null; // array of weights for pixels (to fade values near borders), corresponding to Y array
public double [][] dTA_dUV = null; // null or double [2][2] to return averaged {{dU/dAz,dU/dTl}{dV/dAz,dV/dTl}}.inverse
public double sumWeights;
public double [][] targetXYZ=null; // array of target {x,y,z} matching each image each grid point
......@@ -175,7 +177,10 @@ public class Distortions {
}
public void setSensorHeight(int subCam, int v) {fittingStrategy.distortionCalibrationData.eyesisCameraParameters.setSensorHeight(subCam, v);}
public void setDecimateMasks(int subCam, int v){fittingStrategy.distortionCalibrationData.eyesisCameraParameters.setDecimateMasks(subCam, v);}
public double [][] getDtaDuv(){
return dTA_dUV;
}
public class LMAArrays {
......@@ -399,7 +404,7 @@ public class Distortions {
System.out.println("initFittingSeries("+justSelection+","+filter+","+numSeries+"), pass="+pass);
//TODO: ********* Implement comments above ************
// calculate total number of x/y pairs in the selected images
if (numSeries<0) justSelection=true;
if (numSeries <0 ) justSelection=true;
if ((pass==1) && (numSeries>=0)) fittingStrategy.invalidateSelectedImages(numSeries); // next selectedImages() will select all, including empty
if (!justSelection) {
fittingStrategy.buildParameterMap (numSeries); // also sets currentSeriesNumber
......@@ -615,6 +620,14 @@ public class Distortions {
if ((this.pixelCorrection==null) || (this.pixelCorrection[chnNum] == null)){
this.Y[2*index]= fittingStrategy.distortionCalibrationData.gIP[imgNum].pixelsXY[pointNumber][0];
this.Y[2*index+1]=fittingStrategy.distortionCalibrationData.gIP[imgNum].pixelsXY[pointNumber][1];
if (Double.isNaN(this.Y[2*index]) || Double.isNaN(this.Y[2*index+1])) {
System.out.println("Bug 1 in initFittingSeries(): NaN! distortionCalibrationData.gIP["+imgNum+"].pixelsXY["+pointNumber+"][0]="+
fittingStrategy.distortionCalibrationData.gIP[imgNum].pixelsXY[pointNumber][0]+
", distortionCalibrationData.gIP["+imgNum+"].pixelsXY["+pointNumber+"][1]="+
fittingStrategy.distortionCalibrationData.gIP[imgNum].pixelsXY[pointNumber][1]);
this.Y[2*index]= 0.0;
this.Y[2*index + 1]= 0.0;
}
} else {
// TODO: remove and use new code (if tested OK)
double [] pXY={
......@@ -632,6 +645,17 @@ public class Distortions {
} else {
this.Y[2*index]= pXY[0]-this.pixelCorrection[chnNum][0][indexXY]; //java.lang.ArrayIndexOutOfBoundsException: 3204663
this.Y[2*index+1]=pXY[1]-this.pixelCorrection[chnNum][1][indexXY];
if (Double.isNaN(this.Y[2*index]) || Double.isNaN(this.Y[2*index+1])) {
System.out.println("Bug 2 in initFittingSeries(): NaN! this.pixelCorrection["+chnNum+"][0]["+indexXY+"]="+
this.pixelCorrection[chnNum][0][indexXY]+
", this.pixelCorrection["+chnNum+"][1]["+indexXY+"]="+
this.pixelCorrection[chnNum][1][indexXY]+
", pXY[0]="+pXY[0]+", pXY[1]="+pXY[1]+
", imgNum="+imgNum+", pointNumber="+pointNumber);
this.Y[2*index]= 0.0;
this.Y[2*index + 1]= 0.0;
}
}
// TODO: remove above and un-comment below (after testing)
/*
......@@ -686,7 +710,7 @@ public class Distortions {
}
}
// Normalize set weights
int numSetsUsed=0;
int numSetsUsed=0+0;
double totalSetWeight=0.0;
for (int imgSet=0;imgSet<this.fittingStrategy.distortionCalibrationData.gIS.length;imgSet++){
if (this.fittingStrategy.distortionCalibrationData.gIS[imgSet].setWeight>0){
......@@ -703,7 +727,7 @@ public class Distortions {
}
}
}
// last? not here!
// last? not here! numSetsUsed counted twice (should be = 1, is 2)
// this.imageStartIndex[numImg]=index;
if (justSelection) {
this.currentVector = null;
......@@ -3327,14 +3351,20 @@ For each point in the image
System.out.println("Processing debug image "+numGridImage);
System.out.println("Processing debug image "+numGridImage);
}
*/
int set_number = dcd.gIP[numGridImage].getSetNumber();
if ((set_number >= start_set) &&
(set_number <= end_set) &&
(((imageNumber<0) ||
((imageNumber==numGridImage)) &&(processAll) ||
(((imageNumber<0) || ((imageNumber==numGridImage)) && (processAll) ||
(!dcd.gIP[numGridImage].enabled &&
((hintGridTolerance>0.0) || ((dcd.gIP[numGridImage].matchedPointers>0)) && !ignoreLaserPointers))))){ // skip no-pointers if only orientation is hinted
((hintGridTolerance>0.0) ||
((dcd.gIP[numGridImage].matchedPointers>0)) && !ignoreLaserPointers))))){ // skip no-pointers if only orientation is hinted
*/
int set_number = dcd.gIP[numGridImage].getSetNumber();
if ((set_number >= start_set) && (set_number <= end_set) && // correct set range
((imageNumber < 0) || (imageNumber==numGridImage)) && // either all images or selected image
(processAll || !dcd.gIP[numGridImage].enabled) && // "process all" (including disabled) or this is disabled
((hintGridTolerance > 0.0) || ((dcd.gIP[numGridImage].matchedPointers>0) && !ignoreLaserPointers)) // hint tolerance is provided, or there are lasers not disabled
){ // skip no-pointers if only orientation is hinted
if (((dcd.gIP[numGridImage].matchedPointers==0) || ignoreLaserPointers)&&
(dcd.gIS[dcd.get_gIS_index(numGridImage)].orientationEstimated)) {
if ( !processBlind) {
......@@ -3708,6 +3738,11 @@ For each point in the image
public void manualGridHint(int imgNumber) {
int [][] markers = getImageMarkers(imgNumber);
if ((markers != null) && (markers.length > 0)) {
if (markers.length > 1) {
System.out.println("This image has multiple point marks - please remove extra");
IJ.showMessage("This image has multiple point marks - please remove extra");
return;
}
double [][] xyuv = new double [markers.length][4];
for (int i =0; i < markers.length; i++) {
xyuv[i][0]=markers[i][0];
......@@ -3771,25 +3806,28 @@ For each point in the image
}
int ix0 = indx_best % width;
int iy0 = indx_best / width;
int half_range = 2; // was 1;
PolynomialApproximation polynomialApproximation =new PolynomialApproximation(0);// no debug
double [][][] data = new double[9][3][];
// double [][][] data = new double[9][3][];
double [][][] data = new double[(2*half_range+1)*(2*half_range+1)][3][];
int indx = 0;
for (int idy = -1; idy <=1; idy++) {
for (int idy = -half_range; idy <=half_range; idy++) {
int iy = iy0+idy;
for (int idx = -1; idx <=1; idx++) {
for (int idx = -half_range; idx <= half_range; idx++) {
int ix = ix0 + idx;
data[indx][0] = new double[2];
data[indx][1] = new double[2];
data[indx][2] = new double[1];
data[indx][0][0] = idx;
data[indx][0][1] = idy;
data[indx][2][0] = 0.0;
if ((ix >= 0) && (ix < width) && (iy >= 0) && (iy < height)) {
int offs = iy * width + ix;
data[indx][1][0] = pixels[0][offs] - xyuv[0][0];
data[indx][1][1] = pixels[1][offs] - xyuv[0][1];
data[indx][2][0] = 1.0;
} else {
data[indx][2][0] = 0.0;
if ((pixels[0][offs] >= 0) && (pixels[1][offs] >= 0)) {
data[indx][1][0] = pixels[0][offs] - xyuv[0][0];
data[indx][1][1] = pixels[1][offs] - xyuv[0][1];
data[indx][2][0] = 1.0;
}
}
indx++;
}
......@@ -5877,7 +5915,7 @@ List calibration
final double [][] patternXYZ, // this.targetXYZ
final double [] weightFunction, // may be null - make it twice smaller? - same for X and Y?
final LensDistortionParameters lensDistortionParametersProto,
// final double lambda,
final double [][] dTA_dUV, // null or double [][] to return averaged per-image {{dU/dAz,dU/dTl}{dV/dAz,dV/dTl}}
int threadsMax,
boolean updateStatus){
......@@ -5906,6 +5944,8 @@ List calibration
if (selectedImages[i]) selectedIndex++;
if (selectedIndex>=numSelectedImages) selectedIndex--;
}
final double [][][] dUV_image = (dTA_dUV != null) ? new double [selectedImages.length][][]: null;
final double [] dUV_weights = (dTA_dUV != null) ? new double [selectedImages.length]: null;
final AtomicInteger stopRequested=this.stopRequested;
final AtomicBoolean interruptedAtomic=new AtomicBoolean();
for (int ithread = 0; ithread < threads.length; ithread++) {
......@@ -5915,6 +5955,11 @@ List calibration
LensDistortionParameters lensDistortionParameters=lensDistortionParametersProto.clone(); // see - if that is needed - maybe new is OK
// LensDistortionParameters lensDistortionParameters= new LensDistortionParameters();
for (int numImage=imageNumberAtomic.getAndIncrement(); (numImage<selectedImages.length) && !interruptedAtomic.get();numImage=imageNumberAtomic.getAndIncrement()){
int length=2*(imageStartIndex[numImage+1]-imageStartIndex[numImage]);
if (length == 0) {
continue;
}
int start= 2*imageStartIndex[numImage];
double [][] partialJacobian= calculatePartialFxAndJacobian(
numImage, // number of grid image
vector, // parameters vector
......@@ -5924,8 +5969,8 @@ List calibration
lensDistortionParameters, // initialize one per each tread? Or for each call?
true); // when false, modifies only this.lensDistortionParameters.*
int length=2*(imageStartIndex[numImage+1]-imageStartIndex[numImage]);
int start= 2*imageStartIndex[numImage];
// int length=2*(imageStartIndex[numImage+1]-imageStartIndex[numImage]);
// int start= 2*imageStartIndex[numImage];
double [][] partialJtByJmod=new double [numPars][numPars]; // out of heap space
double [] partialJtByDiff=new double [numPars];
......@@ -5947,20 +5992,102 @@ List calibration
for (int i=0;i<numPars;i++) if (partialJacobian[i]!=null) {
partialJtByDiff[i]=0.0;
if (weightFunction!=null)
for (int k=0;k<length;k++) partialJtByDiff[i]+=partialJacobian[i][k]*partialDiff[k]*weightFunction[start+k];
for (int k=0;k<length;k++) {
if (Double.isNaN(partialDiff[k])) {
System.out.println("calculateJacobianArrays() BUG1:partialDiff["+k+"]=NaN, i="+i);
} else {
partialJtByDiff[i]+=partialJacobian[i][k]*partialDiff[k]*weightFunction[start+k];
}
}
else
for (int k=0;k<length;k++) partialJtByDiff[i]+=partialJacobian[i][k]*partialDiff[k];
for (int k=0;k<length;k++) {
if (Double.isNaN(partialDiff[k])) {
System.out.println("calculateJacobianArrays() BUG2:partialDiff["+k+"]=NaN, i="+i);
} else {
partialJtByDiff[i]+=partialJacobian[i][k]*partialDiff[k];
}
}
}
// wrong! fix it
/*
synchronized(this){
for (int i=0;i<numPars;i++) if (partialJacobian[i]!=null){
JtByDiff[i]+=partialJtByDiff[i];
for (int j=i;j<numPars;j++) JtByJmod[i][j]+=partialJtByJmod[i][j];
int par_gh = -1;
int par_ga = -1;
if (dUV_image != null) {
dUV_image[numImage] = null; //new double [2][2];
for (int i = 0; i < numPars; i++) {
int parNum=fittingStrategy.parameterMap[i][1];
if (parNum == fittingStrategy.distortionCalibrationData.index_gh) {
par_gh = i;
} else if (parNum == fittingStrategy.distortionCalibrationData.index_ga) {
par_ga = i;
}
}
if ((par_gh >= 0) && (par_ga >= 0)) { // both defined
// partialJacobian[par_gh][2*k ] dPx/dGh
// partialJacobian[par_gh][2*k+1] dPy/dGh
// partialJacobian[par_gh][2*k ] dPx/dGa
// partialJacobian[par_gh][2*k+1] dPy/dGa
// d3780: public void updateGridToPointer(ImagePlus imp_grid, double[][] xyuv) {
// find average dX/dU, dY/dU, dX/dV, dY/dV
PolynomialApproximation polynomialApproximation =new PolynomialApproximation(0);// no debug
GridImageParameters gip = fittingStrategy.distortionCalibrationData.gIP[numImage];
int np = gip.pixelsXY.length;
double wsx=0.0, wsy=0.0, ws_dpx_dgh= 0.0, ws_dpy_dgh= 0.0, ws_dpx_dga= 0.0, ws_dpy_dga= 0.0;
for (int k = 0; k < length; k+=1) {
double w = (weightFunction!=null)? weightFunction[start+k] : 1.0;
wsx += w;
ws_dpx_dgh += w * partialJacobian[par_gh][k];
ws_dpx_dga += w * partialJacobian[par_ga][k];
k++;
w = (weightFunction!=null)? weightFunction[start+k] : 1.0;
wsy += w;
ws_dpy_dgh += w * partialJacobian[par_gh][k];
ws_dpy_dga += w * partialJacobian[par_ga][k];
}
if ((wsx == 0.0) || (wsy == 0.0)) {
if (debugLevel>2) {
System.out.println("Not enough data for dpx/dgh, dpy/dgh, dpx/dga, dpy/dga for image #"+numImage);
}
continue;
}
ws_dpx_dgh /= wsx;
ws_dpx_dga /= wsx;
ws_dpy_dgh /= wsy;
ws_dpy_dga /= wsy;
Matrix mXY_HA = new Matrix(new double[][] {{ws_dpx_dgh, ws_dpx_dga},{ws_dpy_dgh, ws_dpy_dga}});
double [][][] data = new double[np][3][];
for (int indx = 0; indx < np; indx++) {
data[indx][0] = new double[2];
data[indx][1] = new double[2];
data[indx][2] = new double[1];
data[indx][0][0] = gip.pixelsUV[indx][0]; // U
data[indx][0][1] = gip.pixelsUV[indx][1]; // V
data[indx][1][0] = gip.pixelsXY[indx][0]; // pX
data[indx][1][1] = gip.pixelsXY[indx][1]; // pY
data[indx][2][0] = gip.pixelsMask[indx]; // weighth
}
double [][] coeff = polynomialApproximation.quadraticApproximation(
data,
true); // force linear
Matrix mXY_UV=new Matrix(new double[][] {{coeff[0][0],coeff[0][1]},{coeff[1][0],coeff[1][1]}});
if (!(new LUDecomposition(mXY_UV)).isNonsingular()){
if (debugLevel>2) {
System.out.println("Skipping singular matrix for image #"+numImage);
}
continue;
}
Matrix mUV_XY= mXY_UV.inverse();
Matrix mUV_HA = mUV_XY.times(mXY_HA);
dUV_image [numImage] = mUV_HA.getArray();
dUV_weights[numImage] = wsx + wsy;
} else {
System.out.println ("Bug: ga/gh are not among the parameters, par_gh="+par_gh+", par_ga="+par_ga);
}
}
*/
synchronizedCombinePartialJacobians(
JtByJmod, //Transposed Jacobian multiplied by Jacobian
JtByDiff,
......@@ -5970,7 +6097,6 @@ List calibration
numPars );
final int numFinished=imageFinishedAtomic.getAndIncrement();
// IJ.showProgress(progressValues[numFinished]);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
......@@ -5983,8 +6109,6 @@ List calibration
if (stopRequested.get()==1){ // ASAP
interruptedAtomic.set(true);
}
// if (debugLevel>1) System.out.println("IJ.showProgress("+progressValues[numImage]+")");
// if (debugLevel>1) IJ.showStatus("Progress "+IJ.d2s(100*progressValues[numImage],2)+"%");
}
}
};
......@@ -6009,10 +6133,31 @@ List calibration
lMAArrays.jTByDiff=JtByDiff;
if (debugLevel>3){
String msg="calculateJacobianArrays() lMAArrays.jTByJ trace=";
for (int ii=0;ii<numPars;ii++) msg+=IJ.d2s(lMAArrays.jTByJ[ii][ii],5);
for (int ii=0;ii<numPars;ii++) msg+=IJ.d2s(lMAArrays.jTByJ[ii][ii],5)+" ";
System.out.println(msg);
}
if (dTA_dUV != null) {
double [][] dUV_average = new double [2][2];
for (int i = 0; i < 2; i++) for (int j=0; j<2; j++) dUV_average[i][j] = 0.0;
double sw = 0.0;
for (int ni = 0; ni < dUV_weights.length; ni++) {
double w = dUV_weights[ni];
if (w > 0.0) {
for (int i = 0; i < 2; i++) for (int j=0; j<2; j++) {
dUV_average[i][j] += w *dUV_image[ni][i][j] ;
}
sw += w;
}
}
if (sw > 0) {
for (int i = 0; i < 2; i++) for (int j=0; j<2; j++) {
dUV_average[i][j] /= sw;
}
Matrix mdTA_dUV = (new Matrix(dUV_average)).inverse();
this.dTA_dUV = mdTA_dUV.getArray();
}
}
return lMAArrays;
}
......@@ -6052,7 +6197,7 @@ List calibration
M.print(10, 5);
}
Matrix Mb=new Matrix(lMAArrays.jTByDiff,numPars); // single column
Matrix Mb=new Matrix(lMAArrays.jTByDiff,numPars); // single column {NaN,NaN}
if (!(new LUDecomposition(M)).isNonsingular()){
double [][] arr=M.getArray();
System.out.println("Singular Matrix "+arr.length+"x"+arr[0].length);
......@@ -6081,9 +6226,11 @@ List calibration
* @param numSeries
* @return array of two booleans: { improved, finished}
*/
public boolean [] stepLevenbergMarquardtFirst(int numSeries){
public boolean [] stepLevenbergMarquardtFirst(
int numSeries,
boolean calc_dUV){
double [] deltas=null;
if (this.currentVector==null) {
if ((this.currentVector==null) || (this.currentVector.length==0)) { // length==0 was debugging
int filter=this.filterForAll;
if (this.askFilter) filter=selectFilter(filter);
initFittingSeries(false,filter,numSeries); // first step in series
......@@ -6108,11 +6255,12 @@ List calibration
// IJ.showStatus(this.seriesNumber+": "+"Step #"+this.iterationStepNumber+" RMS="+IJ.d2s(this.currentRMS,8)+ " ("+IJ.d2s(this.firstRMS,8)+")");
IJ.showStatus(this.seriesNumber+": initial Jacobian matrix calculation. Points:"+this.Y.length+" Parameters:"+this.currentVector.length);
}
if (this.debugLevel>1) {
if (this.debugLevel >1) {
System.out.println(this.seriesNumber+": initial Jacobian matrix calculation. Points:"+this.Y.length+" Parameters:"+this.currentVector.length);
}
if (this.threadedLMA) {
this.currentfX=new double[this.Y.length];
this.dTA_dUV = calc_dUV ? (new double [2][2]): null;
// deltas=solveLevenbergMarquardtThreaded(
this.lMAArrays=calculateJacobianArrays(
this.fittingStrategy.selectedImages(), // selected images to process
......@@ -6123,6 +6271,7 @@ List calibration
this.targetXYZ, // this.targetXYZ
this.weightFunction, // may be null - make it twice smaller? - same for X and Y?
this.lensDistortionParameters,
this.dTA_dUV,// final double [][][] dUV_average, // null or double [selectedImages.length][][] to return per-image {{dU/dAz,dU/dTl}{dV/dAz,dV/dTl}}
// this.lambda,
this.threadsMax,
this.updateStatus);
......@@ -6135,7 +6284,7 @@ List calibration
// deltas=solveLevenbergMarquardt(this.currentfX,this.lambda);
}
// add termes that push selected extrinsic parameters towards average (global, per station, per tilt-station)
this.currentRMSPure= calcErrorDiffY(this.currentfX);
this.currentRMSPure= calcErrorDiffY(this.currentfX) +0.0;
if ((this.fittingStrategy.varianceModes!=null) && (this.fittingStrategy.varianceModes[numSeries]!=this.fittingStrategy.varianceModeDisabled)) {
this.fittingStrategy.addVarianceToLMA(
numSeries,
......@@ -6238,6 +6387,7 @@ List calibration
this.targetXYZ, // this.targetXYZ
this.weightFunction, // may be null - make it twice smaller? - same for X and Y?
this.lensDistortionParameters,
this.dTA_dUV,// final double [][][] dUV_average, // null or double [selectedImages.length][][] to return per-image {{dU/dAz,dU/dTl}{dV/dAz,dV/dTl}}
// this.lambda,
this.threadsMax,
this.updateStatus);
......@@ -6719,7 +6869,7 @@ List calibration
/// this.pixelCorrectionHeight=height;
// }
if (this.pixelCorrection==null) {
if (this.debugLevel>1) System.out.println("Initializing pixelCorrection array");
if (this.debugLevel>1) System.out.println("Initializing pixelCorrection array...");
this.pixelCorrection=new double [sensorXYCorr.length][][];
this.pathNames=new String[sensorXYCorr.length];
for (int i=0;i<this.pixelCorrection.length;i++){
......@@ -6775,8 +6925,15 @@ List calibration
this.pixelCorrection[i][5]=sensorXYCorr[i][indxB];
} else {
for (int n=3;n<numLayers;n++){
this.pixelCorrection[i][n]=new double[this.pixelCorrection[0].length];
for (int j=0;j<this.pixelCorrection[i][0].length;j++) this.pixelCorrection[i][n][j]=1.0;
// this.pixelCorrection[i][n]=new double[this.pixelCorrection[0].length];
this.pixelCorrection[i][n]=new double[this.pixelCorrection[i][0].length]; // number of pixels
for (int j=0;j<this.pixelCorrection[i][0].length;j++) {
if ((i >= pixelCorrection.length) || (n >= pixelCorrection[i].length) || (j >= pixelCorrection[i][n].length)){
System.out.println("i="+i+", n="+n+", j="+j);
continue;
}
this.pixelCorrection[i][n][j]=1.0; // java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 6
}
}
}
......@@ -6910,7 +7067,15 @@ List calibration
float [][]pixels=new float [titles.length][length]; // dx, dy, sensor mask,v-r,v-g,v-b
// assuming all sensors have the same dimension
double [] mask=null;
if (distortionCalibrationData.sensorMasks.length<=numSensor) return null; // no data
if (distortionCalibrationData.sensorMasks == null) {
if (this.debugLevel>0) {
System.out.println("sensorMasks are null, calculating");
}
distortionCalibrationData.calculateSensorMasks();
}
if (distortionCalibrationData.sensorMasks.length<=numSensor) return null; // no data (make if distortionCalibrationData.sensorMasks==null
if ((distortionCalibrationData.sensorMasks!=null) &&
(distortionCalibrationData.sensorMasks[numSensor]!=null)){
mask=distortionCalibrationData.sensorMasks[numSensor];
......@@ -6924,7 +7089,15 @@ List calibration
} else {
pixels[0][index]= (float) pixelCorr[0][index];
pixels[1][index]= (float) pixelCorr[1][index];
for (int n=3;n<pixels.length;n++) pixels[n][index]= (float) pixelCorr[n][index];
for (int n=3;n<pixels.length;n++) {
if (pixelCorr[n] != null) {
if ((n>=pixels.length) || (index >= pixels[n].length) || (n>=pixelCorr.length) || (index >= pixelCorr[n].length)) {
System.out.println (" Bug: n="+n+", index="+index);
continue;
}
pixels[n][index]= (float) pixelCorr[n][index]; // java.lang.NullPointerException
}
}
}
// get sensor mask here
pixels[2][index]= (mask==null)? 1.0f:((float) mask[index]);
......@@ -8273,11 +8446,20 @@ List calibration
return true;
}
public boolean LevenbergMarquardt(
boolean openDialog,
boolean dry_run){ // do not save results
return LevenbergMarquardt(
openDialog,
dry_run,
false);
}
public boolean LevenbergMarquardt(
boolean openDialog,
boolean dry_run, // do not save results
boolean calc_dUV){
if (this.fittingStrategy==null) {
String msg="Fitting strategy does not exist, exiting";
IJ.showMessage("Error",msg);
......@@ -8294,7 +8476,7 @@ List calibration
boolean wasLastSeries=false;
while (true) { // loop for the same series
boolean [] state=stepLevenbergMarquardtFirst(this.seriesNumber);
boolean [] state=stepLevenbergMarquardtFirst(this.seriesNumber, calc_dUV);
if (!this.fittingStrategy.isSeriesValid(this.seriesNumber)){
System.out.println("Series "+this.seriesNumber+" is invalid when weight function filters are applied (probably removed some images)");
return false;
......
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