Commit 9b8069a8 authored by Andrey Filippov's avatar Andrey Filippov

Refactored - split Distortions.java into individual class files

parent 9739c913
......@@ -371,7 +371,7 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
1,1};
public static Distortions LENS_DISTORTIONS;
public static Distortions.PatternParameters PATTERN_PARAMETERS=new Distortions.PatternParameters(
public static PatternParameters PATTERN_PARAMETERS=new PatternParameters(
viewMap,
1, // initial number of stations
3022.6, // double patternWidth; // pattern full width in mm
......@@ -379,10 +379,10 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
41.6667, // patternHalfPeriod; // distance between opposite sign nodes
5.0 // double patternTilt; // pattern tilt (degrees) - U clockwise from X-right (V clockwise from Y-down)
);
// public static Distortions.LensDistortionParameters LENS_DISTORTION_PARAMETERS=new Distortions.LensDistortionParameters(
// public static LensDistortionParameters LENS_DISTORTION_PARAMETERS=new LensDistortionParameters(
// public static Distortions.LensDistortionParameters LENS_DISTORTION_PARAMETERS=LENS_DISTORTIONS.new LensDistortionParameters(
public static Distortions.LensDistortionParameters LENS_DISTORTION_PARAMETERS=(new Distortions()).new LensDistortionParameters(
// public static LensDistortionParameters LENS_DISTORTION_PARAMETERS=LENS_DISTORTIONS.new LensDistortionParameters(
public static LensDistortionParameters LENS_DISTORTION_PARAMETERS=new LensDistortionParameters(
4.5, // double focalLength
2.2, // double pixelSize (um)
2.8512, //double distortionRadius mm - half width of the sensor
......@@ -406,7 +406,7 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
true// boolean flipVertical // acquired image is mirrored vertically (mirror used)
);
// public static double [] defaultGoniometerPosition={0.0, 0.0, 2360};
public static Distortions.EyesisCameraParameters EYESIS_CAMERA_PARAMETERS=new Distortions.EyesisCameraParameters(
public static EyesisCameraParameters EYESIS_CAMERA_PARAMETERS=new EyesisCameraParameters(
1, //int numStations,
true, //false, // boolean isTripod=false; // when true - make goniometerHorizontal rotation around "vertical" axis and "goniometerAxial" - around
0.0, // double goniometerHorizontal, // goniometer rotation around "horizontal" axis (tilting from the target - positive)
......@@ -491,8 +491,8 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
);
public static Distortions.RefineParameters REFINE_PARAMETERS = new Distortions.RefineParameters();
public static Distortions.DistortionCalibrationData DISTORTION_CALIBRATION_DATA=null;
// public static Distortions.FittingStrategy FITTING_STRATEGY=null;
public static DistortionCalibrationData DISTORTION_CALIBRATION_DATA=null;
// public static FittingStrategy FITTING_STRATEGY=null;
// public static boolean ADVANCED_MODE=false;
public static boolean ADVANCED_MODE=true;
......@@ -532,7 +532,7 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
public static CalibrationHardwareInterface.CamerasInterface CAMERAS=new CalibrationHardwareInterface.CamerasInterface(26,LASERS);
public static CalibrationHardwareInterface.FocusingMotors MOTORS=new CalibrationHardwareInterface.FocusingMotors();
public static Distortions.DistortionProcessConfiguration DISTORTION_PROCESS_CONFIGURATION=new Distortions.DistortionProcessConfiguration();
public static DistortionProcessConfiguration DISTORTION_PROCESS_CONFIGURATION=new DistortionProcessConfiguration();
public static LensAdjustment.FocusMeasurementParameters FOCUS_MEASUREMENT_PARAMETERS= new LensAdjustment.FocusMeasurementParameters(MOTORS.curpos);
public static CalibrationHardwareInterface.GoniometerMotors GONIOMETER_MOTORS= new CalibrationHardwareInterface.GoniometerMotors();
......@@ -1106,7 +1106,7 @@ if (MORE_BUTTONS) {
ABERRATIONS_PARAMETERS,
LENS_DISTORTIONS, // should be initialized, after update DISTORTION_CALIBRATION_DATA from this
PATTERN_PARAMETERS,
EYESIS_CAMERA_PARAMETERS, //Distortions.EyesisCameraParameters eyesisCameraParameters,
EYESIS_CAMERA_PARAMETERS, //EyesisCameraParameters eyesisCameraParameters,
UPDATE_STATUS,
DEBUG_LEVEL
);
......@@ -2273,8 +2273,8 @@ if (MORE_BUTTONS) {
" +DISTORTION_CALIBRATION_DATA.eyesisCameraParameters.goniometerHorizontal.length="+DISTORTION_CALIBRATION_DATA.eyesisCameraParameters.goniometerHorizontal.length);
}
Distortions.DistortionCalibrationData dcd=(DISTORTION_CALIBRATION_DATA!=null)?DISTORTION_CALIBRATION_DATA:
new Distortions.DistortionCalibrationData(EYESIS_CAMERA_PARAMETERS);
DistortionCalibrationData dcd=(DISTORTION_CALIBRATION_DATA!=null)?DISTORTION_CALIBRATION_DATA:
new DistortionCalibrationData(EYESIS_CAMERA_PARAMETERS);
if (DEBUG_LEVEL>1) System.out.println("+++++++++++ dcd.eyesisCameraParameters.numStations="+dcd.eyesisCameraParameters.numStations+
" +dcd.eyesisCameraParameters.goniometerHorizontal.length="+dcd.eyesisCameraParameters.goniometerHorizontal.length);
dcd.listCameraParameters();
......@@ -2342,7 +2342,7 @@ if (MORE_BUTTONS) {
PATTERN_PARAMETERS.debugLevel=MASTER_DEBUG_LEVEL;
EYESIS_CAMERA_PARAMETERS.updateNumstations (numStations);
//if (MASTER_DEBUG_LEVEL==0) return; //TODO: Remove - just debugging
DISTORTION_CALIBRATION_DATA=new Distortions.DistortionCalibrationData(
DISTORTION_CALIBRATION_DATA=new DistortionCalibrationData(
gridFiles,
PATTERN_PARAMETERS,
EYESIS_CAMERA_PARAMETERS,
......@@ -2363,7 +2363,7 @@ if (MORE_BUTTONS) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
LENS_DISTORTIONS=new Distortions(LENS_DISTORTION_PARAMETERS,PATTERN_PARAMETERS,REFINE_PARAMETERS);
DISTORTION_CALIBRATION_DATA=new Distortions.DistortionCalibrationData(gridFiles,PATTERN_PARAMETERS,EYESIS_CAMERA_PARAMETERS);
DISTORTION_CALIBRATION_DATA=new DistortionCalibrationData(gridFiles,PATTERN_PARAMETERS,EYESIS_CAMERA_PARAMETERS);
LENS_DISTORTIONS.initImageSet(
DISTORTION_CALIBRATION_DATA,
EYESIS_CAMERA_PARAMETERS
......@@ -2396,9 +2396,9 @@ if (MORE_BUTTONS) {
if (label.equals("Restore Calibration")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
String defaultPath= (DISTORTION_CALIBRATION_DATA!=null)?DISTORTION_CALIBRATION_DATA.pathName:"";
// public static Distortions.DistortionCalibrationData DISTORTION_CALIBRATION_DATA=null;
Distortions.DistortionCalibrationData oldDISTORTION_CALIBRATION_DATA=DISTORTION_CALIBRATION_DATA;
DISTORTION_CALIBRATION_DATA=new Distortions.DistortionCalibrationData(
// public static DistortionCalibrationData DISTORTION_CALIBRATION_DATA=null;
DistortionCalibrationData oldDISTORTION_CALIBRATION_DATA=DISTORTION_CALIBRATION_DATA;
DISTORTION_CALIBRATION_DATA=new DistortionCalibrationData(
false,
defaultPath,
PATTERN_PARAMETERS,
......@@ -2434,7 +2434,7 @@ if (MORE_BUTTONS) {
}
LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
if (DEBUG_LEVEL>2) System.out.println("New Strategy");
LENS_DISTORTIONS.fittingStrategy=new Distortions.FittingStrategy(DISTORTION_CALIBRATION_DATA);
LENS_DISTORTIONS.fittingStrategy=new FittingStrategy(DISTORTION_CALIBRATION_DATA);
LENS_DISTORTIONS.fittingStrategy.debugLevel=DEBUG_LEVEL;
IJ.showMessage("Empty new strategy initialized");
return;
......@@ -2457,7 +2457,7 @@ if (MORE_BUTTONS) {
LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
if (LENS_DISTORTIONS.fittingStrategy==null) {
if (DISTORTION_CALIBRATION_DATA==null) return;
LENS_DISTORTIONS.fittingStrategy=new Distortions.FittingStrategy(DISTORTION_CALIBRATION_DATA);
LENS_DISTORTIONS.fittingStrategy=new FittingStrategy(DISTORTION_CALIBRATION_DATA);
}
LENS_DISTORTIONS.fittingStrategy.debugLevel=DEBUG_LEVEL;
LENS_DISTORTIONS.fittingStrategy.selectStrategy(LENS_DISTORTIONS.seriesNumber);
......@@ -2494,9 +2494,9 @@ if (MORE_BUTTONS) {
LENS_DISTORTIONS=new Distortions(LENS_DISTORTION_PARAMETERS,PATTERN_PARAMETERS,REFINE_PARAMETERS,this.SYNC_COMMAND.stopRequested);
}
LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
Distortions.FittingStrategy fs=LENS_DISTORTIONS.fittingStrategy; // save old value
FittingStrategy fs=LENS_DISTORTIONS.fittingStrategy; // save old value
String defaultPath= ((fs!=null) && (fs.pathName != null) && (fs.pathName.length()>0)) ? fs.pathName : "";
LENS_DISTORTIONS.fittingStrategy=new Distortions.FittingStrategy(
LENS_DISTORTIONS.fittingStrategy=new FittingStrategy(
false,
defaultPath,
DISTORTION_CALIBRATION_DATA);
......@@ -3821,7 +3821,7 @@ if (MORE_BUTTONS) {
if (findCenter){
// Read required calibration files
// initial calibration
DISTORTION_CALIBRATION_DATA=new Distortions.DistortionCalibrationData(
DISTORTION_CALIBRATION_DATA=new DistortionCalibrationData(
true, // skip dialog if file exists
FOCUS_MEASUREMENT_PARAMETERS.initialCalibrationFile,
PATTERN_PARAMETERS,
......@@ -3849,7 +3849,7 @@ if (MORE_BUTTONS) {
}
LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
LENS_DISTORTIONS.fittingStrategy=new Distortions.FittingStrategy(
LENS_DISTORTIONS.fittingStrategy=new FittingStrategy(
true,
FOCUS_MEASUREMENT_PARAMETERS.strategyFile,
DISTORTION_CALIBRATION_DATA);
......@@ -3892,7 +3892,7 @@ if (MORE_BUTTONS) {
if (DEBUG_LEVEL>0) System.out.println("Finished LMA at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
int stationNumber=0;
// Read camera parameters
Distortions.EyesisCameraParameters camPars=
EyesisCameraParameters camPars=
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.eyesisCameraParameters;
double threadPitch=0.35; // M1.6
double dPx0=camPars.eyesisSubCameras[stationNumber][0].px0-(camPars.sensorWidth/2)-FOCUS_MEASUREMENT_PARAMETERS.centerDeltaX;
......@@ -5951,7 +5951,7 @@ if (MORE_BUTTONS) {
CAMERAS, // CalibrationHardwareInterface.CamerasInterface cameras,
DISTORTION, //MatchSimulatedPattern.DistortionParameters distortion,
PATTERN_DETECT, //MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
EYESIS_CAMERA_PARAMETERS, //Distortions.EyesisCameraParameters eyesisCameraParameters,
EYESIS_CAMERA_PARAMETERS, //EyesisCameraParameters eyesisCameraParameters,
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointers
SIMUL, //SimulationPattern.SimulParameters simulParametersDefault,
GONIOMETER_PARAMETERS, //LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
......@@ -5982,7 +5982,7 @@ if (MORE_BUTTONS) {
CAMERAS, // CalibrationHardwareInterface.CamerasInterface cameras,
DISTORTION, //MatchSimulatedPattern.DistortionParameters distortion,
PATTERN_DETECT, //MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
EYESIS_CAMERA_PARAMETERS, //Distortions.EyesisCameraParameters eyesisCameraParameters,
EYESIS_CAMERA_PARAMETERS, //EyesisCameraParameters eyesisCameraParameters,
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointers
SIMUL, //SimulationPattern.SimulParameters simulParametersDefault,
GONIOMETER_PARAMETERS, //LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
......@@ -5997,8 +5997,8 @@ if (MORE_BUTTONS) {
// calculate angular size of the target as visible from the camera
/*
Distortions.DistortionCalibrationData dcd=(DISTORTION_CALIBRATION_DATA!=null)?DISTORTION_CALIBRATION_DATA:
new Distortions.DistortionCalibrationData(EYESIS_CAMERA_PARAMETERS);*/
DistortionCalibrationData dcd=(DISTORTION_CALIBRATION_DATA!=null)?DISTORTION_CALIBRATION_DATA:
new DistortionCalibrationData(EYESIS_CAMERA_PARAMETERS);*/
// double distanceToTarget=dcd.eyesisCameraParameters.GXYZ[2];
double distanceToTarget=GONIOMETER_PARAMETERS.targetDistance;
double patternWidth= PATTERN_PARAMETERS.patternWidth;
......@@ -6420,7 +6420,7 @@ if (MORE_BUTTONS) {
CAMERAS, // CalibrationHardwareInterface.CamerasInterface cameras,
DISTORTION, //MatchSimulatedPattern.DistortionParameters distortion,
PATTERN_DETECT, //MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
EYESIS_CAMERA_PARAMETERS, //Distortions.EyesisCameraParameters eyesisCameraParameters,
EYESIS_CAMERA_PARAMETERS, //EyesisCameraParameters eyesisCameraParameters,
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointers
SIMUL, //SimulationPattern.SimulParameters simulParametersDefault,
GONIOMETER_PARAMETERS, //LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
......@@ -6433,7 +6433,7 @@ if (MORE_BUTTONS) {
System.out.println("GONIOMETER was initialized");
}
// initialize needed classes
DISTORTION_CALIBRATION_DATA=new Distortions.DistortionCalibrationData( // images are not setup yet
DISTORTION_CALIBRATION_DATA=new DistortionCalibrationData( // images are not setup yet
EYESIS_CAMERA_PARAMETERS); //EyesisCameraParameters eyesisCameraParameters
if ((LENS_DISTORTIONS!=null) && (LENS_DISTORTIONS.fittingStrategy!=null)) {
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData=DISTORTION_CALIBRATION_DATA;
......@@ -6487,8 +6487,8 @@ if (MORE_BUTTONS) {
// PATTERN_DETECT, //MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
// LASER_POINTERS, //MatchSimulatedPattern.LaserPointer laserPointer, // null OK
// SIMUL, //SimulationPattern.SimulParameters simulParametersDefault,
DISTORTION_CALIBRATION_DATA, // Distortions.DistortionCalibrationData distortionCalibrationData,
PATTERN_PARAMETERS, //Distortions.PatternParameters patternParameters, // should not be null
DISTORTION_CALIBRATION_DATA, // DistortionCalibrationData distortionCalibrationData,
PATTERN_PARAMETERS, //PatternParameters patternParameters, // should not be null
LENS_DISTORTIONS, //Distortions lensDistortions, // should not be null
COMPONENTS.equalizeGreens, //boolean equalizeGreens,
THREADS_MAX, // int threadsMax,
......@@ -6519,7 +6519,7 @@ if (MORE_BUTTONS) {
CAMERAS, // CalibrationHardwareInterface.CamerasInterface cameras,
DISTORTION, //MatchSimulatedPattern.DistortionParameters distortion,
PATTERN_DETECT, //MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
EYESIS_CAMERA_PARAMETERS, //Distortions.EyesisCameraParameters eyesisCameraParameters,
EYESIS_CAMERA_PARAMETERS, //EyesisCameraParameters eyesisCameraParameters,
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointers
SIMUL, //SimulationPattern.SimulParameters simulParametersDefault,
GONIOMETER_PARAMETERS, //LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
......@@ -6547,8 +6547,8 @@ if (MORE_BUTTONS) {
GONIOMETER.testHintedTarget (
images, //CAMERAS.getImages(0), // last acquired images with number of pointers detected>=0
LENS_DISTORTIONS, //Distortions lensDistortions, // should not be null
DISTORTION_CALIBRATION_DATA, // Distortions.DistortionCalibrationData distortionCalibrationData,
PATTERN_PARAMETERS, //Distortions.PatternParameters patternParameters, // should not be null
DISTORTION_CALIBRATION_DATA, // DistortionCalibrationData distortionCalibrationData,
PATTERN_PARAMETERS, //PatternParameters patternParameters, // should not be null
COMPONENTS.equalizeGreens, //boolean equalizeGreens,
THREADS_MAX, // int threadsMax,
UPDATE_STATUS, //boolean updateStatus,
......@@ -6565,7 +6565,7 @@ if (MORE_BUTTONS) {
CAMERAS, // CalibrationHardwareInterface.CamerasInterface cameras,
DISTORTION, //MatchSimulatedPattern.DistortionParameters distortion,
PATTERN_DETECT, //MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
EYESIS_CAMERA_PARAMETERS, //Distortions.EyesisCameraParameters eyesisCameraParameters,
EYESIS_CAMERA_PARAMETERS, //EyesisCameraParameters eyesisCameraParameters,
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointers
SIMUL, //SimulationPattern.SimulParameters simulParametersDefault,
GONIOMETER_PARAMETERS, //LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
......@@ -6593,8 +6593,8 @@ if (MORE_BUTTONS) {
GONIOMETER.testHintedTarget (
CAMERAS.getImages(0), // last acquired images with number of pointers detected>=0
LENS_DISTORTIONS, //Distortions lensDistortions, // should not be null
DISTORTION_CALIBRATION_DATA, // Distortions.DistortionCalibrationData distortionCalibrationData,
PATTERN_PARAMETERS, //Distortions.PatternParameters patternParameters, // should not be null
DISTORTION_CALIBRATION_DATA, // DistortionCalibrationData distortionCalibrationData,
PATTERN_PARAMETERS, //PatternParameters patternParameters, // should not be null
COMPONENTS.equalizeGreens, //boolean equalizeGreens,
THREADS_MAX, // int threadsMax,
UPDATE_STATUS, //boolean updateStatus,
......@@ -10173,8 +10173,8 @@ if (MORE_BUTTONS) {
public boolean autoLoadFiles(
EyesisAberrations.AberrationParameters aberrationParameters,
Distortions distortions, // should be initialized, after update DISTORTION_CALIBRATION_DATA from this
Distortions.PatternParameters patternParameters,
Distortions.EyesisCameraParameters eyesisCameraParameters,
PatternParameters patternParameters,
EyesisCameraParameters eyesisCameraParameters,
boolean updateStstus,
int debugLevel
){
......@@ -10186,7 +10186,7 @@ if (MORE_BUTTONS) {
if (configPaths[0]==null) return false;
System.out.println("+++++++++++ autoLoadFiles() eyesisCameraParameters.numStations="+eyesisCameraParameters.numStations+
" +eyesisCameraParameters.goniometerHorizontal.length="+eyesisCameraParameters.goniometerHorizontal.length);
Distortions.DistortionCalibrationData dcd=new Distortions.DistortionCalibrationData(
DistortionCalibrationData dcd=new DistortionCalibrationData(
true,
configPaths[0],
patternParameters,
......@@ -10201,8 +10201,8 @@ if (MORE_BUTTONS) {
if (configPaths[1]!=null) {
Distortions.FittingStrategy fs=distortions.fittingStrategy; // save old value
distortions.fittingStrategy=new Distortions.FittingStrategy(
FittingStrategy fs=distortions.fittingStrategy; // save old value
distortions.fittingStrategy=new FittingStrategy(
true, // do not ask if specified
configPaths[1],
dcd);
......@@ -10240,7 +10240,7 @@ if (MORE_BUTTONS) {
boolean alwaysShow, // true overwrites focusMeasurementParameters.showResults
boolean alwaysSave, // true overwrites focusMeasurementParameters.saveResults
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
boolean updateStatus,
int debugLevel
......@@ -10369,7 +10369,7 @@ if (MORE_BUTTONS) {
double focusTolerance, // will exit after whatever comes first tolearance or number of iterations
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......@@ -10471,7 +10471,7 @@ if (MORE_BUTTONS) {
int numIterations, // maximal number of iterations (0 - suggest only, do not move). When calling from the button - first time single iteration, second time - as specified
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......@@ -10661,7 +10661,7 @@ if (MORE_BUTTONS) {
int numIterations, // maximal number of iterations (0 - suggest only, do not move). When calling from the button - first time single iteration, second time - as specified
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......@@ -10869,7 +10869,7 @@ if (MORE_BUTTONS) {
int numIterations, // maximal number of iterations (0 - suggest only, do not move). When calling from the button - first time single iteration, second time - as specified
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......@@ -10979,7 +10979,7 @@ if (MORE_BUTTONS) {
int numIterations, // maximal number of iterations (0 - suggest only, do not move). When calling from the button - first time single iteration, second time - as specified
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
boolean updateStatus,
......@@ -11052,7 +11052,7 @@ if (MORE_BUTTONS) {
int [] centerMotorPos, // null OK
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......@@ -11384,7 +11384,7 @@ if (MORE_BUTTONS) {
int [] centerMotorPos, // null OK
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......@@ -11514,7 +11514,7 @@ if (MORE_BUTTONS) {
int [] newMotorPos, // null OK
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......@@ -11555,7 +11555,7 @@ if (MORE_BUTTONS) {
int [] newMotorPos, // null OK
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......@@ -11721,7 +11721,7 @@ if (MORE_BUTTONS) {
int [] newMotorPos, // null OK
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......@@ -11815,7 +11815,7 @@ if (MORE_BUTTONS) {
int [] newMotorPos, // null OK
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......@@ -11984,7 +11984,7 @@ if (MORE_BUTTONS) {
int [] newMotorPos, // null OK
CalibrationHardwareInterface.FocusingMotors focusingMotors,
CalibrationHardwareInterface.CamerasInterface camerasInterface,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern, // should not bee null
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
boolean updateStatus,
......@@ -12049,7 +12049,7 @@ if (MORE_BUTTONS) {
public double [][] measurePSFMetrics(
ImagePlus imp_sel,
Distortions.LensDistortionParameters lensDistortionParameters,
LensDistortionParameters lensDistortionParameters,
MatchSimulatedPattern matchSimulatedPattern,
LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
**
** DistortionProcessConfiguration.java
**
** Copyright (C) 2011-2014 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** DistortionProcessConfiguration.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
import ij.IJ;
import ij.Prefs;
import ij.gui.GenericDialog;
import java.io.File;
import java.util.Properties;
public class DistortionProcessConfiguration{
public String sourceDirectory="";
public String gridDirectory= "";
public boolean useLaserPonters=true;
public boolean useNoPonters=true; // use images that do not have any lasre pointers
public boolean showAcquiredImages=true;
public boolean saveAcquiredImages=true;
public boolean selectSourceFiles = true;
public boolean removeOutOfGridPointers=true;
public boolean showGridImages=false;
public boolean saveGridImages=true;
public boolean overwriteResultFiles=false;
public int debugLevel=1;
public String selectSourceDirectory(boolean smart, String defaultPath, boolean newAllowed) {
String dir= CalibrationFileManagement.selectDirectory(
smart,
newAllowed, // save
"Source (acquired from the camera) image directory", // title
"Select source directory", // button
null, // filter
defaultPath); // this.sourceDirectory);
if (dir!=null) this.sourceDirectory=dir;
return dir;
}
public String selectGridFileDirectory(boolean smart, String defaultPath, boolean newAllowed) {
String dir= CalibrationFileManagement.selectDirectory(
smart,
newAllowed, // save
"Grid files directory (grid patterns extracted from the images)", // title
"Select grid files directory", // button
null, // filter
defaultPath); //this.sourceDirectory);
if (dir!=null) this.gridDirectory=dir;
return dir;
}
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"sourceDirectory", this.sourceDirectory);
properties.setProperty(prefix+"gridDirectory", this.gridDirectory);
properties.setProperty(prefix+"useLaserPonters", this.useLaserPonters+"");
properties.setProperty(prefix+"useNoPonters", this.useNoPonters+"");
properties.setProperty(prefix+"showAcquiredImages", this.showAcquiredImages+"");
properties.setProperty(prefix+"saveAcquiredImages", this.saveAcquiredImages+"");
properties.setProperty(prefix+"selectSourceFiles", this.selectSourceFiles+"");
properties.setProperty(prefix+"removeOutOfGridPointers",this.removeOutOfGridPointers+"");
properties.setProperty(prefix+"showGridImages", this.showGridImages+"");
properties.setProperty(prefix+"saveGridImages", this.saveGridImages+"");
properties.setProperty(prefix+"overwriteResultFiles", this.overwriteResultFiles+"");
properties.setProperty(prefix+"debugLevel", this.debugLevel+"");
}
public void getProperties(String prefix,Properties properties){
if (properties.getProperty(prefix+"sourceDirectory")!=null)
this.sourceDirectory=properties.getProperty(prefix+"sourceDirectory");
if (properties.getProperty(prefix+"gridDirectory")!=null)
this.gridDirectory=properties.getProperty(prefix+"gridDirectory");
if (properties.getProperty(prefix+"useLaserPonters")!=null)
this.useLaserPonters=Boolean.parseBoolean(properties.getProperty(prefix+"useLaserPonters"));
if (properties.getProperty(prefix+"useNoPonters")!=null)
this.useNoPonters=Boolean.parseBoolean(properties.getProperty(prefix+"useNoPonters"));
if (properties.getProperty(prefix+"showAcquiredImages")!=null)
this.showAcquiredImages=Boolean.parseBoolean(properties.getProperty(prefix+"showAcquiredImages"));
if (properties.getProperty(prefix+"saveAcquiredImages")!=null)
this.saveAcquiredImages=Boolean.parseBoolean(properties.getProperty(prefix+"saveAcquiredImages"));
if (properties.getProperty(prefix+"selectSourceFiles")!=null)
this.selectSourceFiles=Boolean.parseBoolean(properties.getProperty(prefix+"selectSourceFiles"));
if (properties.getProperty(prefix+"removeOutOfGridPointers")!=null)
this.removeOutOfGridPointers=Boolean.parseBoolean(properties.getProperty(prefix+"removeOutOfGridPointers"));
if (properties.getProperty(prefix+"showGridImages")!=null)
this.showGridImages=Boolean.parseBoolean(properties.getProperty(prefix+"showGridImages"));
if (properties.getProperty(prefix+"saveGridImages")!=null)
this.saveGridImages=Boolean.parseBoolean(properties.getProperty(prefix+"saveGridImages"));
if (properties.getProperty(prefix+"overwriteResultFiles")!=null)
this.overwriteResultFiles=Boolean.parseBoolean(properties.getProperty(prefix+"overwriteResultFiles"));
if (properties.getProperty(prefix+"debugLevel")!=null)
this.debugLevel=Integer.parseInt(properties.getProperty(prefix+"debugLevel"));
}
public boolean showDialog(String title) {
GenericDialog gd = new GenericDialog(title);
gd.addStringField("Source (acquired from the camera) image directory, blank will open selection window",this.sourceDirectory,40);
gd.addStringField("Grid files directory (grid patterns extracted from the images, blank will open selection window)",this.gridDirectory,40);
gd.addCheckbox ("Locate laser pointers for each image", this.useLaserPonters);
gd.addCheckbox ("Use images that do not contain laser pointers", this.useLaserPonters);
gd.addCheckbox ("Show images after acquisition", this.showAcquiredImages);
gd.addCheckbox ("Save acquired images", this.saveAcquiredImages);
gd.addCheckbox ("Individually select source image (false use all directory)", this.selectSourceFiles);
gd.addCheckbox ("Remove detected laser pointers if they are outside of the grid", this.removeOutOfGridPointers);
gd.addCheckbox ("Show grid files as images", this.showGridImages);
gd.addCheckbox ("Save grid files", this.saveGridImages);
gd.addCheckbox ("Overwrite existing result files", this.overwriteResultFiles);
gd.addNumericField("Debug level", this.debugLevel,0);
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
String newSourceDirectory= gd.getNextString();
String newGridDirectory= gd.getNextString();
this.useLaserPonters= gd.getNextBoolean();
this.useLaserPonters= gd.getNextBoolean();
this.showAcquiredImages= gd.getNextBoolean();
this.saveAcquiredImages= gd.getNextBoolean();
this.selectSourceFiles= gd.getNextBoolean();
this.removeOutOfGridPointers=gd.getNextBoolean();
this.showGridImages= gd.getNextBoolean();
this.saveGridImages= gd.getNextBoolean();
this.overwriteResultFiles= gd.getNextBoolean();
this.debugLevel= (int) gd.getNextNumber();
System.out.println("1.newSourceDirectory = "+newSourceDirectory);
System.out.println("1.newGridDirectory = "+ newGridDirectory);
if ((newSourceDirectory.length()==0) || (newSourceDirectory.indexOf('?')>=0))
newSourceDirectory= selectSourceDirectory(false, this.sourceDirectory, true);
else
newSourceDirectory= selectSourceDirectory(true, newSourceDirectory, true); // if matches, no dialog
if (newSourceDirectory!=null) this.sourceDirectory=newSourceDirectory;
if ((newGridDirectory.length()==0) || (newGridDirectory.indexOf('?')>=0))
newGridDirectory= selectGridFileDirectory(false, this.gridDirectory, true);
else
newGridDirectory= selectGridFileDirectory(true, newGridDirectory, true);
if (newGridDirectory!=null) this.gridDirectory=newGridDirectory;
// System.out.println("2.newSourceDirectory = "+newSourceDirectory);
// System.out.println("2.newGridDirectory = "+ newGridDirectory);
// System.out.println("this.sourceDirectory = "+this.sourceDirectory);
// System.out.println("this.gridDirectory = "+ this.gridDirectory);
return true;
}
public String [] selectSourceFiles(){
return selectSourceFiles(!this.selectSourceFiles);
}
public String [] selectSourceFiles(boolean allFiles){
String [] extensions={".tif",".tiff"};
if (this.sourceDirectory.length()==0){
String newSourceDirectory= selectSourceDirectory(true, this.sourceDirectory, true);
if (newSourceDirectory!=null) this.sourceDirectory=newSourceDirectory;
}
String [] defaultPaths={this.sourceDirectory+Prefs.getFileSeparator()};
if (this.sourceDirectory.length()==0){
defaultPaths[0]="";
}
CalibrationFileManagement.MultipleExtensionsFileFilter sourceFilter =
new CalibrationFileManagement.MultipleExtensionsFileFilter("",extensions,"Source files");
String [] sourceFiles=null;
if (allFiles){
File dir= new File (this.sourceDirectory);
if (this.debugLevel>1) System.out.println("selectSourceFiles, dir="+this.sourceDirectory);
if (!dir.exists()) {
String error="Source directory "+this.sourceDirectory+" does not exist.";
IJ.showMessage("No files selected");
if (this.debugLevel>1) System.out.println("selectSourceFiles() ERROR:"+error);
return null;
}
File [] fileList=dir.listFiles(sourceFilter);
if (this.debugLevel>1) System.out.println("Source directory "+this.sourceDirectory+" has "+fileList.length+" files.");
sourceFiles = new String[fileList.length];
for (int i=0;i<sourceFiles.length;i++) sourceFiles[i]=fileList[i].getPath();
} else {
new CalibrationFileManagement.MultipleExtensionsFileFilter("",extensions,"Source files");
sourceFiles=CalibrationFileManagement.selectFiles(false,
"Select Source files, saved as TIFF",
"Select",
sourceFilter,
defaultPaths); // String [] defaultPaths); //this.sourceDirectory // null
if ((sourceFiles==null) || (sourceFiles.length==0)) {
if (this.debugLevel>1) System.out.println("selectSourceFiles() ERROR: No files selected");
IJ.showMessage("No files selected");
return null;
}
}
return sourceFiles;
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -972,7 +972,7 @@ public class EyesisAberrations {
public String [][] preparePartialKernelsFilesList(
int debugLevel){
Distortions.DistortionCalibrationData distortionCalibrationData= distortions.fittingStrategy.distortionCalibrationData;
DistortionCalibrationData distortionCalibrationData= distortions.fittingStrategy.distortionCalibrationData;
boolean [] selectedImages=distortions.fittingStrategy.selectedImagesNoBadKernels(this.aberrationParameters.allImages?-1:this.aberrationParameters.seriesNumber); // negative series number OK - will select all enabled
int num=0;
for (int imgNum=0;imgNum<selectedImages.length;imgNum++) if (selectedImages[imgNum]) num++;
......@@ -1072,7 +1072,7 @@ public class EyesisAberrations {
int loopDebugLevel, // debug level used inside loops
int debugLevel
){
Distortions.DistortionCalibrationData distortionCalibrationData= distortions.fittingStrategy.distortionCalibrationData;
DistortionCalibrationData distortionCalibrationData= distortions.fittingStrategy.distortionCalibrationData;
boolean partialToReprojected=this.aberrationParameters.partialToReprojected;
boolean applySensorCorrection=this.aberrationParameters.partialCorrectSensor;
// this.distortions is set to top level LENS_DISTORTIONS
......
/*
**
** EyesisCameraParameters.java
**
** Copyright (C) 2011-2014 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** EyesisCameraParameters.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
import ij.gui.GenericDialog;
import java.util.Properties;
import org.apache.commons.configuration.XMLConfiguration;
public class EyesisCameraParameters{
public double [] goniometerHorizontal; // goniometer rotation around "horizontal" axis (tilting from the target - positive)
public double [] goniometerAxial; // goniometer rotation around Eyesis axis (clockwise in plan - positive
public EyesisSubCameraParameters [][] eyesisSubCameras=null;
public double [] interAxisDistance; // distance in mm between two goniometer axes
public double [] interAxisAngle; // angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
// clockwise when eyesis is in 'normal' position, looking to the target
public double [] horAxisErrPhi; // angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
public double [] horAxisErrPsi; // angle in degrees "horizontal" goniometer axis is rotated around moving X axis (up)
public double [] entrancePupilForward; // common to all lenses - distance from the sensor to the lens entrance pupil
public double [] centerAboveHorizontal; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each SFE)
public double [][] GXYZ=null; // [numStations]{x,y,z} coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
// non-adjustable parameters, not parts of vector
public int numStations;
public double [] stationWeight; // reprojection error weights (close station - relax errors)
public boolean isTripod=false; // when true - make goniometerHorizontal rotation around "vertical" axis and "goniometerAxial" - around
// rotated horizontal.
public int sensorWidth= 2592;
public int sensorHeight= 1936;
public int shrinkGridForMask=4; //2; //shrink detected grids by one point for/vert this number of times before calculating masks
public double maskBlurSigma= -3; //2.0; // blur sensor masks (>0 - pixels, <0 - in grid units)
public int decimateMasks= 1;
public double badNodeThreshold=0.1; // 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=50; // 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)
public double weightMultiExponent= 1.0;
public double weightDiameterExponent=1.0; // if( >0) use grid diameter to scale weights of this image
public double weightYtoX=1.0; // relative Y-to-X errors weight (to somewhat compensate for rectabular shape of the sensor)
public double minimalGridContrast=0.4; // (normally max ~0.8)
public double shrinkBlurSigma = 4.0;
public double shrinkBlurLevel = 0.5;
public double balanceChannelWeightsMode=-1.0; // <0 - use defaults, 0 - keep, >0 balance by number of points to this power
public double removeOverRMS=2.0; // error is multiplied by weight function before comparison (more permissive on the borders
public double removeOverRMSNonweighted=4.0; // error is not multiplied (no more permissions on tyhe borders
public int [] extrinsicIndices={6,7,8,9,10,11,12,13,14,15,16}; //support variations
public double [][] variationsDefaults={
null, // 0
null, // 1
null, // 2
null, // 3
null, // 4
null, // 5
{10.0,0.1,0.0,1.0}, // 6 goniometerHorizontal
{10.0,0.1,0.0,1.0}, // 7 goniometerAxial
{10.0,2.0,0.0,1.0}, // 8 interAxisDistance
{10.0,0.2,0.0,1.0}, // 9 interAxisAngle
{10.0,0.2,0.0,1.0}, // 10 horAxisErrPhi
{10.0,0.2,0.0,1.0}, // 11 horAxisErrPsi
{10.0,2.0,0.0,1.0}, // 12 entrancePupilForward
{10.0,2.0,0.0,1.0}, // 13 centerAboveHorizontal
{10.0,2.0,0.0,1.0}, // 14 GXYZ0
{10.0,2.0,0.0,1.0}, // 15 GXYZ1
{10.0,2.0,0.0,1.0} // 16 GXYZ2
};
public int tiltIndex=6;
private ParameterVariationCosts [] parameterVariationCosts=null;
public boolean isExtrinsic (int index){
for (int i=0;i<this.extrinsicIndices.length; i++) if (this.extrinsicIndices[i]==index) return true;
return false;
}
public boolean isTilt (int index){
return (index==this.tiltIndex);
}
public boolean isVarianceCostSet(int index){
return (parameterVariationCosts!=null) && (index< parameterVariationCosts.length) && (parameterVariationCosts[index]!=null);
}
public double varianceCostScale(int index){
if (!isVarianceCostSet(index)) return -1.0;
return parameterVariationCosts[index].scale;
}
public double varianceCostVariationAbs(int index){
if (!isVarianceCostSet(index)) return -1.0;
return parameterVariationCosts[index].variationAbs;
}
public double varianceCostVariationDiff(int index){
if (!isVarianceCostSet(index)) return -1.0;
return parameterVariationCosts[index].variationDiff;
}
public double varianceCostVariationExponent(int index){
if (!isVarianceCostSet(index)) return -1.0;
return parameterVariationCosts[index].exponent;
}
public String varianceCostVariationName(int index){
if (!isVarianceCostSet(index)) return null;
return parameterVariationCosts[index].parName;
}
public int getVarParsLength(){
return parameterVariationCosts.length;
}
public boolean editCostProperties(
int index,
String parameterName,
String parameterDescription,
String parameterUnits) {
if (!isExtrinsic(index)) return false; // does not have varaince parameters
getVariationCosts();
if (parameterVariationCosts[index]==null) parameterVariationCosts[index]=new ParameterVariationCosts(
this.variationsDefaults[index][0],
this.variationsDefaults[index][1],
this.variationsDefaults[index][2],
this.variationsDefaults[index][3]);
return parameterVariationCosts[index].showVarianceDialog(
parameterName,
parameterDescription,
parameterUnits);
}
private ParameterVariationCosts [] getVariationCosts(){
if (this.parameterVariationCosts==null){
int max=0;
for (int i=0;i<this.extrinsicIndices.length; i++) if (this.extrinsicIndices[i]>max) max=this.extrinsicIndices[i];
this.parameterVariationCosts=new ParameterVariationCosts [max+1];
for (int i=0;i<this.parameterVariationCosts.length;i++) this.parameterVariationCosts[i]=null;
}
return this.parameterVariationCosts;
}
public void getCostsPropertiesXML(String prefix,XMLConfiguration hConfig){
getVariationCosts();
for (int i=0;i<this.extrinsicIndices.length;i++){
int index=this.extrinsicIndices[i];
// System.out.println("getCostsPropertiesXML("+prefix+",hconfig) index="+index);
if (hConfig.configurationsAt(prefix+"varianceCosts_"+index).size()!=0){
// System.out.println("hConfig.configurationAt(prefix+\"varianceCosts_\"+index).isEmpty()=false");
this.parameterVariationCosts[index]=new ParameterVariationCosts(
this.variationsDefaults[index][0],
this.variationsDefaults[index][1],
this.variationsDefaults[index][2],
this.variationsDefaults[index][3]);
boolean isSet= this.parameterVariationCosts[index].getPropertiesXML(prefix+"varianceCosts_"+index+".", hConfig);
if (!isSet) this.parameterVariationCosts[index]=null;
}
}
}
public void setCostsPropertiesXML(String prefix,XMLConfiguration hConfig){
if (this.parameterVariationCosts==null) return;
for (int i=0;i<this.extrinsicIndices.length;i++){
int index=this.extrinsicIndices[i];
if (this.parameterVariationCosts[index]!=null) {
hConfig.addProperty(prefix+"varianceCosts_"+index,"");
this.parameterVariationCosts[index].setPropertiesXML(prefix+"varianceCosts_"+index+".", hConfig);
}
}
}
private class ParameterVariationCosts{
public double scale = 1.0; // 1 pixel
public double variationAbs =0.0; // variation of the parameter to cost 1 pixel
public double variationDiff =0.0; // variation of the parameter to cost 1 pixel
public double exponent= 1.0; // 1.0 - square diff
public String parName=null;
// public ParameterVariationCosts(){}
public ParameterVariationCosts(
double scale,
double variationAbs,
double variationDiff,
double exponent,
String parName){
this.scale=scale;
this.variationAbs=variationAbs;
this.variationDiff=variationDiff;
this.exponent=exponent;
this.parName=parName;
}
public ParameterVariationCosts(
double scale,
double variationAbs,
double variationDiff,
double exponent){
this.scale=scale;
this.variationAbs=variationAbs;
this.variationDiff=variationDiff;
this.exponent=exponent;
}
public ParameterVariationCosts clone(){
return new ParameterVariationCosts(
this.scale,
this.variationAbs,
this.variationDiff,
this.exponent,
this.parName);
}
public void setPropertiesXML(String prefix,XMLConfiguration hConfig){
hConfig.addProperty(prefix+"scale",this.scale+"");
hConfig.addProperty(prefix+"variationAbs",this.variationAbs+"");
hConfig.addProperty(prefix+"variationDiff",this.variationDiff+"");
hConfig.addProperty(prefix+"exponent",this.exponent+"");
if (this.parName!=null) hConfig.addProperty(prefix+"parName",this.parName+"");
}
public boolean getPropertiesXML(String prefix,XMLConfiguration hConfig){
// System.out.println("getPropertiesXML("+prefix+",hconfig)");
boolean isSet=false;
if (hConfig.getString(prefix+"scale")!=null){
// System.out.println("getPropertiesXML("+prefix+",hconfig), hConfig.getString(prefix+\"scale\")!=null");
this.scale=Double.parseDouble(hConfig.getString(prefix+"scale"));
isSet=true;
}
if (hConfig.getString(prefix+"variationAbs")!=null){
// System.out.println("getPropertiesXML("+prefix+",hconfig), hConfig.getString(prefix+\"variationAbs\")!=null");
this.variationAbs=Double.parseDouble(hConfig.getString(prefix+"variationAbs"));
isSet=true;
}
if (hConfig.getString(prefix+"variationDiff")!=null){
// System.out.println("getPropertiesXML("+prefix+",hconfig), hConfig.getString(prefix+\"variationDiff\")!=null");
this.variationDiff=Double.parseDouble(hConfig.getString(prefix+"variationDiff"));
isSet=true;
}
if (hConfig.getString(prefix+"exponent")!=null){
// System.out.println("getPropertiesXML("+prefix+",hconfig), hConfig.getString(prefix+\"exponent\")!=null");
this.exponent=Double.parseDouble(hConfig.getString(prefix+"exponent"));
isSet=true;
}
if (hConfig.getString(prefix+"parName")!=null){
// System.out.println("getPropertiesXML("+prefix+",hconfig), hConfig.getString(prefix+\"parName\")!=null");
this.parName=hConfig.getString(prefix+"parName");
isSet=true;
}
return isSet;
}
public boolean showVarianceDialog(
String parameterName,
String parameterDescription,
String parameterUnits) {
String title="Setup costs for image set variance of "+parameterName;
GenericDialog gd = new GenericDialog(title);
gd.addMessage("Parameter: "+parameterName+" - "+parameterDescription);
gd.addNumericField("Effective cost of the image set when the "+parameterName+" variance reaches value below",this.scale, 2,4,"pix");
gd.addNumericField("Variance amount from the average of "+parameterName+" to result in the specified cost", this.variationAbs, 3,8,parameterUnits);
gd.addNumericField("Variance amount from the p to result in the specified cost", this.variationDiff, 3,8,parameterUnits);
gd.addNumericField("Exponent of the cost vs. variance (1.0 - squared err "+parameterName+" to result in the specified cost", this.exponent, 3,8,"");
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
this.scale= gd.getNextNumber();
this.variationAbs= gd.getNextNumber();
this.variationDiff= gd.getNextNumber();
this.exponent= gd.getNextNumber();
this.parName=parameterName;
return true;
}
}
public int getNumStations() {return this.numStations;}
public EyesisCameraParameters () {} // just create new instance, all parameters data will be provided additionally
public EyesisCameraParameters (
int numStations,
boolean isTripod,
double goniometerHorizontal, // goniometer rotation around "horizontal" axis (tilting from the target - positive)
double goniometerAxial, // goniometer rotation around Eyesis axis (clockwise in plan - positive
int numSubCameras,
double interAxisDistance, // distance in mm between two goniometer axes, positive if the vertical axis (when Eyesis is head up) is closer to the target
double interAxisAngle, // angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
// clockwise when eyesis is in 'normal' position, looking to the target
double horAxisErrPhi, // angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
double horAxisErrPsi, // angle in degrees "horizontal" goniometer axis is rotated around moving Z axis (CW looking at target)
double entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil
double centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
double GXYZ_0, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
double GXYZ_1, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
double GXYZ_2, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
int sensorWidth,
int sensorHeight,
int shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks
double maskBlurSigma, // blur sensor masks (in grid units)
int decimateMasks, // reduce masks resolution
double badNodeThreshold, // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
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)
double weightMultiExponent,
double weightDiameterExponent, // if( >0) use grid diameter to scale weights of this image
double weightYtoX,
double minimalGridContrast,
double shrinkBlurSigma,
double shrinkBlurLevel,
double balanceChannelWeightsMode,
double removeOverRMS,
double removeOverRMSNonweighted
){
double [] GXYZ={GXYZ_0,GXYZ_1,GXYZ_2};
setSameEyesisCameraParameters (
numStations,
isTripod,
goniometerHorizontal, // goniometer rotation around "horizontal" axis (tilting from the target - positive)
goniometerAxial, // goniometer rotation around Eyesis axis (clockwise in plan - positive
numSubCameras,
interAxisDistance, // distance in mm between two goniometer axes
interAxisAngle, // angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
// clockwise when eyesis is in 'normal' position, looking to the target
horAxisErrPhi, // angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
horAxisErrPsi, // angle in degrees "horizontal" goniometer axis is rotated moving Z axis (CW looking at target)
entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil
centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
sensorWidth,
sensorHeight,
shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks
maskBlurSigma, // blur sensor masks (in grid units)
decimateMasks, // reduce masks resolution
badNodeThreshold, // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
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)
weightMultiExponent,
weightDiameterExponent, // if( >0) use grid diameter to scale weights of this image
weightYtoX,
minimalGridContrast,
shrinkBlurSigma,
shrinkBlurLevel,
balanceChannelWeightsMode,
removeOverRMS,
removeOverRMSNonweighted
);
}
public EyesisCameraParameters (
int numStations,
boolean isTripod,
double goniometerHorizontal, // goniometer rotation around "horizontal" axis (tilting from the target - positive)
double goniometerAxial, // goniometer rotation around Eyesis axis (clockwise in plan - positive
int numSubCameras,
double interAxisDistance, // distance in mm between two goniometer axes
double interAxisAngle, // angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
// clockwise when eyesis is in 'normal' position, looking to the target
double horAxisErrPhi, // angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
double horAxisErrPsi, // angle in degrees "horizontal" goniometer axis is rotated moving Z axis (CW looking at target)
double entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil
double centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
double [] GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
int sensorWidth,
int sensorHeight,
int shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks
double maskBlurSigma, // blur sensor masks (in grid units)
int decimateMasks, // reduce masks resolution
double badNodeThreshold, // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
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)
double weightMultiExponent,
double weightDiameterExponent, // if( >0) use grid diameter to scale weights of this image
double weightYtoX,
double minimalGridContrast,
double shrinkBlurSigma,
double shrinkBlurLevel,
double balanceChannelWeightsMode,
double removeOverRMS,
double removeOverRMSNonweighted
){
setSameEyesisCameraParameters (
numStations,
isTripod,
goniometerHorizontal, // goniometer rotation around "horizontal" axis (tilting from the target - positive)
goniometerAxial, // goniometer rotation around Eyesis axis (clockwise in plan - positive
numSubCameras,
interAxisDistance, // distance in mm between two goniometer axes
interAxisAngle, // angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
// clockwise when eyesis is in 'normal' position, looking to the target
horAxisErrPhi, // angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
horAxisErrPsi, // angle in degrees "horizontal" goniometer axis is rotated moving Z axis (CW looking at target)
entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil
centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
sensorWidth,
sensorHeight,
shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks
maskBlurSigma, // blur sensor masks (in grid units)
decimateMasks, // reduce masks resolution
badNodeThreshold, // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
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)
weightMultiExponent,
weightDiameterExponent, // if( >0) use grid diameter to scale weights of this image
weightYtoX,
minimalGridContrast,
shrinkBlurSigma,
shrinkBlurLevel,
balanceChannelWeightsMode,
removeOverRMS,
removeOverRMSNonweighted
);
}
void setSameEyesisCameraParameters (
int numStations,
boolean isTripod,
double goniometerHorizontal, // goniometer rotation around "horizontal" axis (tilting from the target - positive)
double goniometerAxial, // goniometer rotation around Eyesis axis (clockwise in plan - positive
int numSubCameras,
double interAxisDistance, // distance in mm between two goniometer axes
double interAxisAngle, // angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
// clockwise when eyesis is in 'normal' position, looking to the target
double horAxisErrPhi, // angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
double horAxisErrPsi, // angle in degrees "horizontal" goniometer axis is rotated moving Z axis (CW looking at target)
double entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil
double centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
double [] GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
int sensorWidth,
int sensorHeight,
int shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks
double maskBlurSigma, // blur sensor masks (in grid units)
int decimateMasks, // reduce masks resolution
double badNodeThreshold, // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
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)
double weightMultiExponent,
double weightDiameterExponent, // if( >0) use grid diameter to scale weights of this image
double weightYtoX,
double minimalGridContrast,
double shrinkBlurSigma,
double shrinkBlurLevel,
double balanceChannelWeightsMode,
double removeOverRMS,
double removeOverRMSNonweighted
){
this.numStations=numStations;
this.isTripod=isTripod;
this.sensorWidth=sensorWidth;
this.sensorHeight=sensorHeight;
this.shrinkGridForMask=shrinkGridForMask; //shrink detected grids by one point for/vert this number of times before calculating masks
this.maskBlurSigma=maskBlurSigma; // blur sensor masks (in grid units)
this.decimateMasks=decimateMasks;
this.badNodeThreshold=badNodeThreshold; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
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)
this.weightMultiExponent=weightMultiExponent;
this.weightDiameterExponent=weightDiameterExponent; // if( >0) use grid diameter to scale weights of this image
this.weightYtoX=weightYtoX;
this.minimalGridContrast=minimalGridContrast;
this.goniometerHorizontal=new double[numStations];
this.goniometerAxial=new double[numStations];
this.interAxisDistance=new double[numStations];
this.interAxisAngle=new double[numStations];
this.horAxisErrPhi=new double[numStations];
this.horAxisErrPsi=new double[numStations];
this.entrancePupilForward=new double[numStations]; // common to all lenses - distance from the sensor to the lens entrance pupil
this.centerAboveHorizontal=new double[numStations]; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
this.GXYZ=new double[numStations][];
if (numSubCameras>0) this.eyesisSubCameras=new EyesisSubCameraParameters[numStations][];
this.stationWeight=new double[numStations];
for (int numStation=0;numStation<numStations;numStation++) {
this.stationWeight[numStation]=1.0;
this.goniometerHorizontal[numStation]=goniometerHorizontal;
this.goniometerAxial[numStation]=goniometerAxial;
this.interAxisDistance[numStation]=interAxisDistance;
this.interAxisAngle[numStation]=interAxisAngle;
this.horAxisErrPhi[numStation]=horAxisErrPhi;
this.horAxisErrPsi[numStation]=horAxisErrPsi;
this.entrancePupilForward[numStation]=entrancePupilForward; // common to all lenses - distance from the sensor to the lens entrance pupil
this.centerAboveHorizontal[numStation]=centerAboveHorizontal; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
this.GXYZ[numStation]=new double [3];
for (int i=0;i<3;i++) this.GXYZ[numStation][i]=GXYZ[i];
if (numSubCameras>0) initSubCameras(numStation,numSubCameras);
}
}
public EyesisCameraParameters clone() {
EyesisCameraParameters result= new EyesisCameraParameters ();
copyData(
this.numStations,
this,
result);
return result;
}
/**
* Capoy parameters from source EysesisCamerParameters to destination, trimming/expanding nu,ber of stations
* @param newNumStations new number of stations
* @param source source EysesisCamerParameters
* @param destination destination EysesisCamerParameters
*/
public void copyData(
int newNumStations,
EyesisCameraParameters source,
EyesisCameraParameters destination) {
destination.numStations=newNumStations;
destination.isTripod=source.isTripod;
destination.sensorWidth=source.sensorWidth;
destination.sensorHeight=source.sensorHeight;
destination.shrinkGridForMask=source.shrinkGridForMask; //shrink detected grids by one point for/vert this number of times before calculating masks
destination.maskBlurSigma=source.maskBlurSigma; // blur sensor masks (in grid units)
destination.decimateMasks=source.decimateMasks;
destination.badNodeThreshold=source.badNodeThreshold; // 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)
destination.weightMultiExponent= source.weightMultiExponent; // if( >0) use grid diameter to scale weights of this image
destination.weightDiameterExponent=source.weightDiameterExponent;
destination.weightYtoX=source.weightYtoX;
destination.minimalGridContrast=source.minimalGridContrast;
destination.shrinkBlurSigma=source.shrinkBlurSigma;
destination.shrinkBlurLevel=source.shrinkBlurLevel;
destination.balanceChannelWeightsMode=source.balanceChannelWeightsMode;
destination.removeOverRMSNonweighted=source.removeOverRMSNonweighted;
destination.goniometerHorizontal=new double[destination.numStations];
destination.goniometerAxial=new double[destination.numStations];
destination.interAxisDistance=new double[destination.numStations];
destination.interAxisAngle=new double[destination.numStations];
destination.horAxisErrPhi=new double[destination.numStations];
destination.horAxisErrPsi=new double[destination.numStations];
destination.entrancePupilForward=new double[destination.numStations]; // common to all lenses - distance from the sensor to the lens entrance pupil
destination.centerAboveHorizontal=new double[destination.numStations]; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
destination.GXYZ=new double[destination.numStations][];
if (source.eyesisSubCameras!=null) destination.eyesisSubCameras=new EyesisSubCameraParameters[destination.numStations][];
else destination.eyesisSubCameras=null;
destination.stationWeight=new double[destination.numStations];
for (int numStation=0;numStation<destination.numStations;numStation++) {
int srcNumStation=(numStation<source.numStations)?numStation:(source.numStations-1);
destination.stationWeight[numStation]=source.stationWeight[srcNumStation];
destination.goniometerHorizontal[numStation]=source.goniometerHorizontal[srcNumStation];
destination.goniometerAxial[numStation]=source.goniometerAxial[srcNumStation];
destination.interAxisDistance[numStation]=source.interAxisDistance[srcNumStation];
destination.interAxisAngle[numStation]=source.interAxisAngle[srcNumStation];
destination.horAxisErrPhi[numStation]=source.horAxisErrPhi[srcNumStation];
destination.horAxisErrPsi[numStation]=source.horAxisErrPsi[srcNumStation];
destination.entrancePupilForward[numStation]=source.entrancePupilForward[srcNumStation]; // common to all lenses - distance from the sensor to the lens entrance pupil
destination.centerAboveHorizontal[numStation]=source.centerAboveHorizontal[srcNumStation]; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
destination.GXYZ[numStation]=new double [3];
for (int i=0;i<3;i++) destination.GXYZ[numStation][i]=source.GXYZ[srcNumStation][i];
if (destination.eyesisSubCameras!=null){
destination.eyesisSubCameras[numStation]=new EyesisSubCameraParameters[source.eyesisSubCameras[srcNumStation].length];
for (int i=0; i<destination.eyesisSubCameras[numStation].length;i++) if (source.eyesisSubCameras[srcNumStation][i]!=null){
destination.eyesisSubCameras[numStation][i]=source.eyesisSubCameras[srcNumStation][i].clone();
}
}
}
}
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"isTripod",this.isTripod+"");
properties.setProperty(prefix+"sensorWidth",this.sensorWidth+"");
properties.setProperty(prefix+"sensorHeight",this.sensorHeight+"");
properties.setProperty(prefix+"shrinkGridForMask",this.shrinkGridForMask+"");
properties.setProperty(prefix+"maskBlurSigma",this.maskBlurSigma+"");
properties.setProperty(prefix+"decimateMasks",this.decimateMasks+"");
properties.setProperty(prefix+"badNodeThreshold",this.badNodeThreshold+"");
properties.setProperty(prefix+"maxBadNeighb",this.maxBadNeighb+"");
properties.setProperty(prefix+"minimalValidNodes",this.minimalValidNodes+"");
properties.setProperty(prefix+"weightMultiImageMode",this.weightMultiImageMode+"");
properties.setProperty(prefix+"weightMultiExponent",this.weightMultiExponent+"");
properties.setProperty(prefix+"weightDiameterExponent",this.weightDiameterExponent+"");
properties.setProperty(prefix+"weightYtoX",this.weightYtoX+"");
properties.setProperty(prefix+"minimalGridContrast",this.minimalGridContrast+"");
properties.setProperty(prefix+"shrinkBlurSigma",this.shrinkBlurSigma+"");
properties.setProperty(prefix+"shrinkBlurLevel",this.shrinkBlurLevel+"");
properties.setProperty(prefix+"balanceChannelWeightsMode",this.balanceChannelWeightsMode+"");
properties.setProperty(prefix+"removeOverRMS",this.removeOverRMS+"");
properties.setProperty(prefix+"removeOverRMSNonweighted",this.removeOverRMSNonweighted+"");
properties.setProperty(prefix+"numSubCameras",this.eyesisSubCameras[0].length+"");
properties.setProperty(prefix+"numStations",this.numStations+"");
for (int numStation=0;numStation<this.numStations;numStation++){
properties.setProperty(prefix+"stationWeight_"+numStation,this.stationWeight[numStation]+"");
properties.setProperty(prefix+"goniometerHorizontal_"+numStation,this.goniometerHorizontal[numStation]+"");
properties.setProperty(prefix+"goniometerAxial_"+numStation,this.goniometerAxial[numStation]+"");
properties.setProperty(prefix+"interAxisDistance_"+numStation,this.interAxisDistance[numStation]+"");
properties.setProperty(prefix+"interAxisAngle_"+numStation,this.interAxisAngle[numStation]+"");
properties.setProperty(prefix+"horAxisErrPhi_"+numStation,this.horAxisErrPhi[numStation]+"");
properties.setProperty(prefix+"horAxisErrPsi_"+numStation,this.horAxisErrPsi[numStation]+"");
properties.setProperty(prefix+"entrancePupilForward_"+numStation,this.entrancePupilForward[numStation]+"");
properties.setProperty(prefix+"centerAboveHorizontal_"+numStation,this.centerAboveHorizontal[numStation]+"");
properties.setProperty(prefix+"GXYZ_0_"+numStation,this.GXYZ[numStation][0]+"");
properties.setProperty(prefix+"GXYZ_1_"+numStation,this.GXYZ[numStation][1]+"");
properties.setProperty(prefix+"GXYZ_2_"+numStation,this.GXYZ[numStation][2]+"");
for (int i=0;i<this.eyesisSubCameras[numStation].length;i++) {
this.eyesisSubCameras[numStation][i].setProperties(prefix+numStation+"_subCamera_"+i+'.',properties);
}
}
// setCostsProperties(prefix,properties);
}
public void getProperties(String prefix,Properties properties){
if (properties.getProperty(prefix+"isTripod")!=null)
this.isTripod=Boolean.parseBoolean(properties.getProperty(prefix+"isTripod"));
if (properties.getProperty(prefix+"sensorWidth")!=null)
this.sensorWidth=Integer.parseInt(properties.getProperty(prefix+"sensorWidth"));
if (properties.getProperty(prefix+"sensorHeight")!=null)
this.sensorHeight=Integer.parseInt(properties.getProperty(prefix+"sensorHeight"));
if (properties.getProperty(prefix+"shrinkGridForMask")!=null)
this.shrinkGridForMask=Integer.parseInt(properties.getProperty(prefix+"shrinkGridForMask"));
if (properties.getProperty(prefix+"maskBlurSigma")!=null)
this.maskBlurSigma=Double.parseDouble(properties.getProperty(prefix+"maskBlurSigma"));
if (properties.getProperty(prefix+"decimateMasks")!=null)
this.decimateMasks=Integer.parseInt(properties.getProperty(prefix+"decimateMasks"));
if (properties.getProperty(prefix+"badNodeThreshold")!=null)
this.badNodeThreshold=Double.parseDouble(properties.getProperty(prefix+"badNodeThreshold"));
if (properties.getProperty(prefix+"maxBadNeighb")!=null)
this.maxBadNeighb=Integer.parseInt(properties.getProperty(prefix+"maxBadNeighb"));
if (properties.getProperty(prefix+"minimalValidNodes")!=null)
this.minimalValidNodes=Integer.parseInt(properties.getProperty(prefix+"minimalValidNodes"));
if (properties.getProperty(prefix+"weightMultiImageMode")!=null)
this.weightMultiImageMode=Integer.parseInt(properties.getProperty(prefix+"weightMultiImageMode"));
if (properties.getProperty(prefix+"weightMultiExponent")!=null)
this.weightMultiExponent=Double.parseDouble(properties.getProperty(prefix+"weightMultiExponent"));
if (properties.getProperty(prefix+"weightDiameterExponent")!=null)
this.weightDiameterExponent=Double.parseDouble(properties.getProperty(prefix+"weightDiameterExponent"));
if (properties.getProperty(prefix+"weightYtoX")!=null)
this.weightYtoX=Double.parseDouble(properties.getProperty(prefix+"weightYtoX"));
if (properties.getProperty(prefix+"minimalGridContrast")!=null)
this.minimalGridContrast=Double.parseDouble(properties.getProperty(prefix+"minimalGridContrast"));
if (properties.getProperty(prefix+"shrinkBlurSigma")!=null)
this.shrinkBlurSigma=Double.parseDouble(properties.getProperty(prefix+"shrinkBlurSigma"));
if (properties.getProperty(prefix+"shrinkBlurLevel")!=null)
this.shrinkBlurLevel=Double.parseDouble(properties.getProperty(prefix+"shrinkBlurLevel"));
if (properties.getProperty(prefix+"balanceChannelWeightsMode")!=null)
this.balanceChannelWeightsMode=Double.parseDouble(properties.getProperty(prefix+"balanceChannelWeightsMode"));
if (properties.getProperty(prefix+"removeOverRMS")!=null)
this.removeOverRMS=Double.parseDouble(properties.getProperty(prefix+"removeOverRMS"));
if (properties.getProperty(prefix+"removeOverRMSNonweighted")!=null)
this.removeOverRMSNonweighted=Double.parseDouble(properties.getProperty(prefix+"removeOverRMSNonweighted"));
boolean multiStation=true; // new default
int newNumStations=1;
int numSubCameras=0;
if (properties.getProperty(prefix+"numSubCameras")!=null) numSubCameras=Integer.parseInt(properties.getProperty(prefix+"numSubCameras"));
if (properties.getProperty(prefix+"numStations")!=null){
newNumStations=Integer.parseInt(properties.getProperty(prefix+"numStations"));
}else {
multiStation=false; // old config format
}
// TODO: trim/expand stations
updateNumstations (newNumStations);
// this.numStations
// read old/new format data
// this.numStations=newNumStations;
if (multiStation){
for (int numStation=0;numStation<this.numStations;numStation++){
if (properties.getProperty(prefix+"stationWeight_"+numStation)!=null)
this.stationWeight[numStation]=Double.parseDouble(properties.getProperty(prefix+"stationWeight_"+numStation));
if (properties.getProperty(prefix+"goniometerHorizontal_"+numStation)!=null)
this.goniometerHorizontal[numStation]=Double.parseDouble(properties.getProperty(prefix+"goniometerHorizontal_"+numStation));
if (properties.getProperty(prefix+"goniometerAxial_"+numStation)!=null)
this.goniometerAxial[numStation]=Double.parseDouble(properties.getProperty(prefix+"goniometerAxial_"+numStation));
if (properties.getProperty(prefix+"interAxisDistance_"+numStation)!=null)
this.interAxisDistance[numStation]=Double.parseDouble(properties.getProperty(prefix+"interAxisDistance_"+numStation));
if (properties.getProperty(prefix+"interAxisAngle_"+numStation)!=null)
this.interAxisAngle[numStation]=Double.parseDouble(properties.getProperty(prefix+"interAxisAngle_"+numStation));
if (properties.getProperty(prefix+"horAxisErrPhi_"+numStation)!=null)
this.horAxisErrPhi[numStation]=Double.parseDouble(properties.getProperty(prefix+"horAxisErrPhi_"+numStation));
if (properties.getProperty(prefix+"horAxisErrPsi_"+numStation)!=null)
this.horAxisErrPsi[numStation]=Double.parseDouble(properties.getProperty(prefix+"horAxisErrPsi_"+numStation));
if (properties.getProperty(prefix+"entrancePupilForward_"+numStation)!=null)
this.entrancePupilForward[numStation]=Double.parseDouble(properties.getProperty(prefix+"entrancePupilForward_"+numStation));
if (properties.getProperty(prefix+"centerAboveHorizontal_"+numStation)!=null)
this.centerAboveHorizontal[numStation]=Double.parseDouble(properties.getProperty(prefix+"centerAboveHorizontal_"+numStation));
if (properties.getProperty(prefix+"GXYZ_0_"+numStation)!=null)
this.GXYZ[numStation][0]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_0_"+numStation));
if (properties.getProperty(prefix+"GXYZ_1_"+numStation)!=null)
this.GXYZ[numStation][1]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_1_"+numStation));
if (properties.getProperty(prefix+"GXYZ_2_"+numStation)!=null)
this.GXYZ[numStation][2]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_2_"+numStation));
if (numSubCameras>0) {
initSubCameras(numStation, numSubCameras); // set array with default parameters
for (int i=0;i<numSubCameras;i++){
this.eyesisSubCameras[numStation][i].getProperties(prefix+numStation+"_subCamera_"+i+'.',properties);
}
}
}
} else { // read old format
if (properties.getProperty(prefix+"goniometerHorizontal")!=null)
this.goniometerHorizontal[0]=Double.parseDouble(properties.getProperty(prefix+"goniometerHorizontal"));
if (properties.getProperty(prefix+"goniometerAxial")!=null)
this.goniometerAxial[0]=Double.parseDouble(properties.getProperty(prefix+"goniometerAxial"));
if (properties.getProperty(prefix+"interAxisDistance")!=null)
this.interAxisDistance[0]=Double.parseDouble(properties.getProperty(prefix+"interAxisDistance"));
if (properties.getProperty(prefix+"interAxisAngle")!=null)
this.interAxisAngle[0]=Double.parseDouble(properties.getProperty(prefix+"interAxisAngle"));
if (properties.getProperty(prefix+"horAxisErrPhi")!=null)
this.horAxisErrPhi[0]=Double.parseDouble(properties.getProperty(prefix+"horAxisErrPhi"));
if (properties.getProperty(prefix+"horAxisErrPsi")!=null)
this.horAxisErrPsi[0]=Double.parseDouble(properties.getProperty(prefix+"horAxisErrPsi"));
if (properties.getProperty(prefix+"entrancePupilForward")!=null)
this.entrancePupilForward[0]=Double.parseDouble(properties.getProperty(prefix+"entrancePupilForward"));
if (properties.getProperty(prefix+"centerAboveHorizontal")!=null)
this.centerAboveHorizontal[0]=Double.parseDouble(properties.getProperty(prefix+"centerAboveHorizontal"));
if (properties.getProperty(prefix+"GXYZ_0")!=null)
this.GXYZ[0][0]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_0"));
if (properties.getProperty(prefix+"GXYZ_1")!=null)
this.GXYZ[0][1]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_1"));
if (properties.getProperty(prefix+"GXYZ_2")!=null)
this.GXYZ[0][2]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_2"));
System.out.println(" === numSubCameras="+numSubCameras);
if (numSubCameras>0) {
initSubCameras(0, numSubCameras); // set array with default parameters
for (int i=0;i<numSubCameras;i++){
System.out.println("this.eyesisSubCameras[0]["+i+"].getProperties("+prefix+"subCamera_"+i+".,properties);");
this.eyesisSubCameras[0][i].getProperties(prefix+"subCamera_"+i+'.',properties);
}
}
}
// getCostsProperties(prefix,properties);
}
void updateNumstations (int newNumStations){
// System.out.println("updateNumstations("+newNumStations+"), was "+this.numStations);
if (newNumStations==this.numStations) return;
System.out.println("updateNumstations("+newNumStations+"), was "+this.numStations);
EyesisCameraParameters newData=this.clone();
copyData(
newNumStations,
newData,
this);
System.out.println("updateNumstations() after copyData() this.numStations="+this.numStations);
}
// returns -1 - canceled, 0 - done, >0 - number of sub-camera to edit
private int subShowDialog(String title, int nextSubCamera) {
GenericDialog gd = new GenericDialog(title);
// public double goniometerHorizontal; // goniometer rotation around "horizontal" axis (tilting from the target - positive)
// public double goniometerAxial; // goniometer rotation around Eyesis axis (clockwise in plan - positive
//this.isTripod
gd.addCheckbox("Tripod mode (first vertical axis, then horizontal), changes meaning of the next 2 fields",this.isTripod);
gd.addMessage("=== Camera parameters to be fitted ===");
for (int numStation=0;numStation<this.numStations;numStation++) {
if (this.numStations>1){
gd.addMessage("--- Station number "+numStation+" ---");
gd.addNumericField("Station reprojection errors weight", 100*this.stationWeight[numStation], 1,5,"%");
}
if (this.isTripod) {
gd.addNumericField("Tripod rotation around vertical axis (clockwise from top - positive)",this.goniometerHorizontal[numStation], 3,7,"degrees");
gd.addNumericField("Tripod rotation around horizontal axis (camera up - positive)", this.goniometerAxial[numStation], 3,7,"degrees");
} else {
gd.addNumericField("Goniometer rotation around 'horizontal' axis (tilting from the target - positive)",this.goniometerHorizontal[numStation], 3,7,"degrees");
gd.addNumericField("Rotation around Eyesis main axis (clockwise in plan - positive)", this.goniometerAxial[numStation], 3,7,"degrees");
}
gd.addNumericField("Distance between goniometer axes", this.interAxisDistance[numStation], 3,7,"mm");
gd.addNumericField("Angle error between goniometer axes (<0 if vertical axis rotated CW )",this.interAxisAngle[numStation], 3,7,"degrees");
if (this.isTripod) {
gd.addNumericField("Vertical tripod axis tilt from true vertical", this.horAxisErrPhi[numStation], 3,7,"degrees");
gd.addNumericField("Vertical tripod axis roll error from true vertical", this.horAxisErrPsi[numStation], 3,7,"degrees");
} else {
gd.addNumericField("Horizontal axis azimuth error (CW in plan)", this.horAxisErrPhi[numStation], 3,7,"degrees");
gd.addNumericField("Horizontal axis roll error (CW looking to target)", this.horAxisErrPsi[numStation], 3,7,"degrees");
}
gd.addNumericField("Distance between the lens entrace pupil and the sensor", this.entrancePupilForward[numStation], 3,7,"mm");
gd.addNumericField("Camera center above goniometer horizontal axis", this.centerAboveHorizontal[numStation], 3,7,"mm");
gd.addNumericField("Goniometer reference point position X (target coordinates, left)", this.GXYZ[numStation][0], 3,7,"mm");
gd.addNumericField("Goniometer reference point position Y (target coordinates, up)", this.GXYZ[numStation][1], 3,7,"mm");
gd.addNumericField("Goniometer reference point position Z (target coordinates, away)", this.GXYZ[numStation][2], 3,7,"mm");
}
gd.addMessage("=== Other parameters ===");
gd.addNumericField("Image sensor width (maximal if different)", this.sensorWidth, 0,4,"pix");
gd.addNumericField("Image sensor height (maximal if different)", this.sensorHeight, 0,4,"pix");
gd.addNumericField("Shrink detected grid by this number of nodes (half/periods) for masks",this.shrinkGridForMask, 0,4,"grid nodes");
gd.addNumericField("Gaussian blur masks for the sensors (positive - pixels, negative - grid half-periods)", this.maskBlurSigma, 2,6,"pix");
gd.addNumericField("Reduce sensor resolution when calculating masks", this.decimateMasks, 0);
gd.addNumericField("Filter out grid nodes with difference from quadratically predicted from 8 neighbors", this.badNodeThreshold, 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);
gd.addNumericField("Increase weight of the multi-image sets power (used with mode above)", this.weightMultiExponent, 2,6,"");
gd.addNumericField("Increase weight of the images by the power of their diameters", this.weightDiameterExponent, 2,6,"");
gd.addNumericField("Increase weight Y-error with respect to X-error", 100.0*this.weightYtoX, 2,6,"%");
gd.addNumericField("Filter out grid nodes with the contrast less than this value (maximal is ~0.8) ", this.minimalGridContrast, 2,6,"");
gd.addNumericField("Shrink-blur detected grids alpha", this.shrinkBlurSigma, 2,6,"grid nodes");
gd.addNumericField("Shrink-blur detected grids level (-1..+1)", this.shrinkBlurLevel, 2,6,"");
gd.addNumericField("Channel balace mode: <0 - use specified defaults, 0 - keep curent, >0 - exponent for correction (1.0 - precise equalization)", this.balanceChannelWeightsMode, 3,6,"");
gd.addNumericField("Remove nodes with error greater than scaled RMS in that image, weighted", this.removeOverRMS, 2,6,"xRMS");
gd.addNumericField("Same, not weghted (not more permissive near the borders with low weight)", this.removeOverRMSNonweighted, 2,6,"xRMS");
gd.addNumericField("Number of sub-camera modules", this.eyesisSubCameras[0].length, 0,2,"");
gd.addNumericField("Number of sub-camera module to edit (<=0 - none)", nextSubCamera, 0,2,"");
gd.enableYesNoCancel("OK", "Done");
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return -1;
this.isTripod= gd.getNextBoolean();
for (int numStation=0;numStation<this.numStations;numStation++) {
if (this.numStations>1){
this.stationWeight[numStation]=0.01*gd.getNextNumber();
}
this.goniometerHorizontal[numStation]= gd.getNextNumber();
this.goniometerAxial[numStation]= gd.getNextNumber();
this.interAxisDistance[numStation]= gd.getNextNumber();
this.interAxisAngle[numStation]= gd.getNextNumber();
this.horAxisErrPhi[numStation]= gd.getNextNumber();
this.horAxisErrPsi[numStation]= gd.getNextNumber();
this.entrancePupilForward[numStation]= gd.getNextNumber();
this.centerAboveHorizontal[numStation]= gd.getNextNumber();
this.GXYZ[numStation][0]= gd.getNextNumber();
this.GXYZ[numStation][1]= gd.getNextNumber();
this.GXYZ[numStation][2]= gd.getNextNumber();
}
this.sensorWidth= (int) gd.getNextNumber();
this.sensorHeight= (int) gd.getNextNumber();
this.shrinkGridForMask= (int) gd.getNextNumber();
this.maskBlurSigma= gd.getNextNumber();
this.decimateMasks= (int) gd.getNextNumber();
this.badNodeThreshold= gd.getNextNumber();
this.maxBadNeighb= (int) gd.getNextNumber();
this.minimalValidNodes= (int) gd.getNextNumber();
this.weightMultiImageMode=(int) gd.getNextNumber();
this.weightMultiExponent= gd.getNextNumber();
this.weightDiameterExponent= gd.getNextNumber();
this.weightYtoX= 0.01*gd.getNextNumber();
this.minimalGridContrast= gd.getNextNumber();
this.shrinkBlurSigma = gd.getNextNumber();
this.shrinkBlurLevel = gd.getNextNumber();
this.balanceChannelWeightsMode= gd.getNextNumber();
this.removeOverRMS = gd.getNextNumber();
this.removeOverRMSNonweighted= gd.getNextNumber();
int numSubCams= (int) gd.getNextNumber();
int numSubCam= (int) gd.getNextNumber();
if (numSubCams!=this.eyesisSubCameras[0].length){
this.eyesisSubCameras=new EyesisSubCameraParameters[this.numStations][];
for (int numStation=0;numStation<numStations;numStation++) {
initSubCameras(numStation,numSubCams); // re-initialize from defaults, discard current!
}
}
if (numSubCam<0)numSubCam=0;
return gd.wasOKed()?numSubCam:-1;
}
public boolean showSubcameraDialog(
int numSubCam,
String title) {
GenericDialog gd = new GenericDialog(title);
for (int numStation=0;numStation<this.numStations;numStation++) {
EyesisSubCameraParameters subCam=this.eyesisSubCameras[numStation][numSubCam];
if (subCam!=null) {
gd.addMessage("Channel weight "+subCam.channelWeightCurrent);
if (numStation==0){
gd.addNumericField("Channel "+numSubCam+" default weight", subCam.channelWeightDefault, 3,6,"");
}
if (this.numStations>1) gd.addMessage("--- Station number "+numStation+" ---");
gd.addNumericField("Subcamera azimuth", subCam.azimuth, 3,7,"degrees");
gd.addNumericField("Subcamera distance from the axis", subCam.radius, 3,7,"mm");
gd.addNumericField("Subcamera height from the 'equator'", subCam.height, 3,7,"mm");
gd.addNumericField("Optical axis heading (relative to azimuth)", subCam.phi, 3,7,"degrees");
gd.addNumericField("Optical axis elevation (up from equator)", subCam.theta, 3,7,"degrees");
gd.addNumericField("Camera roll, positive CW looking to the target",subCam.psi, 3,7,"degrees");
gd.addNumericField("Lens focal length", subCam.focalLength, 3,6,"mm");
gd.addNumericField("Sensor pixel period", subCam.pixelSize, 3,6,"um");
gd.addNumericField("Distortion radius (half width)", subCam.distortionRadius, 5,8,"mm");
gd.addNumericField("Distortion A8 (r^8)", subCam.distortionA8, 6,8,"");
gd.addNumericField("Distortion A7 (r^7)", subCam.distortionA7, 6,8,"");
gd.addNumericField("Distortion A6 (r^6)", subCam.distortionA6, 6,8,"");
gd.addNumericField("Distortion A5 (r^5)", subCam.distortionA5, 6,8,"");
gd.addNumericField("Distortion A (r^4)", subCam.distortionA, 6,8,"");
gd.addNumericField("Distortion B (r^3)", subCam.distortionB, 6,8,"");
gd.addNumericField("Distortion C (r^2)", subCam.distortionC, 6,8,"");
gd.addNumericField("Lens axis on the sensor (horizontal, from left edge)", subCam.px0, 2,7,"pixels");
gd.addNumericField("Lens axis on the sensor (vertical, from top edge)", subCam.py0, 2,7,"pixels");
}
}
gd.enableYesNoCancel("OK", "Done");
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
double channelWeightDefault=1.0;
for (int numStation=0;numStation<this.numStations;numStation++) {
EyesisSubCameraParameters subCam=this.eyesisSubCameras[numStation][numSubCam];
if (subCam!=null) {
if (numStation==0){
gd.addMessage("Channel weight "+subCam.channelWeightCurrent);
channelWeightDefault=gd.getNextNumber();
}
subCam.channelWeightDefault= channelWeightDefault; // assign to all stations
subCam.azimuth= gd.getNextNumber();
subCam.radius= gd.getNextNumber();
subCam.height= gd.getNextNumber();
subCam.phi= gd.getNextNumber();
subCam.theta= gd.getNextNumber();
subCam.psi= gd.getNextNumber();
subCam.focalLength= gd.getNextNumber();
subCam.pixelSize= gd.getNextNumber();
subCam.distortionRadius=gd.getNextNumber();
subCam.distortionA8= gd.getNextNumber();
subCam.distortionA7= gd.getNextNumber();
subCam.distortionA6= gd.getNextNumber();
subCam.distortionA5= gd.getNextNumber();
subCam.distortionA= gd.getNextNumber();
subCam.distortionB= gd.getNextNumber();
subCam.distortionC= gd.getNextNumber();
subCam.px0= gd.getNextNumber();
subCam.py0= gd.getNextNumber();
}
}
return gd.wasOKed();
}
// TODO: make subcameras show numbers from 0
public boolean showDialog(String title) {
System.out.println("this.eyesisSubCameras.length="+this.eyesisSubCameras.length);
System.out.println("this.eyesisSubCameras[0].length="+this.eyesisSubCameras[0].length);
int subCam=1;
while (subCam<=this.eyesisSubCameras[0].length) {
System.out.println("subCam="+subCam);
subCam=subShowDialog(title, subCam);
if (subCam<0) return false;
if (subCam==0) return true;
while (subCam<=this.eyesisSubCameras[0].length) {
// if (!this.eyesisSubCameras[subCam-1].showDialog(title+": subcamera "+subCam)) break;
if (!showSubcameraDialog(subCam-1,title+": subcamera "+subCam+" ("+(subCam-1)+")")) break;
subCam++;
}
}
return true;
}
/**
*
* @param eyesisCameraParameters current parameters of the Eyesis camera, subcameras and goniometer
* @param subCamNumber number of sub-camera (from 0)
* @return array of the parameters (both individual sub-camera and common to all sub-cameras)
*
*/
public double [] getParametersVector(
int stationNumber,
int subCamNumber //
){
if (
(this.eyesisSubCameras==null) ||
(this.numStations<=stationNumber) ||
(this.eyesisSubCameras.length<=stationNumber) ||
(this.eyesisSubCameras[stationNumber].length<=subCamNumber)) throw new IllegalArgumentException
("Nonexistent subcamera "+subCamNumber+ " and/or station number="+stationNumber+" this.numStations="+this.numStations+" this.eyesisSubCameras.length="+this.eyesisSubCameras.length);
EyesisSubCameraParameters subCam=this.eyesisSubCameras[stationNumber][subCamNumber];
// System.out.println("getParametersVector("+stationNumber+","+subCamNumber+"), subCam is "+((subCam==null)?"null":"NOT null"));
double [] parVect={
subCam.azimuth, // 0 azimuth of the lens entrance pupil center, degrees, clockwise looking from top
subCam.radius, // 1 mm, distance from the rotation axis
subCam.height, // 2 mm, up (was downwards?) - from the origin point
subCam.phi, // 3 degrees, optical axis from azimuth/r vector, clockwise
subCam.theta, // 4 degrees, optical axis from the eyesis horizon, positive - up
subCam.psi, // 5 degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
this.goniometerHorizontal[stationNumber], // 6 goniometer rotation around "horizontal" axis (tilting from the target - positive)
this.goniometerAxial[stationNumber], // 7 goniometer rotation around Eyesis axis (clockwise in plan - positive
this.interAxisDistance[stationNumber], // 8 distance in mm between two goniometer axes
this.interAxisAngle[stationNumber], // 9 angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
this.horAxisErrPhi[stationNumber], //10 angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
this.horAxisErrPsi[stationNumber], //11 angle in degrees "horizontal" goniometer axis is rotated around moving X axis (up)
this.entrancePupilForward[stationNumber], //12 common to all lenses - distance from the sensor to the lens entrance pupil
this.centerAboveHorizontal[stationNumber],//13 camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
this.GXYZ[stationNumber][0], //14 (12) coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
this.GXYZ[stationNumber][1], //15 (13) y
this.GXYZ[stationNumber][2], //16 (14) z
subCam.focalLength, //17 (15) lens focal length
subCam.px0, //18 (16) center of the lens on the sensor, pixels
subCam.py0, //19 (17) center of the lens on the sensor, pixels
subCam.distortionA8, //20 (18) r^8 (normalized to focal length or to sensor half width?)
subCam.distortionA7, //21 (19) r^7 (normalized to focal length or to sensor half width?)
subCam.distortionA6, //22 (20) r^6 (normalized to focal length or to sensor half width?)
subCam.distortionA5, //23 (21) r^5 (normalized to focal length or to sensor half width?)
subCam.distortionA, //24 (22) r^4 (normalized to focal length or to sensor half width?)
subCam.distortionB, //25 (23) r^3
subCam.distortionC, //26 (24) r^2
};
// Global parameters, not adjusted - just copied once when camera is selected
// or should they stay fixed and not copied at all?
// this.lensDistortionParameters.pixelSize=subCam.pixelSize; // has to be set separately
// this.lensDistortionParameters.distortionRadius=subCam.distortionRadius;
return parVect;
}
// public int getNumSubCameras (){return (this.eyesisSubCameras==null)?0:this.eyesisSubCameras.length;}
public int getGoniometerHorizontalIndex(){return 6;}
public int getGoniometerAxialIndex(){return 7;}
public int getSensorWidth() { return this.sensorWidth;}
public int getSensorHeight() { return this.sensorHeight;}
public int getSensorWidth(int subCam) { return this.sensorWidth;} // for the future? different sensors
public int getSensorHeight(int subCam) { return this.sensorHeight;}// for the future? different sensors
public double getPixelSize(int subCamNumber){return this.eyesisSubCameras[0][subCamNumber].pixelSize;} // use station 0's pixel size
public double getDistortionRadius(int subCamNumber){return this.eyesisSubCameras[0][subCamNumber].distortionRadius;}
public void setParametersVectorAllStations(
double [] parVect,
boolean [] update,
int subCamNumber //
){
for (int stationNumber=0;stationNumber<this.numStations;stationNumber++){
setParametersVector(
parVect,
update,
stationNumber,
subCamNumber );
}
}
/**
* Set camera/subcamera parameters from the parameters vector
* @param parVect array of the parameters (both individual sub-camera and common to all sub-cameras)
* @param update - which parameter of the vector to update
* @param eyesisCameraParameters current parameters of the Eyesis camera, subcameras and goniometer
* @param subCamNumber number of sub-camera (from 0)
*/
public void setParametersVector(
double [] parVect,
boolean [] update,
int stationNumber,
int subCamNumber //
){
if (parVect.length!=27) throw new IllegalArgumentException ("Wrong length of the parameters vector: "+parVect.length+"(should be 27)");
if (
(this.eyesisSubCameras==null) ||
(this.numStations<=stationNumber) ||
(this.eyesisSubCameras.length<=stationNumber) ||
(this.eyesisSubCameras[stationNumber].length<=subCamNumber)) throw new IllegalArgumentException
("Nonexistent subcamera "+subCamNumber+ " and/or station number="+stationNumber);
EyesisSubCameraParameters subCam=this.eyesisSubCameras[stationNumber][subCamNumber];
if (update[0]) subCam.azimuth=parVect[0]; // 0 azimuth of the lens entrance pupil center, degrees, clockwise looking from top
if (update[1]) subCam.radius=parVect[1]; // 1 mm, distance from the rotation axis
if (update[2]) subCam.height=parVect[2]; // 2 mm, up (was downwards?) - from the origin point
if (update[2]) subCam.phi=parVect[3]; // 3 degrees, optical axis from azimuth/r vector, clockwise
if (update[4]) subCam.theta=parVect[4]; // 4 degrees, optical axis from the eyesis horizon, positive - up
if (update[5]) subCam.psi=parVect[5]; // 5 degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
if (update[6]) this.goniometerHorizontal[stationNumber]=parVect[6]; // 6 goniometer rotation around "horizontal" axis (tilting from the target - positive)
if (update[7]) this.goniometerAxial[stationNumber]=parVect[7]; // 7 goniometer rotation around Eyesis axis (clockwise in plan - positive
if (update[8]) this.interAxisDistance[stationNumber]=parVect[8]; // 8 distance in mm between two goniometer axes
if (update[9]) this.interAxisAngle[stationNumber]=parVect[9]; // 9 angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
if (update[10]) this.horAxisErrPhi[stationNumber]=parVect[10]; //10 angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
if (update[11]) this.horAxisErrPsi[stationNumber]=parVect[11]; //11 angle in degrees "horizontal" goniometer axis is rotated around moving X axis (up)
if (update[12]) this.entrancePupilForward[stationNumber]=parVect[12]; //12 coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
if (update[13]) this.centerAboveHorizontal[stationNumber]=parVect[13]; //13 y
if (update[14]) this.GXYZ[stationNumber][0]=parVect[14]; //14 coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
if (update[15]) this.GXYZ[stationNumber][1]=parVect[15]; //15 y
if (update[16]) this.GXYZ[stationNumber][2]=parVect[16]; //16 z
if (update[17]) subCam.focalLength=parVect[17]; //17 lens focal length
if (update[18]) subCam.px0=parVect[18]; //18 center of the lens on the sensor, pixels
if (update[19]) subCam.py0=parVect[19]; //19 center of the lens on the sensor, pixels
if (update[20]) subCam.distortionA8=parVect[20]; //20 r^8 (normalized to focal length or to sensor half width?)
if (update[21]) subCam.distortionA7=parVect[21]; //21 r^7 (normalized to focal length or to sensor half width?)
if (update[22]) subCam.distortionA6=parVect[22]; //22 r^6 (normalized to focal length or to sensor half width?)
if (update[23]) subCam.distortionA5=parVect[23]; //23 r^5 (normalized to focal length or to sensor half width?)
if (update[24]) subCam.distortionA= parVect[24]; //24 r^4 (normalized to focal length or to sensor half width?)
if (update[25]) subCam.distortionB= parVect[25]; //25 r^3
if (update[26]) subCam.distortionC= parVect[26]; //26 r^2
}
public void initSubCameras(
int numStation,
int numSubCameras){
System.out.println("initSubCameras("+numStation+","+numSubCameras+")");
this.eyesisSubCameras[numStation]=new EyesisSubCameraParameters[numSubCameras];
for (int i=0;i<numSubCameras;i++) this.eyesisSubCameras[numStation][i]=null;
if (numSubCameras==3) {
this.eyesisSubCameras[numStation][0]=new EyesisSubCameraParameters( //TODO: modify for lens adjustment defaults?
0.0, // double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
52.53, // double radius, // mm, distance from the rotation axis
34.64, // double height, // mm, up (was downwards) - from the origin point
0.0, // double phi, // degrees, optical axis from azimuth/r vector, clockwise
0.0, //double theta, // degrees, optical axis from the eyesis horizon, positive - up
180.0, //double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
4.5, // double focalLength
2.2, // double pixelSize (um)
2.8512, //double distortionRadius mm - half width of the sensor
0.0, // double distortionA8 // r^8 (normalized to focal length or to sensor half width?)
0.0, // double distortionA7 // r^7 (normalized to focal length or to sensor half width?)
0.0, // double distortionA6 // r^6 (normalized to focal length or to sensor half width?)
0.0, // double distortionA5 // r^5 (normalized to focal length or to sensor half width?)
0.0, // double distortionA // r^4 (normalized to focal length or to sensor half width?)
0.0, // double distortionB // r^3
0.0, // double distortionC // r^2
1296.0, // double px0=1296.0; // center of the lens on the sensor, pixels
968.0, // double py0=968.0; // center of the lens on the sensor, pixels
1.0); //channelWeightDefault
this.eyesisSubCameras[numStation][1]=new EyesisSubCameraParameters( //TODO: modify for lens adjustment defaults?
30.0, // double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
60.0, // double radius, // mm, distance from the rotation axis
-17.32, // double height, // mm, up (was downwards) - from the origin point
-30.0, // double phi, // degrees, optical axis from azimuth/r vector, clockwise
0.0, //double theta, // degrees, optical axis from the eyesis horizon, positive - up
180.0, //double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
4.5, // double focalLength
2.2, // double pixelSize (um)
2.8512, //double distortionRadius mm - half width of the sensor
0.0, // double distortionA8 // r^8 (normalized to focal length or to sensor half width?)
0.0, // double distortionA7 // r^7 (normalized to focal length or to sensor half width?)
0.0, // double distortionA6 // r^6 (normalized to focal length or to sensor half width?)
0.0, // double distortionA5 // r^5 (normalized to focal length or to sensor half width?)
0.0, // double distortionA // r^4 (normalized to focal length or to sensor half width?)
0.0, // double distortionB // r^3
0.0, // double distortionC // r^2
1296.0, // double px0=1296.0; // center of the lens on the sensor, pixels
968.0, // double py0=968.0; // center of the lens on the sensor, pixels
1.0); //channelWeightDefault
this.eyesisSubCameras[numStation][2]=new EyesisSubCameraParameters( //TODO: modify for lens adjustment defaults?
-30.0, // double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
60.0, // double radius, // mm, distance from the rotation axis
-17.32, // double height, // mm, up (was downwards) - from the origin point
30.0, // double phi, // degrees, optical axis from azimuth/r vector, clockwise
0.0, //double theta, // degrees, optical axis from the eyesis horizon, positive - up
180.0, //double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
4.5, // double focalLength
2.2, // double pixelSize (um)
2.8512, //double distortionRadius mm - half width of the sensor
0.0, // double distortionA8 // r^8 (normalized to focal length or to sensor half width?)
0.0, // double distortionA7 // r^7 (normalized to focal length or to sensor half width?)
0.0, // double distortionA6 // r^6 (normalized to focal length or to sensor half width?)
0.0, // double distortionA5 // r^5 (normalized to focal length or to sensor half width?)
0.0, // double distortionA // r^4 (normalized to focal length or to sensor half width?)
0.0, // double distortionB // r^3
0.0, // double distortionC // r^2
1296.0, // double px0=1296.0; // center of the lens on the sensor, pixels
968.0, // double py0=968.0; // center of the lens on the sensor, pixels
1.0); //channelWeightDefault
} else if (numSubCameras==1) {
this.eyesisSubCameras[numStation][0]=new EyesisSubCameraParameters( //TODO: modify for lens adjustment defaults?
0.0, // double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
0.0, // double radius, // mm, distance from the rotation axis
0.0, // double height, // mm, up (was downwards) - from the origin point
0.0, // double phi, // degrees, optical axis from azimuth/r vector, clockwise
0.0, //double theta, // degrees, optical axis from the eyesis horizon, positive - up
0.0, //double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
4.5, // double focalLength
2.2, // double pixelSize (um)
2.8512, //double distortionRadius mm - half width of the sensor
0.0, // double distortionA8 // r^8 (normalized to focal length or to sensor half width?)
0.0, // double distortionA7 // r^7 (normalized to focal length or to sensor half width?)
0.0, // double distortionA6 // r^6 (normalized to focal length or to sensor half width?)
0.0, // double distortionA5 // r^5 (normalized to focal length or to sensor half width?)
0.0, // double distortionA // r^4 (normalized to focal length or to sensor half width?)
0.0, // double distortionB // r^3
0.0, // double distortionC // r^2
1296.0, // double px0=1296.0; // center of the lens on the sensor, pixels
968.0, // double py0=968.0; // center of the lens on the sensor, pixels
1.0); //channelWeightDefault
} else {
// default setup for the 26 sub-cameras
for (int i=0;i<8;i++) if (i<numSubCameras) this.eyesisSubCameras[numStation][i]=new EyesisSubCameraParameters( // top 8 cameras
45.0*i, // double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
41.540, // double radius, // mm, distance from the rotation axis
42.883, // double height, // mm, up (was downwards?) - from the origin point
0.0, // double phi, // degrees, optical axis from azimuth/r vector, clockwise
60.0, //double theta, // degrees, optical axis from the eyesis horizon, positive - up
90.0, //double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
4.5, // double focalLength
2.2, // double pixelSize (um)
2.8512, //double distortionRadius mm - half width of the sensor
0.0, // double distortionA8 // r^8 (normalized to focal length or to sensor half width?)
0.0, // double distortionA7 // r^7 (normalized to focal length or to sensor half width?)
0.0, // double distortionA6 // r^6 (normalized to focal length or to sensor half width?)
0.0, // double distortionA5 // r^5 (normalized to focal length or to sensor half width?)
0.0, // double distortionA // r^4 (normalized to focal length or to sensor half width?)
0.0, // double distortionB // r^3
0.0, // double distortionC // r^2
1296.0, // double px0=1296.0; // center of the lens on the sensor, pixels
968.0, // double py0=968.0; // center of the lens on the sensor, pixels
1.0); //channelWeightDefault
for (int i=8;i<16;i++) if (i<numSubCameras) this.eyesisSubCameras[numStation][i]=new EyesisSubCameraParameters( // middle 8 cameras
45.0*(i-8), // double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
54.525, // double radius, // mm, distance from the rotation axis
0.0, // double height, // mm, up (was downwards) - from the origin point
0.0, // double phi, // degrees, optical axis from azimuth/r vector, clockwise
0.0, //double theta, // degrees, optical axis from the eyesis horizon, positive - up
90.0, //double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
4.5, // double focalLength
2.2, // double pixelSize (um)
2.8512, //double distortionRadius mm - half width of the sensor
0.0, // double distortionA8 // r^8 (normalized to focal length or to sensor half width?)
0.0, // double distortionA7 // r^7 (normalized to focal length or to sensor half width?)
0.0, // double distortionA6 // r^6 (normalized to focal length or to sensor half width?)
0.0, // double distortionA5 // r^5 (normalized to focal length or to sensor half width?)
0.0, // double distortionA // r^4 (normalized to focal length or to sensor half width?)
0.0, // double distortionB // r^3
0.0, // double distortionC // r^2
1296.0, // double px0=1296.0; // center of the lens on the sensor, pixels
968.0, // double py0=968.0; // center of the lens on the sensor, pixels
1.0); //channelWeightDefault
for (int i=16;i<24;i++) if (i<numSubCameras) this.eyesisSubCameras[numStation][i]=new EyesisSubCameraParameters( // bottom eight cameras
45.0*(i-16), // double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
41.540, // double radius, // mm, distance from the rotation axis
-42.883, // double height, // mm, up (was downwards?) - from the origin point
0.0, // double phi, // degrees, optical axis from azimuth/r vector, clockwise
-60.0, //double theta, // degrees, optical axis from the eyesis horizon, positive - up
-90.0, //double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
4.5, // double focalLength
2.2, // double pixelSize (um)
2.8512, //double distortionRadius mm - half width of the sensor
0.0, // double distortionA8 // r^8 (normalized to focal length or to sensor half width?)
0.0, // double distortionA7 // r^7 (normalized to focal length or to sensor half width?)
0.0, // double distortionA6 // r^6 (normalized to focal length or to sensor half width?)
0.0, // double distortionA5 // r^5 (normalized to focal length or to sensor half width?)
0.0, // double distortionA // r^4 (normalized to focal length or to sensor half width?)
0.0, // double distortionB // r^3
0.0, // double distortionC // r^2
1296.0, // double px0=1296.0; // center of the lens on the sensor, pixels
968.0, // double py0=968.0; // center of the lens on the sensor, pixels
1.0); //channelWeightDefault
if (24<numSubCameras) this.eyesisSubCameras[numStation][24]=new EyesisSubCameraParameters(
90, // double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
12.025, // double radius, // mm, distance from the rotation axis
-807.0, // double height, // mm, up - from the origin point
0.0, // double phi, // degrees, optical axis from azimuth/r vector, clockwise
0.0, //double theta, // degrees, optical axis from the eyesis horizon, positive - up
90.0, //double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
4.5, // double focalLength
2.2, // double pixelSize (um)
2.8512, //double distortionRadius mm - half width of the sensor
0.0, // double distortionA8 // r^8 (normalized to focal length or to sensor half width?)
0.0, // double distortionA7 // r^7 (normalized to focal length or to sensor half width?)
0.0, // double distortionA6 // r^6 (normalized to focal length or to sensor half width?)
0.0, // double distortionA5 // r^5 (normalized to focal length or to sensor half width?)
0.0, // double distortionA // r^4 (normalized to focal length or to sensor half width?)
0.0, // double distortionB // r^3
0.0, // double distortionC // r^2
1296.0, // double px0=1296.0; // center of the lens on the sensor, pixels
968.0, // double py0=968.0; // center of the lens on the sensor, pixels
4.0); //channelWeightDefault
if (25<numSubCameras) this.eyesisSubCameras[numStation][25]=new EyesisSubCameraParameters(
270, // double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
12.025, // double radius, // mm, distance from the rotation axis
-841.0, // double height, // mm, up - from the origin point
0.0, // double phi, // degrees, optical axis from azimuth/r vector, clockwise
0.0, //double theta, // degrees, optical axis from the eyesis horizon, positive - up
-90.0, //double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
4.5, // double focalLength
2.2, // double pixelSize (um)
2.8512, //double distortionRadius mm - half width of the sensor
0.0, // double distortionA8 // r^8 (normalized to focal length or to sensor half width?)
0.0, // double distortionA7 // r^7 (normalized to focal length or to sensor half width?)
0.0, // double distortionA6 // r^6 (normalized to focal length or to sensor half width?)
0.0, // double distortionA5 // r^5 (normalized to focal length or to sensor half width?)
0.0, // double distortionA // r^4 (normalized to focal length or to sensor half width?)
0.0, // double distortionB // r^3
0.0, // double distortionC // r^2
1296.0, // double px0=1296.0; // center of the lens on the sensor, pixels
968.0, // double py0=968.0; // center of the lens on the sensor, pixels
4.0); //channelWeightDefault
}
}
public void recenterVertically(boolean [] subcams, boolean [] stations){
boolean sameCenterAboveHorizontal=true;
double cah=Double.NaN;
for (int i=0;i<stations.length;i++){
if (stations[i]) {
if (Double.isNaN(cah)) cah=this.centerAboveHorizontal[i];
else if (cah!=this.centerAboveHorizontal[i]) sameCenterAboveHorizontal=false;
}
}
if (Double.isNaN(cah)){
System.out.println("No stations enabled, nothing to do for vertical centering");
return;
}
System.out.println("centerAboveHorizontal "+
(sameCenterAboveHorizontal?"is common for all stations":"differs between stations"));
if (sameCenterAboveHorizontal){
System.out.println("Re-centering vertically for centerAboveHorizontal common for all stations ");
double sumWeightedHeights=0.0;
double sumWeights=0.0;
for (int i=0;i<stations.length;i++) if (stations[i]) {
for (int subIndex=0; subIndex<subcams.length;subIndex++) if (subcams[subIndex]){
System.out.println("Averaging station "+i+", subcamera "+subIndex);
sumWeights+=stationWeight[i];
sumWeightedHeights+=stationWeight[i]*eyesisSubCameras[i][subIndex].height;
}
}
if (sumWeights==0.0){
System.out.println("No subcams are enabled, nothing to do for vertical centering");
return;
}
sumWeightedHeights/=sumWeights;
for (int i=0;i<stations.length;i++) if (stations[i]) {
for (int subIndex=0; subIndex<subcams.length;subIndex++) { // need to update all channels, not only averaged
eyesisSubCameras[i][subIndex].height-=sumWeightedHeights;
}
this.centerAboveHorizontal[i]+=sumWeightedHeights;
}
} else {
System.out.println("Re-centering vertically for centerAboveHorizontal individual for each station");
for (int i=0;i<stations.length;i++) if (stations[i]) {
double sumWeightedHeights=0.0;
double sumWeights=0.0;
for (int subIndex=0; subIndex<subcams.length;subIndex++) if (subcams[subIndex]){
System.out.println("Averaging station "+i+", subcamera "+subIndex);
sumWeights+=stationWeight[i];
sumWeightedHeights+=stationWeight[i]*eyesisSubCameras[i][subIndex].height;
}
if (sumWeights==0.0){
System.out.println("No subcams are enabled, nothing to do for vertical centering");
return;
}
sumWeightedHeights/=sumWeights;
for (int subIndex=0; subIndex<subcams.length;subIndex++) { // need to update all channels, not only averaged
eyesisSubCameras[i][subIndex].height-=sumWeightedHeights;
}
this.centerAboveHorizontal[i]+=sumWeightedHeights;
}
}
}
}
\ No newline at end of file
/*
**
** EyesisSubCameraParameters.java
**
** Copyright (C) 2011-2014 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** EyesisSubCameraParameters.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
import java.util.Properties;
public class EyesisSubCameraParameters{
// origin is on the rotation axis of the tube body closest to the goniometer horizontal axis
public double azimuth; // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
public double radius; // mm, distance from the rotation axis
public double height; // mm, up - from the origin point
public double phi; // degrees, optical axis from azimuth/r vector, clockwise
public double theta; // degrees, optical axis from the eyesis horizon, positive - up
public double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
public double focalLength=4.5;
public double pixelSize= 2.2; //um
public double distortionRadius= 2.8512; // mm - half width of the sensor
public double distortionA8=0.0; //r^8 (normalized to focal length or to sensor half width?)
public double distortionA7=0.0; //r^7 (normalized to focal length or to sensor half width?)
public double distortionA6=0.0; //r^6 (normalized to focal length or to sensor half width?)
public double distortionA5=0.0; //r^5 (normalized to focal length or to sensor half width?)
public double distortionA=0.0; // r^4 (normalized to focal length or to sensor half width?)
public double distortionB=0.0; // r^3
public double distortionC=0.0; // r^2
public double px0=1296.0; // center of the lens on the sensor, pixels
public double py0=968.0; // center of the lens on the sensor, pixels
public double channelWeightDefault=1.0;
public double channelWeightCurrent=1.0;
public int [][] defectsXY=null; // pixel defects coordinates list (starting with worst)
public double [] defectsDiff=null; // pixel defects value (diff from average of neighbors), matching defectsXY
public EyesisSubCameraParameters(
double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
double radius, // mm, distance from the rotation axis
double height, // mm, up from the origin point
double phi, // degrees, optical axis from azimuth/r vector, clockwise
double theta, // degrees, optical axis from the eyesis horizon, positive - up
double psi, // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
double focalLength,
double pixelSize,//um
double distortionRadius, //mm - half width of the sensor
double distortionA8, // r^8
double distortionA7, // r^7
double distortionA6, // r^5
double distortionA5, // r^5
double distortionA, // r^4 (normalized to focal length or to sensor half width?)
double distortionB, // r^3
double distortionC, // r^2
double px0, // center of the lens on the sensor, pixels
double py0, // center of the lens on the sensor, pixels
double channelWeightDefault
){
this.azimuth=azimuth;
this.radius=radius;
this.height=height;
this.phi=phi;
this.theta=theta;
this.psi=psi;
this.focalLength=focalLength;
this.pixelSize= pixelSize; //um
this.distortionRadius= distortionRadius; // mm - half width of the sensor
this.distortionA8=distortionA8;
this.distortionA7=distortionA7;
this.distortionA6=distortionA6;
this.distortionA5=distortionA5;
this.distortionA=distortionA; // r^4 (normalized to focal length or to sensor half width?)
this.distortionB=distortionB; // r^3
this.distortionC=distortionC; // r^2
this.px0=px0;
this.py0=py0;
this.channelWeightDefault=channelWeightDefault;
this.channelWeightCurrent=this.channelWeightDefault;
this.defectsXY=null; // pixel defects coordinates list (starting with worst)
this.defectsDiff=null; // pixel defects value (diff from average of neighbors), matching defectsXY
}
// defects are not cloned!
public EyesisSubCameraParameters clone() {
return new EyesisSubCameraParameters(
this.azimuth,
this.radius,
this.height,
this.phi,
this.theta,
this.psi,
this.focalLength,
this.pixelSize,
this.distortionRadius,
this.distortionA8,
this.distortionA7,
this.distortionA6,
this.distortionA5,
this.distortionA,
this.distortionB,
this.distortionC,
this.px0,
this.py0,
this.channelWeightDefault
);
}
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"azimuth",this.azimuth+"");
properties.setProperty(prefix+"radius",this.radius+"");
properties.setProperty(prefix+"height",this.height+"");
properties.setProperty(prefix+"phi",this.phi+"");
properties.setProperty(prefix+"theta",this.theta+"");
properties.setProperty(prefix+"psi",this.psi+"");
properties.setProperty(prefix+"focalLength",this.focalLength+"");
properties.setProperty(prefix+"pixelSize",this.pixelSize+"");
properties.setProperty(prefix+"distortionRadius",this.distortionRadius+"");
properties.setProperty(prefix+"distortionA8",this.distortionA8+"");
properties.setProperty(prefix+"distortionA7",this.distortionA7+"");
properties.setProperty(prefix+"distortionA6",this.distortionA6+"");
properties.setProperty(prefix+"distortionA5",this.distortionA5+"");
properties.setProperty(prefix+"distortionA",this.distortionA+"");
properties.setProperty(prefix+"distortionB",this.distortionB+"");
properties.setProperty(prefix+"distortionC",this.distortionC+"");
properties.setProperty(prefix+"px0",this.px0+"");
properties.setProperty(prefix+"py0",this.py0+"");
properties.setProperty(prefix+"channelWeightDefault",this.channelWeightDefault+"");
}
public void getProperties(String prefix,Properties properties){
if (properties.getProperty(prefix+"azimuth")!=null)
this.azimuth=Double.parseDouble(properties.getProperty(prefix+"azimuth"));
if (properties.getProperty(prefix+"radius")!=null)
this.radius=Double.parseDouble(properties.getProperty(prefix+"radius"));
if (properties.getProperty(prefix+"height")!=null)
this.height=Double.parseDouble(properties.getProperty(prefix+"height"));
if (properties.getProperty(prefix+"phi")!=null)
this.phi=Double.parseDouble(properties.getProperty(prefix+"phi"));
if (properties.getProperty(prefix+"theta")!=null)
this.theta=Double.parseDouble(properties.getProperty(prefix+"theta"));
if (properties.getProperty(prefix+"psi")!=null)
this.psi=Double.parseDouble(properties.getProperty(prefix+"psi"));
if (properties.getProperty(prefix+"focalLength")!=null)
this.focalLength=Double.parseDouble(properties.getProperty(prefix+"focalLength"));
if (properties.getProperty(prefix+"pixelSize")!=null)
this.pixelSize=Double.parseDouble(properties.getProperty(prefix+"pixelSize"));
if (properties.getProperty(prefix+"distortionRadius")!=null)
this.distortionRadius=Double.parseDouble(properties.getProperty(prefix+"distortionRadius"));
if (properties.getProperty(prefix+"distortionA8")!=null)
this.distortionA8=Double.parseDouble(properties.getProperty(prefix+"distortionA8"));
if (properties.getProperty(prefix+"distortionA7")!=null)
this.distortionA7=Double.parseDouble(properties.getProperty(prefix+"distortionA7"));
if (properties.getProperty(prefix+"distortionA6")!=null)
this.distortionA6=Double.parseDouble(properties.getProperty(prefix+"distortionA6"));
if (properties.getProperty(prefix+"distortionA5")!=null)
this.distortionA5=Double.parseDouble(properties.getProperty(prefix+"distortionA5"));
if (properties.getProperty(prefix+"distortionA")!=null)
this.distortionA=Double.parseDouble(properties.getProperty(prefix+"distortionA"));
if (properties.getProperty(prefix+"distortionB")!=null)
this.distortionB=Double.parseDouble(properties.getProperty(prefix+"distortionB"));
if (properties.getProperty(prefix+"distortionC")!=null)
this.distortionC=Double.parseDouble(properties.getProperty(prefix+"distortionC"));
if (properties.getProperty(prefix+"px0")!=null)
this.px0=Double.parseDouble(properties.getProperty(prefix+"px0"));
if (properties.getProperty(prefix+"py0")!=null)
this.py0=Double.parseDouble(properties.getProperty(prefix+"py0"));
if (properties.getProperty(prefix+"channelWeightDefault")!=null) {
this.channelWeightDefault=Double.parseDouble(properties.getProperty(prefix+"channelWeightDefault"));
this.channelWeightCurrent=this.channelWeightDefault;
}
}
public void setChannelWeightCurrent(
double weight){
this.channelWeightCurrent=weight;
}
public double getChannelWeightCurrent(){
return this.channelWeightCurrent;
}
public double getChannelWeightDefault(){
return this.channelWeightDefault;
}
}
......@@ -2516,7 +2516,7 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos
return false;
}
/* ======================================================================== */
private String [] selectSourceFiles(String [] defaultPaths) {
public String [] selectSourceFiles(String [] defaultPaths) {
String []patterns={".jp4",".jp46",".tiff",".tif"};
return selectFiles(false, // save
"Source file(s) selection", // title
......
/*
**
** FittingStrategy.java
**
** Copyright (C) 2011-2014 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** FittingStrategy.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
import ij.IJ;
import ij.gui.GenericDialog;
import ij.text.TextWindow;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
/**
*
* Specifies images to process and parameters to adjust
* Each parameter cab be:
* 0 - "fixed" - use individual, per-image parameters, do not modify them
* 1 - "common" - parameters are common for all selected images.
* When saving - save to all selected images.
* When loading (if different) use "master image" (or closest to it in time)
* 2 - "super common" - same as common, but save to all images, not just selected
* 3 - "individual"
* 4 - "per group"
* 5 - "per-station"
* 6 - "per-station" save to all (super)
* 7 - "weak common" - like common, but enable small individual variations (for a price) - not yet implemented, will have separate weight fixed/floating
* 8 - "weak station" - like per-station, but enable individual (for a price)
*
+====================+===========+===========+
| | Same TS | Diff TS |
| +-----+-----+-----+-----+
| | C | I | C | I |
+============+=======+=====+=====+=====+=====+
| Same |Eyesis | X | X | C | I |
| Subcamera +-------+-----+-----+-----+-----+
| |Subcam | X | X | C | I* |
+============+=======+=====+=====+=====+=====+
| Different |Eyesis | C | C | C | I |
| Subcameras +-------+-----+-----+-----+-----+
| |Subcam | I | I | I | I |
+============+=======+=====+=====+=====+=====+
I* - special case when the subcamera is being adjusted/replaced. How to deal with it?
*
*/
public class FittingStrategy{
public String pathName=null; // path to XML file this instance was created from
public DistortionCalibrationData distortionCalibrationData=null;// per-image parameters
private boolean [][] selectedImages=null; // images selected for each step (will be masked with enabled images)
private boolean [][] selectedValidImages=null; // images selected for each step same as selected, but only if number of weight>0.0 nodes > threshold
public boolean [] stopAfterThis=null;
final public int modeFixed=0,modeCommon=1,modeSupercommon=2,modeIndividual=3,modeGroup=4;
final public int modeStation=5,modeSuperStation=6,modeWeakCommon=7,modeWeakStation=8,modeTiltEqualize=9;
public String[] definedModes={
"fixed", // modeFixed=0
"common", // modeCommon=1
"common, save to all", // modeSupercommon=2
"individual", // modeIndividual=3
"per-group", // modeGroup=4
"per-station", // modeStation=5
"per-station, save to all", // modeSuperStation=6
"weak common, save to all", // modeWeakCommon=7
"weak per-station, save to all" // modeWeakStation=8
};
public String[] definedModesNoWeak={ // show for parameters that can not use weak
"fixed", // modeFixed=0
"common", // modeCommon=1
"common, save to all", // modeSupercommon=2
"individual", // modeIndividual=3
"per-group", // modeGroup=4
"per-station", // modeStation=5
"per-station, save to all" // modeSuperStation=6
// "weak common", // modeWeakCommon=7
// "weak per-station", // modeWeakStation=8
};
public String[] definedModesTiltEq={ // show for parameters that can not use weak
"fixed", // modeFixed=0
"common", // modeCommon=1
"common, save to all", // modeSupercommon=2
"individual", // modeIndividual=3
"per-group", // modeGroup=4
"per-station", // modeStation=5
"per-station, save to all", // modeSuperStation=6
"weak common, save to all", // modeWeakCommon=7
"weak per-station, save to all",// modeWeakStation=8
"tilt equalize" // modeTiltEqualize
};
public String[] definedModesAll= definedModesTiltEq;
public int [][] parameterMode=null; // per series, per-parameter
public int [][][] parameterGroups=null; // per series, per-parameter - null or array of group numbers (1 element per image)
public int [][] zGroups=null;
public boolean saveUnusedGroups=false; // purge groups for parameters when saving to XML, preserve if true
public double [] lambdas=null; // LMA initial lambda for each step
public double defaultLambda=0.001;
public int [][] parameterList=null; // list of all parameters in the system, each has subcamera number and parameters index
public boolean [] parameterEnable=null; // select which parameters (of some 320 to display in selector)
public int [] masterImages=null; // number of image no take "common" parameters from if they are different
public double defaultStepDone=1.0E-6;
public double [] stepDone=null;// delta_error to error ratio to consider series finished
// public double [] parameterVector;
public int [][] parameterMap=null;// ** valid for one strategy sequence *** for each parameter vector element hold image number/parameter number
public int [][] reverseParameterMap=null; // reversed map - for each [imageNumber][parameterNumber] -> vector index (-1 fixed)
public int currentSeriesNumber=-1; // currently selected strategy step (for which parameterMap and reverseParameterMap)
public int debugLevel=2;
public int [] varianceModes=null; // per-series: 0 - disabled, 1 - constant imageSets weight, 2 - variable imageSets weight
final public int varianceModeDisabled=0,varianceModeSameWeight=1,varianceModeVariableWeight=2;
public String [] definedVarianceModes={
"disabled",
"same weight",
"variable weight",
};
// next arrays will be initialized at buildVariancesMaps only if at least some parameters use variances, otherwise they will be null
public double [] variationsAverages=null; // holds per extrinsic parameter or per parameter/per station average values
public int [] averageCellIndex= null; // for each element in the parameters vector holds index in variationsAverages array
public double [] weightOnAverage= null; // how variation of this parameter influences average (for all or for currenrt station
public double [] weightVariance= null; // weight for LMA over variance of parameters from average
public double [] varianceErrorsSquared= null; // weighted squared errors
public FittingStrategy(
DistortionCalibrationData distortionCalibrationData// per-image parameters
) {
this.distortionCalibrationData=distortionCalibrationData;
setDflt(0);
}
public FittingStrategy(
DistortionCalibrationData distortionCalibrationData,// per-image parameters
int numSeries // number of iteration series
){
this.distortionCalibrationData=distortionCalibrationData;
this.selectedImages=new boolean[numSeries][this.distortionCalibrationData.getNumImages()];
this.selectedValidImages=new boolean[numSeries][this.distortionCalibrationData.getNumImages()];
setDflt(numSeries);
}
public FittingStrategy(
boolean smart,
String defaultPath,
DistortionCalibrationData distortionCalibrationData // per-image parameters
) {
String [] extensions={".stg-xml","-strategy.xml"};
CalibrationFileManagement.MultipleExtensionsFileFilter parFilter = new CalibrationFileManagement.MultipleExtensionsFileFilter("",extensions,"*.stg-xml files");
String pathname=CalibrationFileManagement.selectFile(
smart,
false,
"Restore Fitting Strategy",
"Restore",
parFilter,
defaultPath); //String defaultPath
if ((pathname==null) || (pathname=="")) return;
setFromXML(
distortionCalibrationData, // per-image parameters
pathname);
System.out.println("Restored fitting strategy from "+pathname);
}
/**
* Reads FittingStrategy from an XML file
* @param distortionCalibrationData should be defined before this class!
* @param pathname pathe to the saved data
*/
public FittingStrategy(
DistortionCalibrationData distortionCalibrationData, // per-image parameters
String pathname
) {
setFromXML(
distortionCalibrationData, // per-image parameters
pathname);
}
public void setFromXML(
DistortionCalibrationData distortionCalibrationData, // per-image parameters
String pathname
) {
this.distortionCalibrationData=distortionCalibrationData;
XMLConfiguration hConfig=null;
try {
hConfig=new XMLConfiguration(pathname);
} catch (ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
hConfig.setThrowExceptionOnMissing(false); // default value, will return null on missing
// read parameterList
int len=Integer.parseInt(hConfig.getString("parameterMap.length","0"));
if (len<=0) {
String msg="No parameterMap specified in "+ pathname;
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
this.parameterList=new int [len][2];
this.parameterEnable=new boolean[len];
for (int i=0; i<this.parameterList.length; i++){
this.parameterList[i][0]=Integer.parseInt(hConfig.getString("parameterMap.par_"+i+".subcamera"));
this.parameterList[i][1]=Integer.parseInt(hConfig.getString("parameterMap.par_"+i+".index"));
this.parameterEnable[i]= (Integer.parseInt(hConfig.getString("parameterMap.par_"+i+".visible"))>0);
}
int nSer=Integer.parseInt(hConfig.getString("series.number","0"));
if (nSer==0) return; // arrays will just be null
this.selectedImages=new boolean[nSer][];
this.selectedValidImages=new boolean[nSer][];
this.masterImages=new int[nSer];
this.stopAfterThis=new boolean[nSer];
for (int i=0;i<nSer;i++) this.stopAfterThis[i]=true; // older configuration files did not have it
this.parameterMode=new int[nSer][len];
this.varianceModes=new int[nSer];
this.zGroups=new int [nSer][];
this.parameterGroups=new int[nSer][len][];
this.lambdas=new double [nSer];
this.stepDone=new double [nSer];
for (int i=0;i<nSer;i++){ // iterate through series
//this.stopAfterThis
// read selected images (no check here that it matches to the distortionCalibrationData!
String sSeries="series.series_"+i;
String fs=hConfig.getString(sSeries+".selectedImages");
this.selectedImages[i]=new boolean[fs.length()];
this.selectedValidImages[i]=null;
for (int j=0;j<this.selectedImages[i].length;j++) this.selectedImages[i][j]=(fs.charAt(j)=='+');
this.masterImages[i]=Integer.parseInt(hConfig.getString(sSeries+".masterImage"));
if (hConfig.getString(sSeries+".varianceModes")!=null) {
this.varianceModes[i]=Integer.parseInt(hConfig.getString(sSeries+".varianceModes"));
} else {
this.varianceModes[i]=varianceModeDisabled;
}
for (int j=0;j<this.parameterList.length;j++){
int nPar=this.parameterList[j][1];
int nSub=this.parameterList[j][0];
String hconfigName=sSeries+".parameterMode."+
this.distortionCalibrationData.parameterDescriptions[nPar][0]+
(this.distortionCalibrationData.isSubcameraParameter(nPar)?("_sub"+nSub):"");
// System.out.println("Setting this.parameterMode["+i+"]["+j+"] from " +hconfigName);
if (hConfig.getString(hconfigName)!=null) this.parameterMode[i][j]=Integer.parseInt(hConfig.getString(hconfigName));
else System.out.println("Failed to set this.parameterMode["+i+"]["+j+"] from " +hconfigName+" - maybe it is a new parameter not present in the file "+pathname);
this.parameterGroups[i][j]=null;
//Try to read series
for (int ni=0;ni<this.selectedImages.length;ni++){
String sGroup=hConfig.getString(sSeries+".parameterMode."+
this.distortionCalibrationData.parameterDescriptions[nPar][0]+
(this.distortionCalibrationData.isSubcameraParameter(nPar)?("_sub"+nSub):"")+
"_group"+ni);
if (sGroup!=null){
if (this.parameterGroups[i][j]==null){
this.parameterGroups[i][j]=new int[this.selectedImages.length];
for (int ni1=0;ni1<this.selectedImages.length;ni1++)this.parameterGroups[i][j][ni1]=0;
}
this.parameterGroups[i][j][ni]=Integer.parseInt(sGroup);
}
}
}
this.lambdas[i]=Double.parseDouble(hConfig.getString(sSeries+".lambdas"));
this.stepDone[i]=Double.parseDouble(hConfig.getString(sSeries+".stepDone"));
if (hConfig.getString(sSeries+".stopAfterThis")!=null){
this.stopAfterThis[i]=Boolean.parseBoolean(hConfig.getString(sSeries+".stopAfterThis"));
}
String zGroupsName=sSeries+".zGroups";
if (hConfig.getString(zGroupsName)!=null) {
int numZgroups=Integer.parseInt(hConfig.getString(zGroupsName));
this.zGroups[i]=new int [numZgroups];
for (int nZGroup=0;nZGroup<numZgroups;nZGroup++){
this.zGroups[i][nZGroup]=Integer.parseInt(hConfig.getString(sSeries+".zGroup_"+nZGroup));
}
} else {
this.zGroups[i]=null;
}
}
// if (hConfig.getString("variances")!=null){
// if (!hConfig.configurationAt("variances").isEmpty()){
if (hConfig.configurationsAt("variances").size()>0){
// System.out.println("hConfig.configurationAt(\"variances\").isEmpty()=false");
this.distortionCalibrationData.eyesisCameraParameters.getCostsPropertiesXML("variances.",hConfig);
}
this.pathName=pathname;
// distortionCalibrationData.readAllGrids();
}
/**
* Adjust selectedImages and parameterGroups after number of images may change, old number of images should be >0
* If the new number is larger, the first images attributes will be copied, the extra ones - use those of the last of the old ones
* @param newNumberOfImages new number of images used by this series
*/
public void adjustNumberOfImages(int newNumberOfImages){
if ((this.selectedImages == null) ||(this.selectedImages[0].length==0)) {
String msg="selectedImages array is "+((this.selectedImages == null)?"null":"empty");
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
if (this.selectedImages[0].length==newNumberOfImages) return;
for (int nSer=0;nSer<this.selectedImages.length;nSer++){
boolean [] tmp=selectedImages[nSer].clone();
this.selectedImages[nSer]=new boolean[newNumberOfImages];
this.selectedValidImages[nSer]=null; // just invalidate
for (int i=0;i<newNumberOfImages;i++) this.selectedImages[nSer][i]=(i<tmp.length)?tmp[i]:tmp[tmp.length-1];
for (int nPar=0;nPar<this.parameterList.length;nPar++){
if (this.parameterGroups[nSer][nPar]!=null){
int [] tmpGroup=this.parameterGroups[nSer][nPar].clone();
this.parameterGroups[nSer][nPar]=new int[newNumberOfImages];
for (int i=0;i<newNumberOfImages;i++) this.parameterGroups[nSer][nPar][i]=(i<tmpGroup.length)?tmpGroup[i]:tmpGroup[tmpGroup.length-1];
}
}
}
}
public String selectAndSaveToXML(
boolean smart,
String defaultPath){
String [] extensions={".stg-xml","-strategy.xml"};
CalibrationFileManagement.MultipleExtensionsFileFilter parFilter = new CalibrationFileManagement.MultipleExtensionsFileFilter("",extensions,"*.stg-xml files");
if ((defaultPath==null) || (defaultPath.length()==0)){
defaultPath=this.pathName;
}
String pathname=CalibrationFileManagement.selectFile(
smart,
true,
"Save Fitting Strategy",
"Save",
parFilter,
defaultPath); //String defaultPath
if (pathname!=null) saveToXML(pathname);
return pathname;
}
//http://commons.apache.org/configuration/userguide/howto_xml.html
public boolean saveToXML(String pathname) {
if (pathname==null) return false;
XMLConfiguration hConfig=new XMLConfiguration();
hConfig.setRootElementName("FittingStrategy");
// write which of the overall parameter correspond to each global/subcamera one, and which parameters are hidden/shown
hConfig.addProperty("parameterMap","");
hConfig.addProperty("parameterMap.length",this.parameterList.length);
for (int i=0; i<this.parameterList.length; i++){
hConfig.addProperty("parameterMap.par_"+i,"");
hConfig.addProperty("parameterMap.par_"+i+".subcamera",this.parameterList[i][0]);
hConfig.addProperty("parameterMap.par_"+i+".index",this.parameterList[i][1]);
hConfig.addProperty("parameterMap.par_"+i+".visible",this.parameterEnable[i]?"1":"0");
}
hConfig.addProperty("series","");
hConfig.addProperty("series.number",this.selectedImages.length);
for (int i=0;i<this.selectedImages.length;i++){ // iterate through series
String sSeries="series.series_"+i;
hConfig.addProperty(sSeries,"");
String fs="";
for (int j=0;j<this.selectedImages[i].length;j++)fs+=this.selectedImages[i][j]?"+":"-";
hConfig.addProperty(sSeries+".selectedImages",fs);
hConfig.addProperty(sSeries+".masterImage",this.masterImages[i]);
if (this.varianceModes!=null) hConfig.addProperty(sSeries+".varianceModes",this.varianceModes[i]);
hConfig.addProperty(sSeries+".parameterMode","");
for (int j=0;j<this.parameterList.length;j++){
int nPar=this.parameterList[j][1];
int nSub=this.parameterList[j][0];
hConfig.addProperty(sSeries+".parameterMode."+
this.distortionCalibrationData.parameterDescriptions[nPar][0]+
(this.distortionCalibrationData.isSubcameraParameter(nPar)?("_sub"+nSub):""),
this.parameterMode[i][j]);
// cleaning up output - removing unused groups (may disable
if (((this.parameterMode[i][j]==this.modeGroup) || this.saveUnusedGroups ) && (this.parameterGroups[i][j]!=null)){
for (int ni=0;ni<this.parameterGroups[i][j].length;ni++){
hConfig.addProperty(sSeries+".parameterMode."+
this.distortionCalibrationData.parameterDescriptions[nPar][0]+
(this.distortionCalibrationData.isSubcameraParameter(nPar)?("_sub"+nSub):"") +"_group"+ni,
this.parameterGroups[i][j][ni]);
}
}
}
if (this.zGroups[i]!=null) {
hConfig.addProperty(sSeries+".zGroups", this.zGroups[i].length);
for (int nZGroup=0;nZGroup<this.zGroups[i].length;nZGroup++){
hConfig.addProperty(sSeries+".zGroup_"+nZGroup,this.zGroups[i][nZGroup]);
}
}
hConfig.addProperty(sSeries+".lambdas",lambdas[i]);
hConfig.addProperty(sSeries+".stepDone",stepDone[i]);
hConfig.addProperty(sSeries+".stopAfterThis",this.stopAfterThis[i]);
}
hConfig.addProperty("variances","");
this.distortionCalibrationData.eyesisCameraParameters.setCostsPropertiesXML("variances.",hConfig);
File file=new File (pathname);
BufferedWriter writer;
try {
writer = new BufferedWriter(new FileWriter(file));
hConfig.save(writer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.pathName=pathname;
return true;
}
/**
* Verifies that series exists and is not empty (valid for LMA)
* @param num - series to verify
* @return true if series is valid
*/
public boolean isSeriesValid(int num){
if ((num<0) || (num>=this.selectedImages.length)) return false;
boolean someImagesSelected=false;
for (int i=0;i<this.selectedImages[num].length;i++) if (this.selectedImages[num][i]){
someImagesSelected=true;
break;
}
if (!someImagesSelected) {
if (this.debugLevel>0) System.out.println("isSeriesValid("+num+"): no images selected");
return false;
}
boolean someParametersSelected=false;
for (int i=0;i<this.parameterMode[num].length;i++) if (this.parameterMode[num][i]>0){
someParametersSelected=true;
break;
}
if (!someParametersSelected) {
if (this.debugLevel>0) System.out.println("isSeriesValid("+num+"): no parameters selected");
return false;
}
return true;
}
/**
* Determins if LMA should stop after this series (either flag is set or next is invalid)
* @param num number of series to test
* @return true if LMA should stop
*/
public boolean isLastSeries(int num){
if (this.stopAfterThis[num]) return true;
if (!isSeriesValid(num+1)) return true;
return false;
}
/**
*
* Specifies images to process and parameters to adjust
* Each parameter cab be:
* 0 - "fixed" - use individual, per-image parameters, do not modify them
* 1 - "common" - parameters are common for all selected images.
* When saving - save to all selected images.
* When loading (if different) use "master image" (or closest to it in time)
* 2 - "super common" - same as common, but save to all images, not just selected
* 3 - "individual"
+====================+===========+===========+
| | Same TS | Diff TS |
| +-----+-----+-----+-----+
| | C | I | C | I |
+============+=======+=====+=====+=====+=====+
| Same |Eyesis | X | X | C | I |
| Subcamera +-------+-----+-----+-----+-----+
| |Subcam | X | X | C | I* |
+============+=======+=====+=====+=====+=====+
| Different |Eyesis | C | C | C | I |
| Subcameras +-------+-----+-----+-----+-----+
| |Subcam | X | X | X | X | subcameras for different subcameras are individual parameters
+============+=======+=====+=====+=====+=====+
I* - special case when the subcamera is being adjusted/replaced. How to deal with it?
*
*/
// public int [][] reverseParameterMap=null; // reversed map - for each [imageNumber][parameterNumber] -> vector index (-1 fixed)\
// selects all enabled images in the specified series (modifies strategy series!)
/**
* selects all enabled images in the specified series (modifies strategy series!)
* @param ser number of fitting strategy series to set
* @return old value for series images selection
*/
public boolean [] selectAllImages(int ser){
// this.selectedValidImages[ser]=null; // just invalidate - do nothing, so restore would work
boolean [] oldSelection=this.selectedImages[ser].clone();
for (int i=0;i<this.selectedImages[ser].length;i++) this.selectedImages[ser][i]=true; // select all\
return oldSelection;
}
/**
* Sets image selection. Can be used to restore saved selection after selectAllImages(int ser)
* @param ser number of fitting strategy series to set
* @param selection array specifying selected images
*/
public void setImageSelection(int ser, boolean [] selection){
this.selectedImages[ser]=selection.clone();
}
public boolean [] selectedAllImages() {
// if (this.currentSeriesNumber<0) return null;
return selectedAllImages(this.currentSeriesNumber);
}
public boolean [] selectedAllImages(int ser) {
if ((ser<0) || (ser>=this.selectedImages.length)){
boolean [] allImages=new boolean[this.selectedImages[0].length];
for (int i=0;i<allImages.length;i++) allImages[i]=true; // select all
return allImages;
} else {
return this.selectedImages[ser];
}
}
public boolean [] selectedImages() {
// if (this.currentSeriesNumber<0) return null;
return selectedImages(this.currentSeriesNumber);
}
public boolean [] selectedImagesNoBadKernels(int ser) {
boolean [] selected=selectedImages(ser);
for (int i=0;i<selected.length;i++) selected[i]&= !this.distortionCalibrationData.gIP[i].noUsefulPSFKernels;
return selected;
}
public void setNoUsefulPSFKernels(int i, boolean noUsefulPSFKernels){
this.distortionCalibrationData.gIP[i].noUsefulPSFKernels=noUsefulPSFKernels;
}
public void invalidateSelectedImages(int ser){
this.selectedValidImages[ser]=null;
}
public void initSelectedValidImages(int ser){
this.selectedValidImages[ser]=this.selectedImages[ser].clone();
}
public void invalidateSelectedImage(int ser,int nImg){
this.selectedValidImages[ser][nImg]=false;
}
//this.selectedValidImages
public boolean [] selectedImages(int ser) {
return selectedImages(ser,false);
}
public boolean [] selectedImages(int ser, boolean userSelection) {
boolean [] selectedMasked;
if ((ser<0) || (ser>=this.selectedImages.length)){
selectedMasked=new boolean[this.selectedImages[0].length];
for (int i=0;i<selectedMasked.length;i++) selectedMasked[i]=true; // select all
} else {
selectedMasked=this.selectedImages[ser].clone();
}
for (int i=0;i<selectedMasked.length;i++) selectedMasked[i] &= this.distortionCalibrationData.gIP[i].enabled;
// unselect empty
// TODO: add minimal number of nodes?
if ((ser>=0) && (this.selectedValidImages[ser]!=null) && !userSelection){
for (int i=0;i<selectedMasked.length;i++) selectedMasked[i] &= this.selectedValidImages[ser][i];
} else {
for (int i=0;i<selectedMasked.length;i++) selectedMasked[i] &= (this.distortionCalibrationData.gIP[i].pixelsXY.length>0);
}
return selectedMasked; //this.selectedImages[ser];
}
public int getNumSeries(){
return this.selectedImages.length;
}
/**
* Creates map from the parameter vector index to the {grid image number, parameter number}
* When the parameter is shared by several images, the map points to the one which value will be used
* (they might be different). Timestamp of the masterImages[] is used to determine which image to use.
* Simultaneously creates this.reverseParameterMap that maps each of the image/parameter to the parameter vector
* Needs to be run for each new strategy series
* @param numSeries number of fitting strategy series
* @return this.parameterMap
*/
public int buildParameterMap (int numSeries){
int numPars=this.distortionCalibrationData.getNumParameters();
int numImg=this.distortionCalibrationData.getNumImages();
int numTPars=this.parameterMode[numSeries].length;
this.reverseParameterMap=new int [numImg][numPars];
// boolean [] selectedEnabledImagesAll=selectedImages(numSeries,true); // strictly as in series, including no valid points ones
boolean [] selectedEnabledImages=selectedImages(numSeries);
// set defaults - -1 - "fixed", use individual parameter from this image
for (int i=0;i<numImg;i++) for (int j=0;j<numPars;j++) this.reverseParameterMap[i][j]=-1;
int vectorIndex=0;
// int [][] tmpMap=new int[numTPars][3]; // temporary array parameterMap[][] (will be truncated)
int [][] tmpMap=new int[numPars*numImg][3]; // temporary array parameterMap[][] (will be truncated)
double masterTS=this.distortionCalibrationData.getImageTimestamp(this.masterImages[numSeries]); // timestamp of the master image
// iterate through all global/subcamera parameters
for (int numTPar=0;numTPar<numTPars;numTPar++) if (this.parameterMode[numSeries][numTPar]!=this.modeFixed){ // skip "fixed"
boolean isCommon=
(this.parameterMode[numSeries][numTPar]==this.modeCommon) ||
(this.parameterMode[numSeries][numTPar]==this.modeSupercommon);
boolean isStation=
(this.parameterMode[numSeries][numTPar]==this.modeStation) ||
(this.parameterMode[numSeries][numTPar]==this.modeSuperStation);
boolean isGroup=(this.parameterMode[numSeries][numTPar]==this.modeGroup);
int numSub=this.parameterList[numTPar][0]; // number of sub-camera for this total parameter index
int numPar=this.parameterList[numTPar][1]; // number of per-image parameter for this total parameter index
boolean isSubCamera=this.distortionCalibrationData.isSubcameraParameter(numPar);
if (this.debugLevel>2) System.out.println("numTPar="+numTPar+" numSub="+numSub+" numPar="+numPar);
// iterate through available images
for (int numThisImg=0;numThisImg<numImg;numThisImg++) {
if ((selectedEnabledImages[numThisImg]) &&
(!isSubCamera || (numSub==this.distortionCalibrationData.getImageSubcamera(numThisImg))) &&
(this.reverseParameterMap[numThisImg][numPar]<0)){ // image used, this cell is not (yet) defined
if (this.debugLevel>2){
System.out.println("buildParameterMap("+numSeries+"): numThisImg="+numThisImg+", numPar="+numPar+", vectorIndex="+vectorIndex);
}
// assign it a new parameter
this.reverseParameterMap[numThisImg][numPar]=vectorIndex;
double thisTS=this.distortionCalibrationData.getImageTimestamp(numThisImg);
int thisStation=this.distortionCalibrationData.gIP[numThisImg].getStationNumber();
// set pointer to this first image
tmpMap[vectorIndex][0]=numThisImg; // vectorindex==22 > tmpMap.length?
tmpMap[vectorIndex][1]=numPar;
tmpMap[vectorIndex][2]=this.parameterMode[numSeries][numTPar];
double minDist=Math.abs(this.distortionCalibrationData.getImageTimestamp(numThisImg)-masterTS);
if (this.debugLevel>2) System.out.println("vectorIndex="+vectorIndex+" numThisImg="+numThisImg);
// see if same parameter in some other image(s) is shared
for (int numOtherImg=numThisImg+1;numOtherImg<numImg;numOtherImg++)
if ((selectedEnabledImages[numOtherImg]) && // OOB 1
(!isSubCamera || (numSub==this.distortionCalibrationData.getImageSubcamera(numOtherImg))) &&
(this.reverseParameterMap[numOtherImg][numPar]<0)){ // image used, this cell is not (yet) defined
if ((this.distortionCalibrationData.getImageTimestamp(numOtherImg)==thisTS) || // same parameter same timestamp - same group even if is set differently
(isStation && (this.distortionCalibrationData.gIP[numOtherImg].getStationNumber()==thisStation)) || // new
isCommon ||
(isGroup && (this.parameterGroups[numSeries][numTPar][numThisImg]==
this.parameterGroups[numSeries][numTPar][numOtherImg]))){
// assign it a the same parameter
this.reverseParameterMap[numOtherImg][numPar]=vectorIndex;
double thisDist=Math.abs(this.distortionCalibrationData.getImageTimestamp(numThisImg)-masterTS);
if (thisDist<minDist) {
minDist=thisDist;
tmpMap[vectorIndex][0]=numOtherImg;
}
}
}
vectorIndex++;
}
}
}
// reverseParameterMap built, vectorIndex equals to the total number of parameters needed for fitting
//truncate tmpMap into this.parameterMap[][]
this.parameterMap=new int[vectorIndex][];
for (int i=0;i<vectorIndex;i++) this.parameterMap[i] =tmpMap[i];
this.currentSeriesNumber=numSeries;
if (this.debugLevel>2) System.out.println("this.parameterMap.length="+this.parameterMap.length);
return this.parameterMap.length;
}
/**
* Prepare data for calculating additional LMA terms for parameter variances
* @param numSeries fitting series to use
* @return number of parameters for which variance is considered
*/
public int buildVariancesMaps (
int numSeries){
if (this.debugLevel>0){
System.out.println("buildVariancesMaps("+numSeries+")");
}
if ((this.varianceModes==null) || (this.varianceModes[numSeries]==varianceModeDisabled)){
this.averageCellIndex=null;
this.variationsAverages=null;
this.weightVariance=null;
this.varianceErrorsSquared=null;
return 0;
}
int debugThreshold=2;
boolean useSetWeights=(this.varianceModes[numSeries]==varianceModeVariableWeight);
int numPars=this.distortionCalibrationData.getNumParameters();
int numStations=this.distortionCalibrationData.eyesisCameraParameters.getNumStations();
// int numTPars=this.parameterMode[numSeries].length;
int numSeriesPars=this.parameterMap.length;
// count tilt positions per station
List<Integer> tiltList= new ArrayList<Integer>(1000);
Integer iStationTilt;
int tiltMotorIndex=2;
for (int numSPar=0;numSPar<numSeriesPars;numSPar++) {
if (this.parameterMap[numSPar]==null){
System.out.println("buildVariancesMaps() BUG - ,this.parameterMap["+numSPar+"]==null, numSeriesPars="+numSeriesPars);
continue;
}
int imgNumber=this.parameterMap[numSPar][0]; // null pointer for triclops after adding variances for tilt
int setNumber=this.distortionCalibrationData.gIP[imgNumber].getSetNumber();
int station= this.distortionCalibrationData.gIP[imgNumber].getStationNumber();
if (this.distortionCalibrationData.gIS[setNumber]==null){
System.out.println("buildVariancesMaps() BUG - ,this.distortionCalibrationData.gIS["+setNumber+"]==null, numSeriesPars="+numSeriesPars+
" numSPar="+numSPar+" imgNumber="+imgNumber+" station="+station);
continue;
}
if (this.distortionCalibrationData.gIS[setNumber].motors==null){
System.out.println("buildVariancesMaps() BUG - ,this.distortionCalibrationData.gIS["+setNumber+"].motors==null, numSeriesPars="+numSeriesPars+
" numSPar="+numSPar+" imgNumber="+imgNumber+" station="+station);
continue;
}
int tiltMotor=this.distortionCalibrationData.gIS[setNumber].motors[tiltMotorIndex];// null pointer for triclops after adding variances for tilt
iStationTilt=station+numStations*tiltMotor;
if (!tiltList.contains(iStationTilt)) tiltList.add(iStationTilt);
}
int numStationTilts=tiltList.size();
int [] numGroups=new int [numPars];
for (int i=0;i<numGroups.length;i++)numGroups[i]=0;
for (int numSPar=0;numSPar<numSeriesPars;numSPar++) {
int parIndex=this.parameterMap[numSPar][1];
// if ((numGroups[parIndex]==0) && (this.distortionCalibrationData.eyesisCameraParameters.isVarianceCostSet(parIndex))){
if (numGroups[parIndex]==0){
boolean isSet=this.distortionCalibrationData.eyesisCameraParameters.isVarianceCostSet(parIndex);
switch (this.parameterMap[numSPar][2]){
case modeWeakCommon:
if (isSet) numGroups[parIndex]=1;
if (this.debugLevel>debugThreshold) System.out.println(">>>1 "+numSPar+":"+parIndex +" - "+numGroups[parIndex]+" isSet="+isSet);
break;
case modeWeakStation:
if (isSet) numGroups[parIndex]=numStations;
if (this.debugLevel>debugThreshold) System.out.println(">>>2 "+numSPar+":"+parIndex +" - "+numGroups[parIndex]+" isSet="+isSet);
break;
case modeTiltEqualize:
if (isSet) numGroups[parIndex]=numStationTilts;
if (this.debugLevel>debugThreshold) System.out.println(">>>3 "+numSPar+":"+parIndex +" - "+numGroups[parIndex]+" isSet="+isSet);
break;
}
}
}
if (this.debugLevel>debugThreshold){
System.out.println("buildVariancesMaps() numGroups:");
for (int i=0;i<numGroups.length;i++) if (numGroups[i]>0) System.out.println("--- "+i+":"+numGroups[i]);
}
int startIndex=0;
for (int i=0;i<numGroups.length;i++){
if (numGroups[i]>0){
int num=numGroups[i];
numGroups[i]=startIndex;
startIndex+=num;
} else {
numGroups[i]=-1;
}
}
if (this.debugLevel>debugThreshold){
System.out.println("buildVariancesMaps() start indices:");
for (int i=0;i<numGroups.length;i++) if (numGroups[i]>=0) System.out.println("--- "+i+":"+numGroups[i]);
}
if (this.debugLevel>debugThreshold){
System.out.println("buildVariancesMaps() startIndex="+startIndex);
}
if (startIndex==0){ // no variance parameters defined
this.averageCellIndex=null;
this.variationsAverages=null;
this.weightVariance=null;
this.varianceErrorsSquared=null;
return 0;
}
// Assign average cell indices for each vector element, for each paramter it can be just 1 for global, numStations or number of tilt positions
this.averageCellIndex=new int [numSeriesPars];
for (int numSPar=0;numSPar<numSeriesPars;numSPar++) {
this.averageCellIndex[numSPar]=-1; // not applicable
int parIndex=this.parameterMap[numSPar][1];
// for (int numTPar=0;numTPar<numTPars;numTPar++) {
// int parIndex=this.parameterList[numTPar][1];
if ((numGroups[parIndex]>=0) && (this.distortionCalibrationData.eyesisCameraParameters.isVarianceCostSet(parIndex))){
int imgNumber=this.parameterMap[numSPar][0];
int setNumber=this.distortionCalibrationData.gIP[imgNumber].getSetNumber();
int station= this.distortionCalibrationData.gIP[imgNumber].getStationNumber();
switch (this.parameterMap[numSPar][2]){
case modeWeakCommon:
this.averageCellIndex[numSPar]=numGroups[parIndex];
break;
case modeWeakStation:
this.averageCellIndex[numSPar]=numGroups[parIndex]+station;
break;
case modeTiltEqualize:
int tiltMotor=this.distortionCalibrationData.gIS[setNumber].motors[tiltMotorIndex];
iStationTilt=station+numStations*tiltMotor;
this.averageCellIndex[numSPar]=numGroups[parIndex]+tiltList.indexOf(iStationTilt);
break;
}
}
}
if (this.debugLevel>1){
System.out.println("buildVariancesMaps() numStationTilts="+numStationTilts+" numSeriesPars="+numSeriesPars+ " useSetWeights="+useSetWeights+
" number of averages="+startIndex);
}
this.variationsAverages=new double [startIndex]; // total number of different averages
int [] numContributors=new int [startIndex];
for (int i=0;i<this.variationsAverages.length;i++) {
this.variationsAverages[i]=0.0;
numContributors[i]=0;
}
// Calculate total weights for averages and number of contributors (to remove single-contributor items)
for (int numSPar=0;numSPar<numSeriesPars;numSPar++) {
int avIndex=this.averageCellIndex[numSPar];
if (avIndex>=0){
double w;
if (useSetWeights){
int imgNumber=this.parameterMap[numSPar][0];
int setNumber=this.distortionCalibrationData.gIP[imgNumber].getSetNumber();
w=this.distortionCalibrationData.gIS[setNumber].getSetWeight();
} else {
w=1.0;
}
if (w>0.0) { // do not count zero-contributors (are they possible?)
this.variationsAverages[avIndex]+=w;
numContributors[avIndex]++;
}
}
}
if (this.debugLevel>debugThreshold){
System.out.println("buildVariancesMaps() numContributors:");
for (int i=0;i<numContributors.length;i++) if (numContributors[i]>0) System.out.println("--- "+i+":"+numContributors[i]);
}
// calculate each parameter share of the average TODO: disable if share =100% (single contributor)
int numVariancePars=0;
this.weightOnAverage=new double [numSeriesPars];
this.weightVariance= new double [numSeriesPars];
this.varianceErrorsSquared= new double [numSeriesPars];
for (int numSPar=0;numSPar<numSeriesPars;numSPar++) {
this.weightOnAverage[numSPar]=0.0;
this.weightVariance[numSPar]=0.0;
this.varianceErrorsSquared[numSPar]=Double.NaN;
int avIndex=this.averageCellIndex[numSPar];
if (avIndex>=0){
if (numContributors[avIndex]<2){
this.averageCellIndex[numSPar]=-1; // single element - impossible to use
if (this.debugLevel>0) System.out.println("buildVariancesMaps(): removed parameter #"+numSPar+" - single contributor to average");
} else {
numVariancePars++;
double w;
if (useSetWeights){
int imgNumber=this.parameterMap[numSPar][0];
int setNumber=this.distortionCalibrationData.gIP[imgNumber].getSetNumber();
w=this.distortionCalibrationData.gIS[setNumber].getSetWeight();
} else w=1.0;
this.weightOnAverage[numSPar]=w/this.variationsAverages[avIndex];
this.weightVariance[numSPar]= w;
}
}
}
if (this.debugLevel>debugThreshold){
System.out.println("average indices/shares:");
for (int numSPar=0;numSPar<numSeriesPars;numSPar++) {
int avIndex=this.averageCellIndex[numSPar];
if (avIndex>=0){
int parIndex=this.parameterMap[numSPar][1];
System.out.println("==="+numSPar+" parIndex="+parIndex+" avIndex="+avIndex+
" weightOnAverage="+this.weightOnAverage[numSPar]+
" weightVariance="+this.weightVariance[numSPar]);
}
}
}
if (numVariancePars==0){
this.averageCellIndex=null;
this.variationsAverages=null;
this.weightVariance=null;
this.varianceErrorsSquared=null;
return 0;
}
// TODO this.variationsAverages needs to be reset to all zeros each calculations
return numVariancePars;
}
/**
* Ammend LMA arrays to pull individual values of the extrinsic parameters to their averages
* Averages may be global, per-station or per same tilt motor position (same station)
* The function to be minimized is
* f(x) Scale*(1/p*Xeff+(1-1/p)*pow(Xeff,p)
* Xeff=x/X0*(1-shareInAverage)
* and x is difference between the poarameter and it's average over the specified set (all/station/tiltStation)
* @param numSeries fitting series number
* @param vector - parameters vector
* @param jTByJ Jacobian transposed multiplied by Jacobian - some diagonal elements may be modified (weighted) or null (will add to old values)
* @param jTByDiff Jacobian transposed multiplied by difference vector (weighted) or null (will add to old values)
* @return true if parameter variances are applicable to the fitting series
*/
public boolean addVarianceToLMA(
int numSeries,
final double [] vector,
double [][] jTByJ, // jacobian multiplied by Jacobian transposed
double [] jTByDiff){ // jacobian multiplied difference vector
if (this.averageCellIndex==null) return false; // parameter varainces are not used
// int numTPars=this.parameterMode[numSeries].length;
int numSeriesPars=this.parameterMap.length;
int debugThreshold=2;
// double [] fX= new double [numTPars];
// double [] diagJ=new double [numTPars]; // diagonal of Jacobian (here parameters only influence themselves)
double [] weights=new double [this.variationsAverages.length];
for (int i=0;i<this.variationsAverages.length;i++) {
this.variationsAverages[i]=0.0;
weights[i]=0.0;
}
// calculate appropriate averages
for (int numSPar=0;numSPar<numSeriesPars;numSPar++) {
this.varianceErrorsSquared[numSPar]=0.0;
int avIndex=this.averageCellIndex[numSPar];
if (avIndex>=0){
this.variationsAverages[avIndex]+=this.weightOnAverage[numSPar]*vector[numSPar];
}
}
// now fX and diagJ
int numModded=0;
for (int numSPar=0;numSPar<numSeriesPars;numSPar++) {
int avIndex=this.averageCellIndex[numSPar];
int parIndex=this.parameterMap[numSPar][1];
// if ((avIndex>=0) && (this.distortionCalibrationData.eyesisCameraParameters.isVarianceCostSet(parIndex))) {
if (avIndex>=0) {
double scale=this.distortionCalibrationData.eyesisCameraParameters.varianceCostScale(parIndex);
double x0= this.distortionCalibrationData.eyesisCameraParameters.varianceCostVariationAbs(parIndex);
double exp= this.distortionCalibrationData.eyesisCameraParameters.varianceCostVariationExponent(parIndex);
double xEff=(vector[numSPar]-this.variationsAverages[avIndex])*(1.0-this.weightOnAverage[numSPar])/x0; //OOB-1
double axEff=Math.abs(xEff);
double sxEff=Math.signum(xEff);
double k=1.0/exp;
double fX=sxEff*scale*(k*axEff+(1.0-k)*Math.pow(axEff,exp));
double diagJ=scale*((1.0-this.weightOnAverage[numSPar])/x0)*(k+(exp-1)*Math.pow(axEff,exp-1.0));
this.varianceErrorsSquared[numSPar]=this.weightVariance[numSPar]*fX*fX;
if (jTByJ!=null) jTByJ[numSPar][numSPar]+=this.weightVariance[numSPar]*diagJ*diagJ;
if (jTByDiff!=null) jTByDiff[numSPar]-= this.weightVariance[numSPar]*fX*diagJ;
if (this.debugLevel>debugThreshold){
System.out.print (numSPar+" "+parIndex+" "+avIndex+": "+" scale="+scale);
System.out.print (" vector["+numSPar+"]="+vector[numSPar]+" ("+this.variationsAverages[avIndex]+") xEff="+xEff+" fX="+fX+" k="+k+" exp="+exp );
System.out.print (" diagJ="+diagJ+" "+xEff+" jTByJ+"+ (this.weightVariance[numSPar]*diagJ*diagJ) );
System.out.print (" jTByDiff+"+(-this.weightVariance[numSPar]*fX*diagJ)+" ves="+(this.weightVariance[numSPar]*fX*fX));
System.out.println(" weight="+this.weightVariance[numSPar]);
}
if (this.weightVariance[numSPar]!=0.0) numModded++;
}
}
if (this.debugLevel>1)System.out.println ("addVarianceToLMA() - modified "+numModded+" elements");
return true;
}
public double [] getVarianceError2(){ return (this.averageCellIndex==null)?null:this.varianceErrorsSquared;}
public double [] getWeights(){ return (this.averageCellIndex==null)?null:this.weightVariance;}
/**
*
* @return number of the current fitting strategy series
*/
public int getCurrentSeries(){
return this.currentSeriesNumber;
}
/**
* Calculate vector of the parameters used in LMA algorithm, extracted from the
* individual data, using parameter map (calculated once after changing series)
* @return vector of parameters used for the LMA
*/
public double [] getSeriesVector(){
if (this.parameterMap==null) {
String msg="Series parameters map is not calculated";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
double [] vector=new double[this.parameterMap.length];
for (int i=0;i<vector.length;i++) {
// vector[i]=this.distortionCalibrationData.pars[this.parameterMap[i][0]][this.parameterMap[i][1]];
vector[i]=this.distortionCalibrationData.getParameterValue(this.parameterMap[i][0],this.parameterMap[i][1]); // (numImg, numPar)
}
return vector;
}
/**
* Saves data from the parameter vector to that of the images
* @param vector vector of parameters (after LMA fitting)
*/
// TODO: Update the temporarily disabled images also, when possible (modify buildParameterMap also?
public void saveSeriesVector(double [] vector){
if ((this.parameterMap==null) ||(vector==null) || (vector.length!=this.parameterMap.length) ) {
String msg="Vector length does not match parameters length";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
// save for "individual" and "common" - and "station" (week - same as individual here)
boolean [] selectedEnabledImages=selectedImages(this.currentSeriesNumber);
for (int numImg=0;numImg<this.reverseParameterMap.length;numImg++) if (selectedEnabledImages[numImg]){
for (int nPar=0;nPar<this.reverseParameterMap[numImg].length;nPar++) if (this.reverseParameterMap[numImg][nPar]>=0){
// this.distortionCalibrationData.pars[numImg][nPar]=vector[this.reverseParameterMap[numImg][nPar]];
this.distortionCalibrationData.setParameterValue(numImg,nPar,vector[this.reverseParameterMap[numImg][nPar]],true);
if (this.debugLevel>2){
System.out.println(" Updated image "+numImg+" "+distortionCalibrationData.getParameterName(nPar)+" = "+
// this.distortionCalibrationData.pars[numImg][nPar]) ; //vector[this.reverseParameterMap[numImg][nPar]]);
this.distortionCalibrationData.getParameterValue(numImg,nPar));
}
}
}
// propagate to other (unselected) images for "super common" parameters
for (int vPar=0; vPar<this.parameterMap.length;vPar++) {
if (
(this.parameterMap[vPar][2]==modeSupercommon) ||
(this.parameterMap[vPar][2]==modeSuperStation) ){ // "super common" No "weak" here!
// int nSub=this.parameterMap[vPar][0]; // that's an image number, not a subcamera number
int nSub=this.distortionCalibrationData.gIP[this.parameterMap[vPar][0]].channel;
int nStation=this.distortionCalibrationData.gIP[this.parameterMap[vPar][0]].getStationNumber();
boolean superCommon=(this.parameterMap[vPar][2]==modeSupercommon);
int nPar=this.parameterMap[vPar][1];
//this.distortionCalibrationData.channels[i]
boolean isSubCamera=this.distortionCalibrationData.isSubcameraParameter(nPar);
for (int numImg=0;numImg<this.reverseParameterMap.length;numImg++) {
if (superCommon || (this.distortionCalibrationData.gIP[numImg].getStationNumber()==nStation)) {
if (this.debugLevel>2){
System.out.println("saveSeriesVector(): numImg="+numImg+" nPar="+nPar+" isSubCamera="+isSubCamera+
" nSub="+nSub+" distortionCalibrationData.getImageSubcamera("+numImg+")="+distortionCalibrationData.getImageSubcamera(numImg)+
" vector["+vPar+"]="+vector[vPar]);
}
if ((!isSubCamera) || (nSub==this.distortionCalibrationData.getImageSubcamera(numImg))) {
// this.distortionCalibrationData.pars[numImg][nPar]=vector[vPar];
this.distortionCalibrationData.setParameterValue(numImg,nPar,vector[vPar],true);
}
}
}
}
}
}
/**
* Calculates current values of all parameters for the particular sensor - some ("fixed")
* are taken from the data stored for this individual image, others - from the parameter
* vector (used in fitting) UPDATE: works with null parameterVector
* @param numImg number of image
* @param vector parameters vector
* @return vector used for the current image (parameters influencing the acquired grid
* on the sensor (common parameters and those of the sensor's subchannel)
*/
public double [] getImageParametersVector(int numImg, double [] parameterVector){
// double [] vector = this.distortionCalibrationData.pars[numImg].clone();
double [] vector = this.distortionCalibrationData.getParameters(numImg); // returns a copy, no clone() is needed
if ((parameterVector!=null) && (this.reverseParameterMap!=null) && (this.reverseParameterMap[numImg]!=null)){
for (int i=0;i<vector.length;i++){
if (this.reverseParameterMap[numImg][i]>=0) vector[i]=parameterVector[this.reverseParameterMap[numImg][i]];
}
}
return vector;
}
/**
* Calculates which of all parameters for the particular sensor are to be adjusted (to reduce calcualtions)
* @param numImg number of image
* @param vector parameters vector
* @return mask vector to be used with the results of getImageParametersVector()
*/
public boolean [] getImageParametersVectorMask (int numImg){
if ((this.reverseParameterMap==null) || (this.reverseParameterMap[numImg]==null)) return null;
// boolean [] mask =new boolean [this.distortionCalibrationData.pars[numImg].length];
boolean [] mask =new boolean [this.distortionCalibrationData.getParametersLength(numImg)];
for (int i=0;i<mask.length;i++){
mask[i]=(this.reverseParameterMap[numImg][i]>=0);
}
return mask;
}
/**
* Calculates index in the parameter vector corresponding to each image parameter vector element
* @param numImg number of image
* @param vector parameters vector
* @return mask vector to be used with the results of getImageParametersVector()
*/
public int [] getImageParametersVectorReverseMap (int numImg){
if ((this.reverseParameterMap==null) || (this.reverseParameterMap[numImg]==null)) return null;
// int [] map =new int [this.distortionCalibrationData.pars[numImg].length];
int [] map =new int [this.distortionCalibrationData.getParametersLength(numImg)];
for (int i=0;i<map.length;i++){
map[i]=this.reverseParameterMap[numImg][i];
}
return map;
}
/**
* Opens a text window wityh a table that shows map from each element of the parameters vector
* to the image number used as a source of this parameter
* @param title Window title
*/
public void showCurrentParameterMap(String title){
String header="#\tMode\tName\tSubcamera\tImage Number\tMode";
StringBuffer sb = new StringBuffer();
for (int i=0; i<this.parameterMap.length;i++){
sb.append(
i+"\t"+
this.definedModesAll[this.parameterMap[i][2]]+"\t"+
this.distortionCalibrationData.getParameterName(this.parameterMap[i][1])+"\t"+
this.distortionCalibrationData.getImageSubcamera(this.parameterMap[i][0])+"\t"+
this.parameterMap[i][0]+"\t"+
this.definedModesAll[this.parameterMap[i][2]]+"\n");
}
new TextWindow(title, header, sb.toString(), 800,600);
}
/**
* Opens window with a table mapping each image (column) parameter (row) to parameter vector element
* "-" (-1 in teh table) - fixed parameter, use one from the individual image
* @param title Window title
*/
public void showCurrentReverseParameterMap(String title){
String header="Image";
boolean [] selectedEnabledImages=selectedImages(this.currentSeriesNumber);
for (int i=0; i<this.reverseParameterMap.length;i++) if (selectedEnabledImages[i]){
header+="\t"+i;
}
StringBuffer sb = new StringBuffer();
sb.append("timestmps");
for (int i=0; i<this.reverseParameterMap.length;i++) if (selectedEnabledImages[i]){
sb.append("\t"+IJ.d2s(this.distortionCalibrationData.getImageTimestamp(i),6));
}
sb.append("\n");
sb.append("subcamera");
for (int i=0; i<this.reverseParameterMap.length;i++) if (selectedEnabledImages[i]){
sb.append("\t"+this.distortionCalibrationData.getImageSubcamera(i));
}
sb.append("\n");
for (int k=0;k<this.reverseParameterMap[0].length;k++){
// boolean isSubCamera=this.distortionCalibrationData.isSubcameraParameter(k);
// sb.append(this.distortionCalibrationData.getParameterName(this.parameterMap[k][1])); // name of parameter
sb.append(this.distortionCalibrationData.getParameterName(k)); // name of parameter
for (int i=0; i<this.reverseParameterMap.length;i++) if (selectedEnabledImages[i]){
int mode =this.reverseParameterMap[i][k];
sb.append("\t"+((mode>=0)?mode:"-"));
}
sb.append("\n");
}
new TextWindow(title, header, sb.toString(), 800,600);
}
/**
* Add/reduce number of series in this fitting strategy
* @param numSeries new number of series
*/
public void setLength(int numSeries){
if (numSeries<=0) {
setDflt(0);
return;
}
if ((this.selectedImages!=null) && (numSeries==this.selectedImages.length)) return;
if ((this.selectedImages==null) && (numSeries==0)) return;
boolean [][] oldSelectedImages=null; // images selected for each step
int [][] oldParameterMode=null;
int [] oldVarianceModes=null;
int [][] oldZGroups=null;
int [][][] oldParameterGroups=null;
double [] oldLambdas=null; // LMA initial lambda for each step
int [] oldMasterImages=null;
double [] oldStepDone=null;
boolean [] oldStopAfterThis=null;
int oldNumSeries=(this.selectedImages==null)?0:this.selectedImages.length;
int oldLength=0;
if (this.selectedImages!=null){
// deep clone this.* to old*;
oldSelectedImages=new boolean[oldNumSeries][];
oldParameterMode=new int[oldNumSeries][];
oldParameterGroups=new int[oldNumSeries][][];
oldZGroups=new int[oldNumSeries][];
for (int i=0;i<oldNumSeries;i++){
oldSelectedImages[i]=this.selectedImages[i].clone();
oldParameterMode[i]= this.parameterMode[i].clone(); // out of bound - 2
oldParameterGroups[i]=new int[this.parameterGroups[i].length][];
for (int j=0;j<oldParameterGroups[i].length;j++)
oldParameterGroups[i][j]=(parameterGroups[i][j]==null)?null:parameterGroups[i][j].clone();
if (this.zGroups[i]!=null) oldZGroups[i]=this.zGroups[i].clone();
else this.zGroups[i]=oldZGroups[i];
}
oldVarianceModes=(this.varianceModes==null)?null:this.varianceModes.clone();
oldLambdas=this.lambdas.clone();
oldLength=this.selectedImages.length;
oldMasterImages=this.masterImages.clone();
oldStepDone=this.stepDone.clone();
oldStopAfterThis=this.stopAfterThis.clone();
}
setDflt(numSeries);
if (this.selectedImages!=null) for (int i=0;(i<this.selectedImages.length) && (i<oldLength);i++){
this.selectedImages[i]=oldSelectedImages[i];
this.parameterMode[i]= oldParameterMode[i];
this.parameterGroups[i]=oldParameterGroups[i];
this.lambdas[i]=oldLambdas[i];
this.masterImages[i]=oldMasterImages[i];
this.stepDone[i]=oldStepDone[i];
this.stopAfterThis[i]=oldStopAfterThis[i];
this.varianceModes[i]=oldVarianceModes[i];
this.zGroups[i]=(oldZGroups[i]!=null)?oldZGroups[i].clone():null;
}
}
public void updateNumberOfSubcameras(){
int numPars= this.distortionCalibrationData.getNumParameters();
int numSubCams=this.distortionCalibrationData.getNumSubCameras();
initParameterList();
int numSubPars=0;
int [] subParIndex=new int[numPars];
for (int i=0;i<numPars;i++){
if (this.distortionCalibrationData.isSubcameraParameter(i)) subParIndex[numSubPars++]=i;
}
int totalNumPars=numPars+(numSubCams-1)*numSubPars; // maximal number of parametes per timestamp?
int oldTotalPars=this.parameterEnable.length;
if (oldTotalPars==totalNumPars) return;
if (oldTotalPars>numPars) { // more than one subcamera, so last numSubPars are subcamera parameters
for (int i=0;i<numSubPars;i++)subParIndex[i]=(oldTotalPars-numSubPars)+i;
}
// public boolean isSubcameraParameter(int num){
int numSeries=this.parameterMode.length;
if (oldTotalPars<totalNumPars){ // grow, repeat last subcamera
if (this.debugLevel>1) System.out.println("Increasing total number of parameters in fitting strategy: "+oldTotalPars+" -> "+totalNumPars);
for (int nSer=0;nSer<numSeries;nSer++){
int [] parameterMode_tmp=this.parameterMode[nSer]; //.clone();
int [][] parameterGroups_tmp=this.parameterGroups[nSer]; //.clone();
this.parameterMode[nSer]=new int[totalNumPars];
this.parameterGroups[nSer]=new int[totalNumPars][];
for (int nTPar=0;nTPar<oldTotalPars;nTPar++){
this.parameterMode[nSer][nTPar]=parameterMode_tmp[nTPar];
this.parameterGroups[nSer][nTPar]=parameterGroups_tmp[nTPar];
}
for (int nTPar=oldTotalPars;nTPar<totalNumPars;nTPar++){
int index= subParIndex[(nTPar-oldTotalPars) % numSubPars];
this.parameterMode[nSer][nTPar]=parameterMode_tmp[index];
this.parameterGroups[nSer][nTPar]=(parameterGroups_tmp[index]==null)?null:parameterGroups_tmp[index].clone();
}
}
boolean [] parameterEnable_tmp=this.parameterEnable; //.clone();
this.parameterEnable= new boolean [totalNumPars];
for (int nTPar=0;nTPar<oldTotalPars;nTPar++){
this.parameterEnable[nTPar]=parameterEnable_tmp[nTPar];
}
for (int nTPar=oldTotalPars;nTPar<totalNumPars;nTPar++){
int index= subParIndex[(nTPar-oldTotalPars) % numSubPars];
this.parameterEnable[nTPar]=parameterEnable_tmp[index];
}
} else { // shrink
if (this.debugLevel>1) System.out.println("Reducing total number of parameters in fitting strategy: "+oldTotalPars+" -> "+totalNumPars);
for (int nSer=0;nSer<numSeries;nSer++){
int [] parameterMode_tmp=this.parameterMode[nSer]; //.clone();
int [][] parameterGroups_tmp=this.parameterGroups[nSer]; //.clone();
this.parameterMode[nSer]=new int[totalNumPars];
this.parameterGroups[nSer]=new int[totalNumPars][];
for (int nTPar=0;nTPar<totalNumPars;nTPar++){
this.parameterMode[nSer][nTPar]=parameterMode_tmp[nTPar];
this.parameterGroups[nSer][nTPar]=parameterGroups_tmp[nTPar];
}
}
boolean [] parameterEnable_tmp=this.parameterEnable; //.clone();
this.parameterEnable= new boolean [totalNumPars];
for (int nTPar=0;nTPar<totalNumPars;nTPar++){
this.parameterEnable[nTPar]=parameterEnable_tmp[nTPar];
}
}
}
private void setDflt(int numSeries){
if (numSeries==0) {
this.selectedImages=null;
this.lambdas=null;
this.stepDone=null;
this.parameterMode=null;
this.parameterGroups=null;
this.varianceModes=null;
this.zGroups=null;
return;
}
this.stopAfterThis=new boolean[numSeries];
for (int i=0;i<numSeries;i++) this.stopAfterThis[i]=true;
// calculate total (potential) number of parameters in the system
//TODO: modify for groups
int numPars= this.distortionCalibrationData.getNumParameters();
int numSubCams=this.distortionCalibrationData.getNumSubCameras();
int numSubPars=0;
for (int i=0;i<numPars;i++){
if (this.distortionCalibrationData.isSubcameraParameter(i)) numSubPars++;
}
int totalNumPars=numPars+(numSubCams-1)*numSubPars; // maximal number of parametes per timestamp?
// number of parameters to adjust may be greater, if they were changing between the images
this.selectedImages=new boolean[numSeries][this.distortionCalibrationData.getNumImages()];//
this.selectedValidImages=new boolean[numSeries][this.distortionCalibrationData.getNumImages()];//
this.masterImages=new int[numSeries];
this.lambdas=new double[numSeries];
this.stepDone=new double[numSeries];
this.parameterMode=new int[numSeries][totalNumPars];
this.varianceModes=new int[numSeries];
this.parameterGroups=new int[numSeries][totalNumPars][];
this.parameterEnable= new boolean [totalNumPars];
this.zGroups=new int[numSeries][];
for (int i=0;i<this.selectedImages.length;i++){
invalidateSelectedImages(i);
for (int j=0;j<this.selectedImages[i].length;j++){
this.selectedImages[i][j]=false;
}
for (int j=0;j<this.parameterMode[i].length;j++){
this.parameterMode[i][j]=this.modeFixed; // fixed
this.parameterGroups[i][j]=null; // no groups yet defined
}
this.lambdas[i]=defaultLambda;
this.stepDone[i]=defaultStepDone;
this.masterImages[i]=0; // first image, supposingly the earliest timestamp
this.varianceModes[i]=varianceModeDisabled;
this.zGroups[i]=null;
}
initParameterList();
for (int i=0;i<numPars;i++){
this.parameterEnable[i]=true; // initially enable all parameters for the first camera
}
for (int i=1;i<numSubCams;i++){
int i1=numPars+numSubPars*(i-1);
int j1=0;
for (int j=0;j<numPars;j++) if (this.distortionCalibrationData.isSubcameraParameter(j)){
this.parameterEnable[i1+j1]=false; // initially disable all other subcamera parameters
j1++;
}
}
}
private void initParameterList(){
int numPars= this.distortionCalibrationData.getNumParameters();
int numSubCams=this.distortionCalibrationData.getNumSubCameras();
int numSubPars=0;
for (int i=0;i<numPars;i++){
if (this.distortionCalibrationData.isSubcameraParameter(i)) numSubPars++;
}
int totalNumPars=numPars+(numSubCams-1)*numSubPars; // maximal number of parametes per timestamp?
this.parameterList=new int[totalNumPars][2];
for (int i=0;i<numPars;i++){
this.parameterList[i][0]=0;
this.parameterList[i][1]=i;
// this.parameterEnable[i]=true; // initially enable all parameters for the first camera
}
for (int i=1;i<numSubCams;i++){
int i1=numPars+numSubPars*(i-1);
int j1=0;
for (int j=0;j<numPars;j++) if (this.distortionCalibrationData.isSubcameraParameter(j)){
this.parameterList[i1+j1][0]=i;
this.parameterList[i1+j1][1]=j;
// this.parameterEnable[i1+j1]=false; // initially disable all other subcamera parameters
j1++;
}
}
}
/**
* Find parameter number from subcamera and index
* @param nSub number of subcamera (channel)
* @param index index of parameter
* @return number of parameter that has specified sub-camera and index. -1 if such does not exist
*/
private int getParameterNumber(int nSub, int index){
for (int i=0;i<this.parameterList.length;i++) if ((this.parameterList[i][0]==nSub) && (this.parameterList[i][1]==index)) return i;
return -1;
}
/**
*
* @param numSeries Number of series to edit
* @param useImages Select images for this series
* @param fromToImages - limit number of checkboxes, otherwise window does not show the bottom ones
* @param useParameters Select parameters for this series
* @param askNextSeries Ask for next series number
* @param zeroAndOther use 2 channels 0 and "other", propagete settings for channel 1 to all the rest
* @return -2 - cancel, -1, done, otherwise - number of step to edit
*/
public int selectStrategyStep(
int numSeries,
boolean useImages,
int [] fromToImages,
boolean allImages,
boolean useParameters,
boolean askLambdas,
boolean askNextSeries,
boolean zeroAndOther
){
boolean showDirectMap=false;
boolean showReverseMap=false;
// if current series is not valid (probably just started a new one) - look for the last valid (if any)
// and copy it;
int numEstimated=this.distortionCalibrationData.getNumberOfEstimated(true); //(boolean enabledOnly
int [] numEstimatedPerStation=this.distortionCalibrationData.getNumberOfEstimatedPerStation(true); //(boolean enabledOnly
String sNumEstimatedPerStation="";
for (int i=0;i<numEstimatedPerStation.length;i++){
if (i>0) sNumEstimatedPerStation+=", ";
sNumEstimatedPerStation+=numEstimatedPerStation[i];
}
int numNewEnabled=this.distortionCalibrationData.getNumNewEnabled();
int [] numNewEnabledPerStation=this.distortionCalibrationData.getNumNewEnabledPerStation();
String sNumNewEnabledPerStation="";
for (int i=0;i<numNewEnabledPerStation.length;i++){
if (i>0) sNumNewEnabledPerStation+=", ";
sNumNewEnabledPerStation+=numNewEnabledPerStation[i];
}
if (!isSeriesValid(numSeries)){
int sourceSeries=-1;
for (int i=numSeries-1;i>=0;i--) if (isSeriesValid(i)){
sourceSeries=i;
break;
}
if (sourceSeries>=0){
invalidateSelectedImages(numSeries); // just in case -= will be recalculated
for (int i =0; i<this.distortionCalibrationData.getNumImages();i++){
this.selectedImages[numSeries][i]=this.selectedImages[sourceSeries][i]; // copy for all, not only enabled
}
for (int i =0; i<this.parameterEnable.length;i++) if (this.parameterEnable[i]){
this.parameterMode[numSeries][i]=this.parameterMode[sourceSeries][i];
this.parameterGroups[numSeries][i]=(this.parameterGroups[sourceSeries][i]==null)?null:this.parameterGroups[sourceSeries][i].clone();
}
this.masterImages[numSeries]=this.masterImages[sourceSeries];
this.lambdas[numSeries]=this.lambdas[sourceSeries];
this.stepDone[numSeries]=this.stepDone[sourceSeries];
this.stopAfterThis[numSeries]=this.stopAfterThis[sourceSeries];
this.varianceModes[numSeries]=this.varianceModes[sourceSeries];
this.zGroups[numSeries]=(this.zGroups[sourceSeries]!=null)?this.zGroups[sourceSeries].clone():null;
}
}
GenericDialog gd = new GenericDialog("Fitting Strategy Step Configuration, step "+numSeries+" number of enabled images="+this.distortionCalibrationData.getNumEnabled());
gd.addCheckbox("Copy all from previous series (ignore all other fields)", false);
gd.addCheckbox("Remove all (but first) images, reopen dialog", false); // remove all will be invalid, copied from the previous
gd.addCheckbox("Select all images, reopen dialog", false);
if (numEstimated>0){
gd.addMessage("There are "+numEstimated+" ("+sNumEstimatedPerStation+") enabled images that have estimated orientation");
gd.addCheckbox("Select them and only them (and re-open dialog)", false);
} else {
gd.addMessage("There are no enabled images with estimated (from neighbors) orientation");
}
if (numNewEnabled>0){
gd.addMessage("There are "+numNewEnabled+" ("+sNumNewEnabledPerStation+" new enabled images");
gd.addCheckbox("Select them and only them (and re-open dialog)", false);
} else {
gd.addMessage("There are no new enabled images");
}
int numStations=this.distortionCalibrationData.eyesisCameraParameters.getNumStations();
boolean [] constrainByStation=new boolean[numStations];
for (int i=0;i<constrainByStation.length;i++) constrainByStation[i]=true;
if (this.distortionCalibrationData.eyesisCameraParameters.numStations>1){
gd.addMessage("Constrain by stations");
// gd.addCheckbox("Remove images of unselected stations below", true);
for (int i=0;i<this.distortionCalibrationData.eyesisCameraParameters.numStations;i++) gd.addCheckbox("Station "+i, constrainByStation[i]);
}
if (useImages) {
gd.addNumericField("Image sepection range, from", fromToImages[0], 0);
gd.addNumericField("Image sepection range, up to (inclufing)", fromToImages[1], 0);
gd.addMessage("Select files to include");
for (int i =0; i<this.distortionCalibrationData.getNumImages();i++)
if ((allImages || this.distortionCalibrationData.gIP[i].enabled) && (i>=fromToImages[0]) && (i<=fromToImages[1])){
int hm=this.distortionCalibrationData.gIP[i].hintedMatch;
gd.addCheckbox (i+" - "+(this.distortionCalibrationData.gIP[i].enabled?"":"(disabled) ")+
IJ.d2s(this.distortionCalibrationData.gIP[i].timestamp,6)+
": "+this.distortionCalibrationData.gIP[i].channel+
" matched "+this.distortionCalibrationData.gIP[i].matchedPointers+" pointers"+
", hinted state: "+((hm<0)?"undefined":((hm==0)?"failed":((hm==1)?"orientation":"orientation and translation"))),
this.selectedImages[numSeries][i]);
}
if (allImages) gd.addCheckbox("Enable selected, disable deselected images", false);
gd.addNumericField("The 'master' (used for common parameters)", this.masterImages[numSeries], 0);
}
if (useParameters) {
gd.addMessage("Select parameters to fit");
for (int i =0; i<this.parameterEnable.length;i++) if (this.parameterEnable[i] &&
(!zeroAndOther || (this.parameterList[i][0] <=1) || (this.parameterList[i][0] ==24))){ // in "zeroAndOther" mode do not show other subcameras
int parIndex=this.parameterList[i][1];
int subCam=this.parameterList[i][0];
boolean isSub=this.distortionCalibrationData.isSubcameraParameter(parIndex);
boolean defined=false;
double min=0.0,max=0.0;
for (int imgNumber=0;imgNumber<this.distortionCalibrationData.getNumImages(); imgNumber++)
if (this.selectedImages[numSeries][imgNumber] && this.distortionCalibrationData.gIP[imgNumber].enabled){
int sub=this.distortionCalibrationData.gIP[imgNumber].channel;
if (!isSub || (sub==subCam) || // global or same subcamera
(zeroAndOther && (subCam>=1) && (subCam<24) && (sub>=1) && (sub<24)) || // both head "other"
(zeroAndOther && (subCam>=24) && (sub>=24) )
) { // both subcameras are "other" subcameras
double parValue=this.distortionCalibrationData.getParameterValue(imgNumber,parIndex);
if (!defined) {
// min=this.distortionCalibrationData.pars[imgNumber][parIndex];
min=parValue;
max=min;
defined=true;
}
// if (this.distortionCalibrationData.pars[imgNumber][parIndex]<min) min=this.distortionCalibrationData.pars[imgNumber][parIndex];
// if (this.distortionCalibrationData.pars[imgNumber][parIndex]>max) max=this.distortionCalibrationData.pars[imgNumber][parIndex];
if (parValue<min) min=parValue;
if (parValue>max) max=parValue;
}
}
// System.out.println(i+": "+parIndex+":"+subCam+"defined="+defined+" min="+min+" max="+max);
// undefined, min, max
String sValue=(defined)?((min==max)?(min+""):(min+"..."+max)):"undefined";
String sChn=(zeroAndOther && (subCam>=1)&& (subCam<24))?"-head-other":
((zeroAndOther && (subCam>=24))?"-bottom":("-"+subCam));
boolean noWeak=!this.distortionCalibrationData.eyesisCameraParameters.isExtrinsic(parIndex);
boolean isTilt=this.distortionCalibrationData.eyesisCameraParameters.isTilt(parIndex);
gd.addChoice( // ArrayIndexOutOfBoundsException: 9
this.distortionCalibrationData.getParameterName(parIndex)+
" ("+sValue+" "+
this.distortionCalibrationData.getParameterUnits(parIndex)+")"+
(this.distortionCalibrationData.isSubcameraParameter(parIndex)?(" sub"+sChn):"com "),
(isTilt?this.definedModesTiltEq:(noWeak?this.definedModesNoWeak:this.definedModes)),
this.definedModesAll[this.parameterMode[numSeries][i]]); // definedModesAll - includes all others
}
}
if (askLambdas) {
gd.addNumericField("Initial lambda for the L-M algorithm", this.lambdas[numSeries], 6,8,"");
gd.addStringField("Relative decrese in error to error ratio to consider series finished", ""+this.stepDone[numSeries], 8);
gd.addCheckbox("Stop after this series", this.stopAfterThis[numSeries]);
}
if (this.varianceModes!=null) gd.addChoice(
"Processing of selected parameters variances",
this.definedVarianceModes,
this.definedVarianceModes[this.varianceModes[numSeries]]);
gd.addCheckbox("Edit variances costs", false);
if (numStations>1){
int oldZGroupsLength=(this.zGroups[numSeries]!=null)?this.zGroups[numSeries].length:0;
int [] oldZGroups={};
if (oldZGroupsLength>0) oldZGroups=this.zGroups[numSeries].clone();
this.zGroups[numSeries]=new int [numStations];
int nextZGroup=-1;
for (int i=0;i<numStations;i++){
if (i<oldZGroupsLength) {
this.zGroups[numSeries][i]=oldZGroups[i];
if (this.zGroups[numSeries][i]>nextZGroup) nextZGroup=this.zGroups[numSeries][i];
} else {
this.zGroups[numSeries][i]=++nextZGroup;
}
}
String [] zGroupsChoices=new String [numStations+1];
zGroupsChoices[0]="Not used";
for (int i=0;i<numStations;i++) zGroupsChoices[i+1]="Group "+i;
gd.addMessage ("Select groups of same pattern for different stations (pattern did not move between measurements). Used for pattern correction command");
for (int i=0;i<numStations;i++){
int zG=(this.zGroups[numSeries][i]<0)?0:(this.zGroups[numSeries][i]+1);
gd.addChoice( // ArrayIndexOutOfBoundsException: 9
"Same target group for station " +i,
zGroupsChoices,
zGroupsChoices[zG]); // definedModesAll - includes all others
}
} else {
this.zGroups[numSeries]=new int [1];
this.zGroups[numSeries][0]=0;
}
if (askNextSeries) {
gd.addCheckbox("Rebuild/Show parameter Map", showDirectMap);
gd.addCheckbox("Rebuild/Show reverse parameter Map", showReverseMap);
gd.addNumericField("Next series to edit (<0 - done)", numSeries+1, 0);
}
if (askNextSeries) gd.enableYesNoCancel("OK", "Done");
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return -2;
boolean copyFromPrevious=gd.getNextBoolean();
boolean removeAllImages=gd.getNextBoolean();
boolean selectAllImages=gd.getNextBoolean();
boolean selectEstimated=false;
if (numEstimated>0) selectEstimated=gd.getNextBoolean();
boolean selectNewEnabled=false;
if (numNewEnabled>0) selectNewEnabled=gd.getNextBoolean();
if (selectNewEnabled) {
this.selectedImages[numSeries]=this.distortionCalibrationData.selectNewEnabled();
return numSeries; // caller will repeat with the same series
}
if (this.distortionCalibrationData.eyesisCameraParameters.numStations>1){
// boolean removeUnselectedStations=gd.getNextBoolean();
for (int i=0;i<constrainByStation.length; i++) constrainByStation[i]=gd.getNextBoolean();
}
if (selectEstimated) {
this.selectedImages[numSeries]=this.distortionCalibrationData.selectEstimated(true); //(boolean enabledOnly
for (int i =0; i<this.distortionCalibrationData.getNumImages();i++){
this.selectedImages[numSeries][i]&=constrainByStation[this.distortionCalibrationData.gIP[i].getStationNumber()];
}
return numSeries; // caller will repeat with the same series
}
if (copyFromPrevious || removeAllImages || selectAllImages) {
for (int i =0; i<this.distortionCalibrationData.getNumImages();i++){
// this.selectedImages[numSeries][i]=false; // invalidate - all, regardless of .enabled
this.selectedImages[numSeries][i]=selectAllImages || ((i==0) && removeAllImages); // invalidate - all, regardless of .enabled
this.selectedImages[numSeries][i]&=constrainByStation[this.distortionCalibrationData.gIP[i].getStationNumber()];
}
return numSeries; // caller will repeat with the same series
}
boolean enableDisableSelected=false;
if (useImages) {
fromToImages[0]= (int) gd.getNextNumber();
fromToImages[1]= (int) gd.getNextNumber();
for (int i =0; i<this.distortionCalibrationData.getNumImages();i++)
if ((allImages || this.distortionCalibrationData.gIP[i].enabled) && (i>=fromToImages[0]) && (i<=fromToImages[1])){
this.selectedImages[numSeries][i]=gd.getNextBoolean();
}
if (allImages) enableDisableSelected=gd.getNextBoolean();
this.masterImages[numSeries]=(int) gd.getNextNumber();
if (this.masterImages[numSeries]<0)this.masterImages[numSeries]=0;
if (this.masterImages[numSeries]>=this.selectedImages[numSeries].length)this.masterImages[numSeries]=this.selectedImages[numSeries].length;
}
if (useParameters) {
int [] lastGroups=null;
for (int i =0; i<this.parameterEnable.length;i++) if (this.parameterEnable[i] &&
(!zeroAndOther || (this.parameterList[i][0] <=1) || (this.parameterList[i][0]==24))){ // in "zeroAndOther" mode do not show other subcameras
// for (int i =0; i<this.parameterEnable.length;i++) if (this.parameterEnable[i]){
this.parameterMode[numSeries][i]=gd.getNextChoiceIndex();
if (this.parameterMode[numSeries][i]==this.modeGroup) {
if (this.parameterGroups[numSeries][i]!=null) lastGroups=this.parameterGroups[numSeries][i]; // default groups
else if (lastGroups!=null) this.parameterGroups[numSeries][i]=lastGroups.clone(); // may be null
selectGroups(numSeries,i);
}
}
if (zeroAndOther){
for (int i =0; i<this.parameterEnable.length;i++) {
if ((this.parameterList[i][0]>1) && (this.parameterList[i][0]!=24)){ // "other" subchannels - copy from subchannel1
int refChannel=(this.parameterList[i][0]<24)?1:24;
int iSub1=getParameterNumber(refChannel, this.parameterList[i][1]);
if (this.parameterEnable[iSub1]){
// System.out.println( "parameter number="+i+" this.parameterList[i][0]="+this.parameterList[i][0]+" this.parameterList[i][1]="+this.parameterList[i][1]+" iSub1="+iSub1);
this.parameterMode[numSeries][i]=this.parameterMode[numSeries][iSub1];
if (this.parameterMode[numSeries][i]==this.modeGroup) { // copy groups from channel 1
if (this.parameterGroups[numSeries][i]!=null) this.parameterGroups[numSeries][i]=this.parameterGroups[numSeries][iSub1].clone(); // may be null
else this.parameterGroups[numSeries][i]=null;
}
}
}
}
}
}
if (askLambdas) {
this.lambdas[numSeries]=gd.getNextNumber();
this.stepDone[numSeries]=Double.parseDouble(gd.getNextString());
this.stopAfterThis[numSeries]=gd.getNextBoolean();
}
if (enableDisableSelected) {
this.distortionCalibrationData.enableSelected(this.selectedImages[numSeries]);
}
if (this.varianceModes!=null) this.varianceModes[numSeries]=gd.getNextChoiceIndex();
boolean editVariancesCosts=gd.getNextBoolean();
if (editVariancesCosts){
for (int i =0; i<this.parameterList.length;i++) {
int parIndex=this.parameterList[i][1];
if ((this.parameterMode[numSeries][i]==modeWeakCommon) ||
(this.parameterMode[numSeries][i]==modeWeakStation) ||
(this.parameterMode[numSeries][i]==modeTiltEqualize)
){
if (!this.distortionCalibrationData.eyesisCameraParameters.isExtrinsic(parIndex)){
System.out.println("BUG: this.parameterMode["+numSeries+"]["+i+"]="+this.parameterMode[numSeries][i]+
", but this parameter ("+this.distortionCalibrationData.getParameterName(parIndex)+" is not valid for variances");
continue;
}
this.distortionCalibrationData.eyesisCameraParameters.editCostProperties(
parIndex,
this.distortionCalibrationData.getParameterName(parIndex),
this.distortionCalibrationData.getParameterDescription(parIndex),
this.distortionCalibrationData.getParameterUnits(parIndex));
}
}
}
if (numStations>1){
for (int i=0;i<numStations;i++){
this.zGroups[numSeries][i]=gd.getNextChoiceIndex()-1;
}
}
if (!gd.wasOKed()) return -1; // pressed Done (no need to ask for the next number)
if (askNextSeries) {
showDirectMap=gd.getNextBoolean();
showReverseMap=gd.getNextBoolean();
if (showDirectMap || showReverseMap){
buildParameterMap(numSeries);
if (showDirectMap) showCurrentParameterMap ("Parameter map");
if (showReverseMap) showCurrentReverseParameterMap("Reverse parameter map");
}
int nextSeries= (int) gd.getNextNumber();
if (nextSeries<-1) nextSeries=-1;
return nextSeries;
}
return -1;
}
private boolean selectGroups(
int numSeries,
int numPar){
// if (this.debugLevel>1){
// System.out.println("selectGroups("+numSeries+", "+numPar+")");
// }
int parIndex=this.parameterList[numPar][1];
int subCam=this.parameterList[numPar][0];
String name=this.distortionCalibrationData.getParameterName(parIndex)+
(this.distortionCalibrationData.isSubcameraParameter(parIndex)?(" s"+subCam):"com ");
GenericDialog gd = new GenericDialog("Select image groups for "+name);
gd.addMessage("Select which images share the same value of "+name);
if (this.parameterGroups[numSeries][numPar]==null) {
this.parameterGroups[numSeries][numPar]=new int [this.distortionCalibrationData.getNumImages()];
for (int i=0;i<this.parameterGroups[numSeries][numPar].length;i++)this.parameterGroups[numSeries][numPar][i]=0;
}
String [] choices=organizeGroups(this.parameterGroups[numSeries][numPar],false); // preserve group numbers
for (int i =0; i<this.distortionCalibrationData.getNumImages();i++) if (this.selectedImages[numSeries][i]){
gd.addChoice (i+" - "+IJ.d2s(this.distortionCalibrationData.gIP[i].timestamp,6)+
": "+this.distortionCalibrationData.gIP[i].channel,
choices,
choices[this.parameterGroups[numSeries][numPar][i]]
);
}
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
for (int i =0; i<this.distortionCalibrationData.getNumImages();i++) if (this.selectedImages[numSeries][i]){
this.parameterGroups[numSeries][numPar][i]=gd.getNextChoiceIndex();
}
return true;
}
/**
* Organizes list of groups and creates a list of selection choices. If all members fit in the range
* of 0 (length-1) and (force==false), group numbers are preserved, otherwise they are renumbered
* @param groups array of integers - group numbers
* @param force force renumbering groups
* @return list of selection choices
*/
private String [] organizeGroups(int []groups, boolean force) {
if ((groups==null) || (groups.length==0)){
String msg="Cannot organize mull or empty group";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
// See if 0.. length-1 groups is not enough to represent all numbers used
for (int i=0;!force && (i<groups.length);i++) if ((groups[i]<0) || (groups[i]>=(groups.length-1))) force = true;
if (force){
int [] tmp=groups.clone();
for (int i=0;i<groups.length;i++) groups[i]=-1;
int groupNumber=0;
int max=tmp[0]; for (int i=0;i<tmp.length;i++) if (max<tmp[i]) max=tmp[i];
for (boolean organized=false; !organized;){
int min=max+1;
for (int i=0;i<tmp.length;i++) if ((groups[i]<0) && (min>tmp[i])) min=tmp[i];
if (min>max) organized=true;
else {
for (int i=0;i<tmp.length;i++) if ((groups[i]<0) && (min == tmp[i])) {
groups[i]=groupNumber;
}
groupNumber++;
}
}
}
String [] rslt= new String [groups.length];
for (int i=0;i<rslt.length;i++) rslt[i]="Group "+(i+1);
return rslt;
}
public boolean selectStrategy(int startSerNumber){
int defaultLength=20;
boolean selectImages= false;
boolean allImages= false;
boolean selectParameters=true;
boolean askNextSeries= true;
boolean askLambdas= true;
boolean askParameterMask=false;
boolean zeroAndOther= true;
int [] fromToImages={0,500};
int numSeries=startSerNumber;
int oldLength=(this.selectedImages==null)?0:this.selectedImages.length;
GenericDialog gd = new GenericDialog("Fitting Strategy Step Configuration");
if (oldLength<=0) gd.addNumericField("Number of series in this strategy", defaultLength, 0);
gd.addNumericField("Number of series to edit (<0 - none)", numSeries, 0);
// gd.addNumericField("Number of series in this strategy", (oldLength>0)?oldLength:1, 0); //
gd.addCheckbox ("Select images",selectImages);
gd.addNumericField("Show image checkboxes from", fromToImages[0], 0);
gd.addNumericField("Show image checkboxes up to (inclufing)", fromToImages[1], 0);
gd.addCheckbox ("Select from all images (false - only enabled)",allImages);
gd.addCheckbox ("Select parameters",selectParameters);
gd.addCheckbox ("Ask for initial lambda",askLambdas);
gd.addCheckbox ("Ask for parameter mask",askParameterMask);
gd.addCheckbox ("Use only channel 0 and \"all other channels\"",zeroAndOther);
gd.addCheckbox ("Ask for next series",askNextSeries);
if (oldLength>0) gd.addNumericField("Increase number of series in this strategy", oldLength, 0);
gd.enableYesNoCancel("OK", "Done");
gd.showDialog();
if (gd.wasCanceled()) return false;
int numberOfSeries=0;
if (oldLength<=0) numberOfSeries= (int) gd.getNextNumber();
numSeries= (int) gd.getNextNumber();
selectImages= gd.getNextBoolean();
fromToImages[0]= (int) gd.getNextNumber();
fromToImages[1]= (int) gd.getNextNumber();
allImages= gd.getNextBoolean();
selectParameters= gd.getNextBoolean();
askLambdas= gd.getNextBoolean();
askParameterMask= gd.getNextBoolean();
zeroAndOther= gd.getNextBoolean();
askNextSeries= gd.getNextBoolean();
if (oldLength>0) numberOfSeries= (int) gd.getNextNumber();
if (numberOfSeries!=oldLength) setLength(numberOfSeries);
if (!gd.wasOKed()) return true;
if (askParameterMask) setParameterSelectionMask(zeroAndOther);
while ((numSeries>=0) && (numSeries<this.selectedImages.length)){
numSeries=selectStrategyStep(
numSeries,
selectImages,
fromToImages,
allImages,
selectParameters,
askLambdas,
askNextSeries,
zeroAndOther);
}
return true;
}
public boolean setParameterSelectionMask(boolean zeroAndOther){
GenericDialog gd = new GenericDialog("Set Parameter Selection Mask");
gd.addMessage("Common parameters and sub-camera 0 parameters");
int subCam=0;
boolean showParameter=true;
for (int i=0;i<this.parameterList.length;i++){
if (this.parameterList[i][0]!=subCam){
subCam=this.parameterList[i][0];
if (zeroAndOther) {
showParameter=true;
if (subCam==1) gd.addMessage("Other sub-cameras parameters");
else if (subCam==24) gd.addMessage("Bottom sub-cameras parameters");
// else break;
else {
showParameter=false;
// continue;
}
} else {
gd.addMessage("Sub-camera "+subCam+" parameters");
}
}
if (showParameter) gd.addCheckbox (this.distortionCalibrationData.getParameterName(parameterList[i][1]),this.parameterEnable[i]);
}
WindowTools.addScrollBars(gd);
// gd.setBackground(Color.white);
gd.showDialog();
if (gd.wasCanceled()) return false;
subCam=0;
showParameter=true;
//May add disablong all other subcameras, but try keeping it for later running with zeroAndOther==false
for (int i=0;i<this.parameterList.length;i++){
if (this.parameterList[i][0]!=subCam){
subCam=this.parameterList[i][0];
showParameter=true;
// if (subCam>1) break;
if ((subCam>1) && (subCam!=24)) showParameter=false;
}
if (showParameter) this.parameterEnable[i]=gd.getNextBoolean();
}
return true;
}
//this.currentSeriesNumber
public double getLambda(){
return getLambda(this.currentSeriesNumber);
}
public double getLambda(int numSeries){
return this.lambdas[numSeries];
}
public double getStepDone(){
return getStepDone(this.currentSeriesNumber);
}
public double getStepDone(int numSeries){
return this.stepDone[numSeries];
}
}
......@@ -47,16 +47,16 @@ horizontal axis:
public CalibrationHardwareInterface.CamerasInterface cameras = null;
// public CalibrationHardwareInterface.LaserPointers lasers = null;
// public static CalibrationHardwareInterface.FocusingMotors motorsS=null;
// public Distortions.DistortionProcessConfiguration
// public DistortionProcessConfiguration
// distortionProcessConfiguration=null;
// public LensAdjustment.FocusMeasurementParameters focusMeasurementParameters = null;
// public Distortions.PatternParameters patternParameters=null;
// public Distortions.LensDistortionParameters
// public PatternParameters patternParameters=null;
// public LensDistortionParameters
// lensDistortionParameters=null;
// public MatchSimulatedPattern.DistortionParameters distortion = null;
public MatchSimulatedPattern.DistortionParameters distortionParametersDefault=null;
public Distortions.EyesisCameraParameters eyesisCameraParameters = null;
public EyesisCameraParameters eyesisCameraParameters = null;
public MatchSimulatedPattern[] matchSimulatedPatterns = null; // =new
// MatchSimulatedPattern();
......@@ -64,7 +64,7 @@ horizontal axis:
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters=null;
public SimulationPattern.SimulParameters simulParametersDefault=null;
public Goniometer.GoniometerParameters goniometerParameters = null;
public Distortions.DistortionProcessConfiguration distortionProcessConfiguration=null;
public DistortionProcessConfiguration distortionProcessConfiguration=null;
public int lastScanStep=-1;
public int debugLevel = 2;
public double bottomRollerTilt=60.0; // decrease scan step if tilt is above this
......@@ -75,11 +75,11 @@ horizontal axis:
MatchSimulatedPattern.DistortionParameters distortionParametersDefault,
// MatchSimulatedPattern.DistortionParameters distortion,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
Distortions.EyesisCameraParameters eyesisCameraParameters,
EyesisCameraParameters eyesisCameraParameters,
MatchSimulatedPattern.LaserPointer laserPointers,
SimulationPattern.SimulParameters simulParametersDefault,
Goniometer.GoniometerParameters goniometerParameters,
Distortions.DistortionProcessConfiguration distortionProcessConfiguration
DistortionProcessConfiguration distortionProcessConfiguration
) {
this.cameras = cameras;
this.distortionParametersDefault = distortionParametersDefault;
......@@ -519,8 +519,8 @@ horizontal axis:
public boolean testHintedTarget (
ImagePlus[] images,
Distortions lensDistortions, // should not be null
Distortions.DistortionCalibrationData distortionCalibrationData,
Distortions.PatternParameters patternParameters, // should not be null
DistortionCalibrationData distortionCalibrationData,
PatternParameters patternParameters, // should not be null
boolean equalizeGreens,
int threadsMax,
boolean updateStatus,
......@@ -677,7 +677,7 @@ horizontal axis:
*
* this.parameterMode[numSeries][i]=gd.getNextChoiceIndex();
Distortions.PatternParameters patternParameters, // should not be null
PatternParameters patternParameters, // should not be null
boolean equalizeGreens,
int threadsMax,
boolean updateStatus,
......@@ -724,8 +724,8 @@ horizontal axis:
// MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
// MatchSimulatedPattern.LaserPointer laserPointer, // null OK
// SimulationPattern.SimulParameters simulParametersDefault,
Distortions.DistortionCalibrationData distortionCalibrationData,
Distortions.PatternParameters patternParameters, // should not be null
DistortionCalibrationData distortionCalibrationData,
PatternParameters patternParameters, // should not be null
Distortions lensDistortions, // should not be null
boolean equalizeGreens,
int threadsMax,
......@@ -888,8 +888,8 @@ horizontal axis:
}
}
/*
* Distortions.DistortionCalibrationData distortionCalibrationData= new
* Distortions.DistortionCalibrationData( imp_calibrated, //ImagePlus []
* DistortionCalibrationData distortionCalibrationData= new
* DistortionCalibrationData( imp_calibrated, //ImagePlus []
* images, // images in the memory patternParameters,
* //PatternParameters patternParameters, eyesisCameraParameters
* //EyesisCameraParameters eyesisCameraParameters );
......@@ -914,7 +914,7 @@ horizontal axis:
// fitting strategy
// distortionCalibrationData.pathName=this.goniometerParameters.initialCalibrationFile;
lensDistortions.debugLevel = this.debugLevel;
lensDistortions.fittingStrategy = new Distortions.FittingStrategy(true,
lensDistortions.fittingStrategy = new FittingStrategy(true,
this.goniometerParameters.strategyFile,
distortionCalibrationData); // will use list of grid files
if (lensDistortions.fittingStrategy.pathName == null) { // failed to select/open the file
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
**
** PatternParameters.java
**
** Copyright (C) 2011-2014 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** PatternParameters.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.gui.GenericDialog;
import ij.io.FileSaver;
import ij.io.Opener;
import java.awt.Rectangle;
import java.util.Properties;
/* gridGeometry:
* [v][u][0] - x(mm) of the node(u,v), right (looking to the wall) - positive
* [v][u][1] - y(mm) of the node(u,v), down - positive
* [v][u][2] - z(mm) of the node(u,v), away (into the wall) - positive
* [v][u][3] - mask 0.0 - outside of the pattern rectangle, 1.0 - on the pattern
* RGB moved to Photometric
* [v][u][4] - R-intensity (normalized to 1.0 full scale)
* [v][u][5] - G-intensity
* [v][u][6] - B-intensity
* ... repeat 3,4,5,6 for different views of the pattern (from different points)
*/
public class PatternParameters {
public double patternWidth; // pattern full width in mm
public double patternHeight; // pattern full height in mm
public double patternHalfPeriod; // distance between opposite sign nodes
public double patternTilt; // pattern tilt (degrees) - U clockwise from X-right (V clockwise from Y-down)
public int [] viewMap=null; // should have
public int numStations=1;
public int numberOfViews=1;
public double [][][] gridGeometry=null; // [v][u]{x,y,z,{"alpha", R-intensity, G--intensity, B--intensity} alpha=0 - no ghrid, 1 - grid}
public double [][][] stationZCorr=null; // [v][u]{station0... stationN} - per-station addition to the gridGeometry[][][2]
public double [] averageRGB={1.0,1.0,1.0};
public int numGeometricChannels=4; // x,y,z,mask
public int numPhotometricChannels=4; // r,g,b,a
public int defaultNumberOfChannels=26;
// public int numLayers=7; // number of layers in gridGeometry
public int U0=0; //39
public int V0=0; //36
public int debugLevel=2;
public boolean updateStatus=true;
public String pathName=null; // path from which the grid was read/ where it was last saved to
public double [][][][] photometricByView=null; // [numStation][numView]{a,r,g,b}[pixel]
// public double [][][] photometricBySensor=null;
public double [] patternErrors=null; // weighted RMS error for each pattern node, calculated
public double [] patternErrorMask=null; // weighted RMS error for each pattern node, calculated
public double [] patternErrorMaskSaved=null; // weighted RMS error for each pattern node, calculated
public void initStationZCorr(){
this.stationZCorr=new double [this.gridGeometry.length][this.gridGeometry[0].length][this.numStations];
for (int v=0;v<this.stationZCorr.length;v++) for (int u=0;u<this.stationZCorr[0].length;u++) for (int s=0;s<this.stationZCorr[0][0].length;s++){
this.stationZCorr[v][u][s]=0.0;
}
}
public void resetStationZCorr(){
this.stationZCorr=null;
}
public Rectangle getUVDimensions(){
return new Rectangle(U0,V0,gridGeometry[0].length,gridGeometry.length);
}
public void setPatternErrors(double [] patternErrors){
this.patternErrors=patternErrors;
}
public double [] getPatternErrors(){
return this.patternErrors;
}
public double [] getPatternErrorMask(){
return this.patternErrorMask;
}
public double [] calculatePatternErrorMask(double maxRMS, double minRMS){
double [] mask=new double [this.patternErrors.length]; // null pointer
double a=1.0/(maxRMS-minRMS);
boolean binary=maxRMS==minRMS;
for (int i=0;i<this.patternErrors.length;i++){
if (Double.isNaN(this.patternErrors[i])) mask[i]=0.0;
else {
if (binary) mask[i]=(this.patternErrors[i]>=maxRMS)?0.0:1.0;
else {
double x= a*(this.patternErrors[i]-minRMS);
if (x<=0) mask[i]=1.0;
else if (x>=1.0) mask[i]=0.0;
else mask[i]=1.0+2*x*x*x-3*x*x;
}
}
}
this.patternErrorMask=mask;
return mask;
}
public double [] expandPatternErrorMask(){
Rectangle dimensions=getUVDimensions();
int [] dirs={1,dimensions.width+1,dimensions.width,dimensions.width-1,-1,-dimensions.width-1,-dimensions.width,dimensions.width+1};
double [] mask=this.patternErrorMask.clone();
for (int v=1;v<(dimensions.height-1);v++) for (int u=1;u<(dimensions.width-1);u++){
int index=v*dimensions.width+u;
double min=this.patternErrorMask[index];
for (int iDir=0;iDir<dirs.length;iDir++){
if (this.patternErrorMask[index+dirs[iDir]]<min) min=this.patternErrorMask[index+dirs[iDir]];
}
mask[index]=min;
}
this.patternErrorMask=mask;
return this.patternErrorMask;
}
//patternErrorMaskSaved
public void resetPatternErrorMask(){
this.patternErrorMask=null;
}
public void savePatternErrorMask(){
if (this.patternErrorMask!=null) this.patternErrorMaskSaved=this.patternErrorMask.clone();
else this.patternErrorMaskSaved=null;
}
public void restorePatternErrorMask(){
if (this.patternErrorMaskSaved!=null) this.patternErrorMask=this.patternErrorMaskSaved.clone();
else this.patternErrorMask=null;
}
public double [] getSavedPatternErrorMask(){
return this.patternErrorMaskSaved;
}
public PatternParameters(
int [] viewMap,
int numStations,
double patternWidth, // pattern full width in mm
double patternHeight, // pattern full height in mm
double patternHalfPeriod, // distance between opposite sign nodes
double patternTilt // pattern tilt (degrees) - U clockwise from X-right (V clockwise from Y-down)
){
this.numStations=numStations;
this.patternWidth=patternWidth;
this.patternHeight=patternHeight;
this.patternHalfPeriod=patternHalfPeriod;
this.patternTilt=patternTilt;
setPhotometric(viewMap);
calculateGridGeometryAndPhotometric(true);
}
public void updateNumStations(int numStations){
this.numStations=numStations;
if (numStations==this.photometricByView.length) {
return;
}
System.out.println ("Updating pattern number of stations from "+this.photometricByView.length+" to "+numStations);
double [][][][] photometricByViewCopy=this.photometricByView;
this.photometricByView=new double [this.numStations][][][];
for (int i=0;i<this.photometricByView.length;i++){
if (i<photometricByViewCopy.length){
this.photometricByView[i]= photometricByViewCopy[i];
} else { // deep clone last station
int iSource=photometricByViewCopy.length-1;
this.photometricByView[i]=new double [photometricByViewCopy[iSource].length][][];
for (int j=0;j<photometricByViewCopy[iSource].length;j++){
if (photometricByViewCopy[iSource][j]==null) {
this.photometricByView[i][j]=null;
} else {
this.photometricByView[i][j]=new double [photometricByViewCopy[iSource][j].length][];
for (int k=0;k<photometricByViewCopy[iSource][j].length;k++){
if (photometricByViewCopy[iSource][j][k]==null) {
this.photometricByView[i][j][k]=null;
} else {
this.photometricByView[i][j][k]=photometricByViewCopy[iSource][j][k].clone();
}
}
}
}
}
}
}
public void setPhotometric(int [] viewMap){
if (viewMap==null){
this.viewMap=null;
} else{
this.viewMap=viewMap.clone();
}
setPhotometric();
}
public void setPhotometric(){
if (this.viewMap==null){
this.viewMap=new int[1];
this.viewMap[0]=0;
}
int maxView=0;
for (int i=0;i<this.viewMap.length;i++) if (this.viewMap[i]>maxView) maxView=this.viewMap[i];
this.numberOfViews=maxView+1;
this.photometricByView=new double [this.numStations][this.numberOfViews][4][];
}
public void initDefaultChannels(int num){
this.viewMap=new int[num];
for (int i=0;i<num;i++) this.viewMap[i]=(i<24)?0:1;
this.numberOfViews=2;
}
public double [][] getPhotometricByView(int stationNumber, int nView){
if (stationNumber>=this.photometricByView.length) stationNumber=this.photometricByView.length-1;
if (nView>=this.photometricByView[stationNumber].length) nView=this.photometricByView[stationNumber].length-1;
return this.photometricByView[stationNumber][nView];
}
public double [][] getPhotometricBySensor(int stationNumber,int nSensor){
if (getNumStations()<=stationNumber) updateNumStations(stationNumber+1);
// if (stationNumber>=this.photometricByView.length) stationNumber=this.photometricByView.length-1;
int isens=nSensor;
if (nSensor>=this.viewMap.length){
System.out.println("nSensor="+nSensor+" this.viewMap.length="+this.viewMap.length+" this.photometricByView.length="+this.photometricByView.length);
nSensor=this.viewMap.length-1;
}
int nView=this.viewMap[nSensor];
if (nView>=this.photometricByView[stationNumber].length){
System.out.println("nSensor was "+isens+", nView="+nView+" this.photometricByView["+stationNumber+"].length="+this.photometricByView[stationNumber].length);
nView=this.photometricByView.length-1;
}
return this.photometricByView[stationNumber][nView];
}
// public int getNumViews(){return this.photometricByView[0].length;}
public int getNumViews(){return this.numberOfViews;}
public int getNumStations(){return this.numStations;}
public void setNumStations(int numStations){this.numStations=numStations;}
public int [] getViewMap(){return this.viewMap;}
public int getNumGeometricChannels(){return this.numGeometricChannels;}
public int getNumPhotometricChannels(){return this.numPhotometricChannels;}
public PatternParameters(
int [] viewMap,
double patternWidth, // pattern full width in mm
double patternHeight, // pattern full height in mm
double patternHalfPeriod, // distance between opposite sign nodes
double patternTilt, // pattern tilt (degrees) - U clockwise from X-right (V clockwise from Y-down)
double [] averageRGB
){
this.patternWidth=patternWidth;
this.patternHeight=patternHeight;
this.patternHalfPeriod=patternHalfPeriod;
this.patternTilt=patternTilt;
this.averageRGB=averageRGB.clone();
setPhotometric(viewMap);
calculateGridGeometryAndPhotometric(true);
}
public PatternParameters clone() {
PatternParameters patternParameters= new PatternParameters(
this.viewMap,
this.patternWidth, // pattern full width in mm
this.patternHeight, // pattern full height in mm
this.patternHalfPeriod, // distance between opposite sign nodes
this.patternTilt, // pattern tilt (degrees) - U clockwise from X-right (V clockwise from Y-down)
this.averageRGB);
patternParameters.debugLevel=this.debugLevel;
patternParameters.updateStatus=this.updateStatus;
patternParameters.pathName=this.pathName;
return patternParameters;
}
public ImagePlus saveGridAsImageStack(String title, String path){
ImagePlus imp=getGridAsImageStack(title);
if (imp==null) return null;
FileSaver fs=new FileSaver(imp);
if (updateStatus) IJ.showStatus("Saving grid "+path);
if (imp.getStackSize()>1)
fs.saveAsTiffStack(path);
else
fs.saveAsTiff(path);
this.pathName=path;
if (this.debugLevel>0) System.out.println("Pattern saved as "+this.pathName);
return imp;
}
public String selectAndSave(boolean smart, String defaultPath){
String [] extensions={".grid-tiff","-grid.tiff"};
CalibrationFileManagement.MultipleExtensionsFileFilter parFilter = new CalibrationFileManagement.MultipleExtensionsFileFilter("",extensions,"Pattern grid *.grid-tiff files");
String pathname=CalibrationFileManagement.selectFile(
smart,
true,
"Save Pattern Grid Geometry",
"Save",
parFilter,
(defaultPath==null)?this.pathName:defaultPath); //String defaultPath
if ((pathname!=null)&& (pathname.length()!=0)) saveGridAsImageStack("Pattern Grid", pathname);
return pathname;
}
public String selectAndRestore(boolean smart, String defaultPath, int numStations){
String [] extensions={".grid-tiff","-grid.tiff"};
CalibrationFileManagement.MultipleExtensionsFileFilter parFilter = new CalibrationFileManagement.MultipleExtensionsFileFilter("",extensions,"Pattern grid *.grid-tiff files");
String pathname=CalibrationFileManagement.selectFile(
smart,
false,
"Restore Pattern Grid Geometry",
"Restore",
parFilter,
(defaultPath==null)?this.pathName:defaultPath); //String defaultPath
if ((pathname==null) || (pathname=="")) return null;
setNumStations(numStations);
setGridFromImageStack(pathname);
return pathname;
}
public void setGridFromImageStack(String path){
Opener opener=new Opener();
ImagePlus imp=opener.openImage("", path);
if (imp==null) {
String msg="Failed to read grid geometry file "+path;
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
(new JP46_Reader_camera(false)).decodeProperiesFromInfo(imp);
setGridFromImageStack(imp);
this.pathName=path;
if (this.debugLevel>0) System.out.println("Opened "+path+" as a stack of the pattern grid geometry");
}
/**
* Loads grid geomnetry (data in mm, X - left, Y - down, Z - into the wall) frome mult-slice
* ImagePlus. Properties should be set or decoded from the info in the tiff file
* @param imp - ImagePlus stack, containg x,y,z,alpha slices
*/
public void setGridFromImageStack(ImagePlus imp){
int indexAlpha=3;
if (imp == null){
String msg="Grid image is null";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
if (imp.getStackSize()<4){
String msg="Expected >=4 slice image with grid geometry";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
if ( (imp.getProperty("U0") == null) ||
(imp.getProperty("V0") == null)){
String msg="Properties \"U0\" and/or \"V0\" do not exist";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
this.U0=Integer.parseInt((String) imp.getProperty("U0"));
this.V0=Integer.parseInt((String) imp.getProperty("V0"));
// Other properties that are needed only during pattern generation:
if (imp.getProperty("patternWidth")!=null) this.patternWidth=Double.parseDouble((String) imp.getProperty("patternWidth"));
if (imp.getProperty("patternHeight")!=null) this.patternHeight=Double.parseDouble((String) imp.getProperty("patternHeight"));
if (imp.getProperty("patternHalfPeriod")!=null) this.patternHalfPeriod=Double.parseDouble((String) imp.getProperty("patternHalfPeriod"));
if (imp.getProperty("patternTilt")!=null) this.patternTilt=Double.parseDouble((String) imp.getProperty("patternTilt"));
if (imp.getProperty("AverageRed")!=null) this.averageRGB[0]=Double.parseDouble((String) imp.getProperty("AverageRed"));
if (imp.getProperty("AverageGreen")!=null) this.averageRGB[1]=Double.parseDouble((String) imp.getProperty("AverageGreen"));
if (imp.getProperty("AverageBlue")!=null) this.averageRGB[2]=Double.parseDouble((String) imp.getProperty("AverageBlue"));
int numZCorr=0;
if (imp.getProperty("numZCorr")!=null) numZCorr=Integer.parseInt((String) imp.getProperty("numZCorr"));
// if (imp.getProperty("numStations")!=null) this.numStations=Integer.parseInt((String) imp.getProperty("numStations"));
int width=imp.getWidth();
int height=imp.getHeight();
ImageStack stack = imp.getStack();
if (stack==null) {
String msg="Expected a image stack with grid geometry";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
float [][] pixels =new float[stack.getSize()][];
for (int i=0;i<pixels.length;i++) pixels[i]= (float[]) stack.getPixels(i+1);
if (this.debugLevel>3){
System.out.println("setGridFromImageStack() width="+width+", height="+height+", pixels[0].length="+pixels[0].length);
}
this.gridGeometry=new double[height][width][getNumGeometricChannels()]; // x,y,z, alpha
boolean geometryMaskOnly=(pixels.length==getNumGeometricChannels());
boolean singleNoAlpha=(pixels.length==7);
int totalNumViews=(geometryMaskOnly || singleNoAlpha)?1:((pixels.length-getNumGeometricChannels()-numZCorr)/getNumPhotometricChannels());
int fileNumStations=totalNumViews/getNumViews(); // keep current number of stations
int length=height*width;
for (int v=0;v<height;v++) for (int u=0;u<width;u++) for (int n=0;n<getNumGeometricChannels();n++){ // x,y,z, alpha
this.gridGeometry[v][u][n]=pixels[n][v*width+u];
}
if (fileNumStations!=getNumStations()){
if (this.debugLevel>0){
System.out.println("File has "+totalNumViews+" photometric slices, expected "+(getNumStations()*getNumViews())+
" ("+getNumStations()+" stations, "+getNumViews()+" views ), skipping loading photometric data");
}
/// TODO: Fix me!
return; //
}
if (numZCorr>0) {
if (numZCorr==getNumStations()) {
if (this.debugLevel>0){
System.out.println("Loading zCorr data: "+getNumStations()+" slices");
}
this.stationZCorr=new double [height][width][numZCorr];
for (int v=0;v<height;v++) for (int u=0;u<width;u++) for (int n=0;n<numZCorr;n++){
this.stationZCorr[v][u][n]=pixels[n+getNumGeometricChannels()][v*width+u];
}
} else {
System.out.println("File has "+numZCorr+" ZCorr slices, current number of stations is "+getNumStations()+
", skipping loading zCorr data (per-station pattern Z-correction from the average Z)");
}
}
if (this.debugLevel>0){
System.out.println("Loading photometric data: "+(getNumStations()*getNumViews())+" slices "+
" ("+getNumStations()+" stations, "+getNumViews()+" vies )");
}
this.photometricByView=new double [this.numStations][this.numberOfViews][getNumPhotometricChannels()][length]; // r,g,b,a
for (int numStation=0;numStation<this.numStations;numStation++) {
int useNumStation=numStation;
if ((useNumStation>0) && (useNumStation>=fileNumStations)) useNumStation=fileNumStations-1;
for (int nView=0;nView<getNumViews();nView++) {
for (int chn=0;chn<getNumPhotometricChannels();chn++){
int pixIndex=numGeometricChannels+numZCorr+(nView + getNumViews()*useNumStation)*getNumPhotometricChannels()+chn;
if ((pixIndex>=pixels.length) && (chn>2)) pixIndex=indexAlpha; // use mask for non-existent alpha
if (pixIndex>=pixels.length) {
for (int i=0;i<length;i++) {
this.photometricByView[useNumStation][nView][chn][i]=(pixels[indexAlpha][i]>0.5)?this.averageRGB[chn]:0.0; // 0<=chn<=2 here OOB =3
}
} else {
for (int i=0;i<length;i++) {
this.photometricByView[useNumStation][nView][chn][i]=pixels[pixIndex][i]; //OOB12
}
}
}
}
}
}
//getNumPhotometricChannels()
public ImagePlus getGridAsImageStack(String title){
if (this.gridGeometry==null){
String msg="Grid geometry does not exist, nothing to convert";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
int width=this.gridGeometry[0].length;
int height=this.gridGeometry.length;
int length=height*width;
int numZCorr=0;
if (this.stationZCorr!=null) {
for (int v=0;(v<height) && (numZCorr==0);v++ ) for (int u=0;u<width;u++) if (this.stationZCorr[v][u]!=null){
numZCorr=this.stationZCorr[v][u].length;
break;
}
}
// float [][]pixels=new float [this.gridGeometry[0][0].length][width*height];
float [][] pixels=new float [getNumGeometricChannels()+numZCorr+getNumViews()*getNumStations()*getNumPhotometricChannels()] [length];
String [] titles=new String[pixels.length];
String [] geometricTitles= {"X","Y","Z","Mask"};
String [] zCorrTitles=new String [numZCorr];
for (int i=0;i<numZCorr;i++) zCorrTitles[i]="dZ"+i;
String [] photometricTitles={"red","green","blue","alpha"};
int index=0;
for (int v=0;v<height;v++) for (int u=0;u<width;u++){
for (int n=0;n<getNumGeometricChannels();n++) { // should be 4==numGeometricChannels
pixels[n][index]= (float) this.gridGeometry[v][u][n];
}
for (int n=0;n<numZCorr;n++) { // should be 4==numGeometricChannels
pixels[n+getNumGeometricChannels()][index]= (this.stationZCorr[v][u]!=null)?((float) this.stationZCorr[v][u][n]):0.0f;
}
index++;
}
for (int n=0;n<getNumGeometricChannels();n++) titles[n]=geometricTitles[n];
for (int numStation=0;numStation<this.numStations;numStation++) {
for (int nView=0;nView<getNumViews();nView++) {
for (int chn=0;chn<getNumPhotometricChannels();chn++){
// int pixIndex=getNumGeometricChannels()+chn*this.getNumPhotometricChannels()();
int pixIndex=getNumGeometricChannels()+numZCorr+(nView + numStation*getNumViews()) *getNumPhotometricChannels()+chn;
for (int i=0;i<length;i++) pixels[pixIndex][i]= (float) this.photometricByView[numStation][nView][chn][i]; //OOB 8 //oob 12
titles[pixIndex]=photometricTitles[chn]+nView;
}
}
}
for (int i=0;i<numZCorr;i++){
titles[getNumGeometricChannels()+i]=zCorrTitles[i];
}
ImagePlus imp=null;
ImageStack stack=new ImageStack(width,height);
for (int n=0;n<pixels.length;n++) stack.addSlice(titles[n], pixels[n]);
imp = new ImagePlus(title, stack);
imp.setProperty("patternWidth", ""+this.patternWidth);
imp.setProperty("patternHeight", ""+this.patternHeight);
imp.setProperty("patternHalfPeriod", ""+this.patternHalfPeriod);
imp.setProperty("patternTilt", ""+this.patternTilt);
imp.setProperty("U0", ""+this.U0);
imp.setProperty("V0", ""+this.V0);
imp.setProperty("AverageRed", ""+this.averageRGB[0]);
imp.setProperty("AverageGreen", ""+this.averageRGB[1]);
imp.setProperty("AverageBlue", ""+this.averageRGB[2]);
if (numZCorr>0) imp.setProperty("numZCorr", ""+numZCorr);
(new JP46_Reader_camera(false)).encodeProperiesToInfo(imp);
imp.getProcessor().resetMinAndMax();
return imp;
}
public void applyGridCorrection(double [][] gridCorr){
applyGridCorrection(gridCorr, 1.0);
}
/**
* Apply X,Y,Z correction to the current grid geometry
* @param gridCorr array [4][width*height] of the corrections to grid geometry (x,y,z,weight).
* Weight is not used, just for information (1.0 - one image file used with full weight)
* @param scale scale correction
*/
public void applyGridCorrection(double [][] gridCorr, double scale){
if (this.gridGeometry==null){
String msg="Grid geometry does not exist, nothing to apply correction to";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
int height=this.gridGeometry.length;
int width=this.gridGeometry[0].length;
if ((gridCorr==null) || (gridCorr.length!=4) || (gridCorr[0].length!=(width*height))){
String msg="Correction is null or does not match pattern grid geometry";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
for (int v=0;v<height;v++) for (int u=0;u<width;u++) if (this.gridGeometry[v][u][3]>0.0){ // only apply to defined grid
int vu=v*width+u;
for (int n=0;n<3;n++) this.gridGeometry[v][u][n]+= scale*gridCorr[n][vu];
}
}
public void applyZGridCorrection(
double [][] gridZCorr3d,
double scale){
int height=this.gridGeometry.length;
int width=this.gridGeometry[0].length;
if ((gridZCorr3d==null) || (gridZCorr3d.length!=this.numStations) || (gridZCorr3d[0].length!=(width*height))){
String msg="Correction is null or does not match pattern grid geometry";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
this.stationZCorr=new double [height][width][this.numStations];
for (int v=0;v<height;v++) for (int u=0;u<width;u++) {
int vu=v*width+u;
for (int s=0;s<this.numStations;s++){
this.stationZCorr[v][u][s]=scale*gridZCorr3d[s][vu];
}
}
}
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"patternWidth",this.patternWidth+"");
properties.setProperty(prefix+"patternHeight",this.patternHeight+"");
properties.setProperty(prefix+"patternHalfPeriod",this.patternHalfPeriod+"");
properties.setProperty(prefix+"patternTilt",this.patternTilt+"");
properties.setProperty(prefix+"averageRGB_0",this.averageRGB[0]+"");
properties.setProperty(prefix+"averageRGB_1",this.averageRGB[1]+"");
properties.setProperty(prefix+"averageRGB_2",this.averageRGB[2]+"");
if (this.viewMap!=null){
properties.setProperty(prefix+"viewMap_length",this.viewMap.length+"");
for (int i=0;i<this.viewMap.length;i++) {
properties.setProperty(prefix+"viewMap_"+i,this.viewMap[i]+"");
}
}
// this.viewMap;
}
public void getProperties(String prefix,Properties properties){
if (properties.getProperty(prefix+"patternWidth")!=null)
this.patternWidth=Double.parseDouble(properties.getProperty(prefix+"patternWidth"));
if (properties.getProperty(prefix+"patternHeight")!=null)
this.patternHeight=Double.parseDouble(properties.getProperty(prefix+"patternHeight"));
if (properties.getProperty(prefix+"patternHalfPeriod")!=null)
this.patternHalfPeriod=Double.parseDouble(properties.getProperty(prefix+"patternHalfPeriod"));
if (properties.getProperty(prefix+"patternTilt")!=null)
this.patternTilt=Double.parseDouble(properties.getProperty(prefix+"patternTilt"));
if (properties.getProperty(prefix+"averageRGB_0")!=null)
this.averageRGB[0]=Double.parseDouble(properties.getProperty(prefix+"averageRGB_0"));
if (properties.getProperty(prefix+"averageRGB_1")!=null)
this.averageRGB[1]=Double.parseDouble(properties.getProperty(prefix+"averageRGB_1"));
if (properties.getProperty(prefix+"averageRGB_2")!=null)
this.averageRGB[2]=Double.parseDouble(properties.getProperty(prefix+"averageRGB_2"));
if (properties.getProperty(prefix+"viewMap_length")!=null) {
this.viewMap=new int [Integer.parseInt(properties.getProperty(prefix+"viewMap_length"))];
for (int i=0;i<this.viewMap.length;i++) {
this.viewMap[i]=0;
if (properties.getProperty(prefix+"viewMap_"+i)!=null)
this.viewMap[i]=Integer.parseInt(properties.getProperty(prefix+"viewMap_"+i));
}
}
setPhotometric();
calculateGridGeometryAndPhotometric(true); // may need to setup this.photometricBySensor
}
public boolean showDialog() {
GenericDialog gd = new GenericDialog("Initial Wall pattern parameters");
gd.addNumericField("Pattern full width", this.patternWidth, 1,6,"mm"); // pattern full width in mm
gd.addNumericField("Pattern full height", this.patternHeight, 1,6,"mm"); // pattern full width in mm
gd.addNumericField("Distance between opposite sign nodes",this.patternHalfPeriod, 4,8,"mm"); // istance between opposite sign nodes in mm
gd.addNumericField("Pattern tilt (clockwise)", this.patternTilt, 1,5,"degrees"); // pattern tilt (degrees) - U clockwise from X-right (V clockwise from Y-down)
gd.addNumericField("Average grid RED (1.0 for white)", this.averageRGB[0], 3,5,"x"); //
gd.addNumericField("Average grid GREEN (1.0 for white)", this.averageRGB[1], 3,5,"x"); //
gd.addNumericField("Average grid BLUE (1.0 for white)", this.averageRGB[2], 3,5,"x"); //
gd.addNumericField("Number of sensors (>24 - two groups, 0 - do not change)",this.defaultNumberOfChannels,0); //
gd.addMessage("Pressing OK will recalculate grid and clear current grid calibration");
gd.showDialog();
if (gd.wasCanceled()) return false;
this.patternWidth= gd.getNextNumber();
this.patternHeight= gd.getNextNumber();
this.patternHalfPeriod= gd.getNextNumber();
this.patternTilt= gd.getNextNumber();
this.averageRGB[0]= gd.getNextNumber();
this.averageRGB[1]= gd.getNextNumber();
this.averageRGB[2]= gd.getNextNumber();
int numberOfChannels= (int)gd.getNextNumber();
if (numberOfChannels>0){
initDefaultChannels(numberOfChannels);
// setPhotometric();
}
setPhotometric();
calculateGridGeometryAndPhotometric(true);
return true;
}
/**
* Calculate pattern x,y,z==0 and alpha (1.0 - inside, 0.0 - outside) for the grid
* @param resetAll - if true - reset all grid info, if false - only recalculate mask and reset flat field info, keep distortions
*/
public void calculateGridGeometryAndPhotometric(boolean resetAll){
// this.photometricByView should be initialized
int indexAlpha=3;
int indexMask=3;
double cosA=Math.cos(this.patternTilt/180*Math.PI);
double sinA=Math.sin(this.patternTilt/180*Math.PI);
double halfWidth=0.5*this.patternWidth;
double halfHeight=0.5*this.patternHeight;
double [][] uv={
{( halfWidth*cosA+halfHeight*sinA)/this.patternHalfPeriod,
(-halfWidth*sinA+halfHeight*cosA)/this.patternHalfPeriod},
{( halfWidth*cosA-halfHeight*sinA)/this.patternHalfPeriod,
(-halfWidth*sinA-halfHeight*cosA)/this.patternHalfPeriod}};
double [] maxUV={Math.max(Math.abs(uv[0][0]), Math.abs(uv[1][0])),Math.max(Math.abs(uv[0][1]), Math.abs(uv[1][1]))};
this.U0=(int)Math.ceil(maxUV[0]);
this.V0=(int)Math.ceil(maxUV[1]);
resetAll |= (this.gridGeometry==null);
double x,y;
// in any case
int len=(2*this.U0+1)*(2*this.V0+1);
for (int station=0;station<getNumStations();station++){
for (int i=0;i<getNumViews();i++){
for (int chn=0;chn<this.getNumPhotometricChannels();chn++){
this.photometricByView[station][i][chn]=new double [len]; // r,g,b,alpha
}
}
}
if (resetAll) {
for (int station=0;station<getNumStations();station++){
for (int i=0;i<getNumViews();i++){
for (int chn=0;chn<this.getNumPhotometricChannels();chn++){
this.photometricByView[station][i][chn]=new double [len]; // r,g,b,alpha
for (int j=0;j<len;j++){
this.photometricByView[station][i][chn][j]=0.0;
}
}
}
}
this.gridGeometry=new double[2*this.V0+1][2*this.U0+1][getNumGeometricChannels()]; // without resetAll all properties should be the same
for (int v=-this.V0; v<=this.V0;v++) for (int u=-this.U0; u<=this.U0;u++){
x=(u*cosA-v*sinA)*this.patternHalfPeriod;
y=(u*sinA+v*cosA)*this.patternHalfPeriod;
boolean inGrid=((x>=-halfWidth) && (x<=halfWidth) && (y>=-halfHeight) && (y<=halfHeight));
this.gridGeometry[v+this.V0][u+this.U0][0]=x;
this.gridGeometry[v+this.V0][u+this.U0][1]=y;
this.gridGeometry[v+this.V0][u+this.U0][2]=0.0;
this.gridGeometry[v+this.V0][u+this.U0][3]=inGrid?1.0:0.0; // common for all views - to be combined with per-view?
}
}
// always - copy mask to alpha for each view
int index=0;
for (int v=-this.V0; v<=this.V0;v++) for (int u=-this.U0; u<=this.U0;u++){
for (int station=0;station<getNumStations();station++){
for (int nView=0;nView<getNumViews();nView++) {
this.photometricByView[station][nView][indexAlpha][index]=this.gridGeometry[v+this.V0][u+this.U0][indexMask];
for (int c=0;c<3;c++) {
this.photometricByView[station][nView][c][index]=averageRGB[c];
}
}
}
index++;
}
}
public int [] uvIndicesToUV (int u1, int v1){
if ((v1<0) || (u1<0) ||
(v1 >= this.gridGeometry.length) ||
(u1 >= this.gridGeometry[0].length) ||
(this.gridGeometry[v1][u1][3]==0)) return null;
int [] iUV={u1-this.U0, v1-this.V0};
return iUV;
}
public double[] getXYZM(int u, int v, boolean verbose, int station){ // u=0,v=0 - center!
int u1=u+this.U0;
int v1=v+this.V0;
if ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length) ||
(this.gridGeometry[v1][u1][3]==0)) {
if ((this.debugLevel>1) && verbose && ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length))){
String msg="Requested (acquired) grid (point u="+u+",v="+v+") is outside of the physical grid ["+
(-this.U0)+"..."+(this.gridGeometry[0].length-this.U0-1)+"]x["+
(-this.V0)+"..."+(this.gridGeometry.length-this.V0-1)+"]";
//IJ.showMessage("Error",msg);
System.out.println(msg);
}
return null;
}
if (this.stationZCorr==null) return this.gridGeometry[v1][u1];
double [] result=this.gridGeometry[v1][u1].clone();
// use lower station if grid file does not have current
int useStation=(this.stationZCorr[v1][u1].length>station)?station:(this.stationZCorr[v1][u1].length-1);
result[2]+=this.stationZCorr[v1][u1][useStation];
return result;
// return this.gridGeometry[v1][u1];
}
public int getGridIndex(int u, int v){ // u=0,v=0 - center!
int u1=u+this.U0;
int v1=v+this.V0;
if ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length) ||
(this.gridGeometry[v1][u1][3]==0)) {
return -1;
}
return u1+this.gridGeometry[0].length*v1;
}
public double[] getXYZM(int u, int v, int station){ // u=0,v=0 - center!
int u1=u+this.U0;
int v1=v+this.V0;
if ((this.debugLevel >1) && ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length))) {
String msg="Requested (acquired) grid (point u="+u+",v="+v+") is outside of the physical grid ["+
(-this.U0)+"..."+(this.gridGeometry[0].length-this.U0-1)+"]x["+
(-this.V0)+"..."+(this.gridGeometry.length-this.V0-1)+"]";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
if (this.stationZCorr==null) return this.gridGeometry[v1][u1];
double [] result=this.gridGeometry[v1][u1].clone();
result[2]+=this.stationZCorr[v1][u1][station];
return result;
}
public double[] getXYZMAverage(int u, int v){ // u=0,v=0 - center!
int u1=u+this.U0;
int v1=v+this.V0;
if ((this.debugLevel >1) && ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length))) {
String msg="Requested (acquired) grid (point u="+u+",v="+v+") is outside of the physical grid ["+
(-this.U0)+"..."+(this.gridGeometry[0].length-this.U0-1)+"]x["+
(-this.V0)+"..."+(this.gridGeometry.length-this.V0-1)+"]";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
return this.gridGeometry[v1][u1];
}
public double getZCorr(int u, int v, int station){ // u=0,v=0 - center!
if (this.stationZCorr==null) return 0.0;
int u1=u+this.U0;
int v1=v+this.V0;
if ((this.debugLevel >1) && ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length))) {
String msg="Requested (acquired) grid (point u="+u+",v="+v+") is outside of the physical grid ["+
(-this.U0)+"..."+(this.gridGeometry[0].length-this.U0-1)+"]x["+
(-this.V0)+"..."+(this.gridGeometry.length-this.V0-1)+"]";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
return this.stationZCorr[v1][u1][station];
}
public double[] getXYZMAverage(int vu){ // u=0,v=0 - center!
int width=this.gridGeometry[0].length;
int u1=vu%width;
int v1=vu/width;
if ((this.debugLevel >1) && ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length))) {
String msg="Requested (acquired) grid (point vu="+vu+") is outside of the physical grid ["+
(-this.U0)+"..."+(this.gridGeometry[0].length-this.U0-1)+"]x["+
(-this.V0)+"..."+(this.gridGeometry.length-this.V0-1)+"]";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
return this.gridGeometry[v1][u1];
}
public double getZCorr(int vu, int station){ // u=0,v=0 - center!
if (this.stationZCorr==null) return 0.0;
int width=this.gridGeometry[0].length;
int u1=vu%width;
int v1=vu/width;
if ((this.debugLevel >1) && ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length))) {
String msg="Requested (acquired) grid (point vu="+vu+") is outside of the physical grid ["+
(-this.U0)+"..."+(this.gridGeometry[0].length-this.U0-1)+"]x["+
(-this.V0)+"..."+(this.gridGeometry.length-this.V0-1)+"]";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
return this.stationZCorr[v1][u1][station];
}
/**
* Return grid geometry and photometics: X,Y,Z,mask,R,G,B,Alpha
* @param u signed grid U (0 in the center)
* @param v signed grid V (0 in the center)
* @param station station number
* @param channel channel (sensor) number
* @param verbose report out of grid
* @return null if out of grid, otherwise X,Y,Z,mask (binary),R (~0.5..1.2),G,B,alpha (0.0..1.0)
*/
public double[] getXYZMP(
int u,
int v,
int station,
int channel,
boolean verbose){ // u=0,v=0 - center!
int u1=u+this.U0;
int v1=v+this.V0;
if ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length) ||
(this.gridGeometry[v1][u1][3]==0)) {
if ((this.debugLevel>1) && verbose && ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length))){
String msg="Requested (acquired) grid (point u="+u+",v="+v+") is outside of the physical grid ["+
(-this.U0)+"..."+(this.gridGeometry[0].length-this.U0-1)+"]x["+
(-this.V0)+"..."+(this.gridGeometry.length-this.V0-1)+"]";
//IJ.showMessage("Error",msg);
System.out.println(msg);
}
return null;
}
int index=u1+v1*this.gridGeometry[0].length;
if (getNumStations()<=station) updateNumStations(station+1);
int nView=this.viewMap[channel];
if (nView>=this.photometricByView[station].length){ // OOB 1// NUll pointer - need to run F-field first?
nView=this.photometricByView.length-1;
}
double [] result= { // null
this.gridGeometry[v1][u1][0],
this.gridGeometry[v1][u1][1],
this.gridGeometry[v1][u1][2]+((this.stationZCorr!=null)?this.stationZCorr[v1][u1][station]:0.0), // per-station correction
this.gridGeometry[v1][u1][3],
this.photometricByView[station][nView][0][index],
this.photometricByView[station][nView][1][index],
this.photometricByView[station][nView][2][index],
this.photometricByView[station][nView][3][index]
};
return result;
}
public double[] getXYZMPE(
int u,
int v,
int station,
int channel,
boolean verbose){ // u=0,v=0 - center!
int u1=u+this.U0;
int v1=v+this.V0;
if ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length) ||
(this.gridGeometry[v1][u1][3]==0)) {
if ((this.debugLevel>1) && verbose && ((v1<0) || (u1<0) || (v1 >= this.gridGeometry.length) || (u1 >= this.gridGeometry[0].length))){
String msg="Requested (acquired) grid (point u="+u+",v="+v+") is outside of the physical grid ["+
(-this.U0)+"..."+(this.gridGeometry[0].length-this.U0-1)+"]x["+
(-this.V0)+"..."+(this.gridGeometry.length-this.V0-1)+"]";
//IJ.showMessage("Error",msg);
System.out.println(msg);
}
return null;
}
int index=u1+v1*this.gridGeometry[0].length;
if (getNumStations()<=station) updateNumStations(station+1);
int nView=this.viewMap[channel];
int useStation=(this.stationZCorr!=null)?((this.stationZCorr[v1][u1].length>station)?station:(this.stationZCorr[v1][u1].length-1)):0;
if (nView>=this.photometricByView[station].length){ // OOB 1// NUll pointer - need to run F-field first? (oob1 when grid had less than now
nView=this.photometricByView.length-1;
}
double [] result= { // null
this.gridGeometry[v1][u1][0],
this.gridGeometry[v1][u1][1],
// this.gridGeometry[v1][u1][2]+((this.stationZCorr!=null)?this.stationZCorr[v1][u1][station]:0.0), // per-station correction
this.gridGeometry[v1][u1][2]+((this.stationZCorr!=null)?this.stationZCorr[v1][u1][useStation]:0.0), // per-station correction
this.gridGeometry[v1][u1][3],
this.photometricByView[station][nView][0][index],
this.photometricByView[station][nView][1][index],
this.photometricByView[station][nView][2][index],
this.photometricByView[station][nView][3][index],
(this.patternErrorMask==null)?1.0:this.patternErrorMask[index]
};
return result;
}
public double [][][] getGeometry(){return this.gridGeometry;}
}
......@@ -818,7 +818,7 @@ public class SFEPhases {
// Ask for image selection (multiple directories), accumulate and create array of accumulated images
public ImagePlus[] getInteractiveAccumulatedImages(
Distortions.DistortionProcessConfiguration distortionProcessConfiguration,
DistortionProcessConfiguration distortionProcessConfiguration,
final AtomicInteger stopRequested,
int threadsMax,
boolean updateStatus,
......@@ -1199,7 +1199,7 @@ public class SFEPhases {
}
public SensorDefects[] accummulateSensorDefects(
Distortions.DistortionProcessConfiguration distortionProcessConfiguration,
DistortionProcessConfiguration distortionProcessConfiguration,
int tileClearSize,
int tileMargins,
int cmask, // bitmask of color channels to process (9 - two greens)
......
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