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

Merge branch 'lwir-distort' of git.elphel.com:Elphel/imagej-elphel into lwir-distort

parents 7f44490f 3b485572
......@@ -31,6 +31,7 @@ import java.awt.Color;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
......@@ -49,6 +50,8 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
......@@ -1461,7 +1464,9 @@ if (MORE_BUTTONS) {
"", //arg - not used in JP46 reader
true, // un-apply camera color gains
imp_sel); // reuse the same image window
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
// matchSimulatedPattern.invalidateFlatFieldForGrid(); //It is already reset, no need to do it again
// matchSimulatedPattern.invalidateFocusMask();
matchSimulatedPattern.calculateDistortions(
......@@ -1829,7 +1834,9 @@ if (MORE_BUTTONS) {
IJ.showMessage("Error","There are no images open\nProcess canceled");
return;
}
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
matchSimulatedPattern.debugLevel=DEBUG_LEVEL;
matchSimulatedPattern.distortionsTest (
DISTORTION, //
......@@ -1858,7 +1865,10 @@ if (MORE_BUTTONS) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
imp_sel = WindowManager.getCurrentImage();
// imp_distortions=imp_sel;
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
// matchSimulatedPattern.invalidateFlatFieldForGrid(); //It is already reset, no need to do it again
// matchSimulatedPattern.invalidateFocusMask();
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
......@@ -3183,7 +3193,10 @@ if (MORE_BUTTONS) {
if (label.equals("Update Focusing Grid")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
if (matchSimulatedPattern==null) {
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
}
matchSimulatedPattern.debugLevel=DEBUG_LEVEL;
imp_sel = WindowManager.getCurrentImage();
......@@ -3345,7 +3358,10 @@ if (MORE_BUTTONS) {
//"Focusing Acquire PSF"
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
if (matchSimulatedPattern==null) {
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
}
matchSimulatedPattern.debugLevel=DEBUG_LEVEL;
if (LENS_DISTORTION_PARAMETERS==null){
......@@ -3556,7 +3572,9 @@ if (MORE_BUTTONS) {
if (DEBUG_LEVEL>0) System.out.println("Image acquisition (@"+FOCUS_MEASUREMENT_PARAMETERS.sensorTemperature+"C) done at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
// reset matchSimulatedPattern, so it will start from scratch
matchSimulatedPatternSet[imgCounter] = new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
int sensor_type = 0; // EO
// matchSimulatedPatternSet[imgCounter] = new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
matchSimulatedPatternSet[imgCounter] = new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type)); // new instance, all reset
// next 2 lines are not needed for the new instance, but can be used alternatively if keeipg it
matchSimulatedPatternSet[imgCounter].invalidateFlatFieldForGrid(); //Reset Flat Field calibration - different image.
matchSimulatedPatternSet[imgCounter].invalidateFocusMask();
......@@ -3833,7 +3851,10 @@ if (MORE_BUTTONS) {
}
POWER_CONTROL.lightsOnWithDelay();
if (matchSimulatedPattern==null) {
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
}
matchSimulatedPattern.debugLevel=DEBUG_LEVEL;
if (LENS_DISTORTION_PARAMETERS==null){
......@@ -4180,7 +4201,9 @@ if (MORE_BUTTONS) {
}
}
if (matchSimulatedPattern==null) {
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
}
matchSimulatedPattern.debugLevel=MASTER_DEBUG_LEVEL;
if (LENS_DISTORTION_PARAMETERS==null){
......@@ -4389,7 +4412,9 @@ if (MORE_BUTTONS) {
}
}
if (matchSimulatedPattern==null) {
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
}
matchSimulatedPattern.debugLevel=DEBUG_LEVEL;
if (LENS_DISTORTION_PARAMETERS==null){
......@@ -6069,211 +6094,7 @@ if (MORE_BUTTONS) {
return;
}
LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
GenericDialog gd=new GenericDialog ("Select image set to re-calibrate");
gd.addNumericField("Image set number", 0, 0);
gd.addCheckbox ("Set image set parameters from closest, (re-)estimate orientation", true);
gd.showDialog();
if (gd.wasCanceled()) return;
int imageSetNumber=(int) gd.getNextNumber();
boolean reEstimate=gd.getNextBoolean();
if (imageSetNumber<0) return;
if (reEstimate){
// boolean OK=
LENS_DISTORTIONS.setSetFromClosestAndEstimateOrientation(
imageSetNumber,
null, //boolean [] selectedImages,
null, //boolean [] parameterMask,
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData,
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.eyesisCameraParameters);
}
double tiltCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
double axialCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
double interCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle;
int tiltNumSteps=1;
int axialNumSteps=21;
double tiltStep=0.25;
double axialStep=0.25;
boolean processAllImages=true;
boolean ignoreLaserPointers=false;
double hintGridTolerance=200.0;
boolean useSetsData= true;
gd=new GenericDialog ("Image set # "+imageSetNumber+" re-calibration without laser pointers");
gd.addMessage("Strategy 0 should have all parameters but 2 goniometer axes disabled");
gd.addMessage("Imgages belonging to the set will be selected, possible to check with \"Remove Outliers\" for strategy 0");
gd.addNumericField("Mismatch tolerance of match between the predicted and acquired grid", hintGridTolerance, 1,4,"fraction of grid half-period");
gd.addCheckbox("Ignore laser pointers", ignoreLaserPointers);
gd.addNumericField("Image set tilt", tiltCenter, 2,6,"degrees");
gd.addNumericField("Image set axial", axialCenter, 2,6,"degrees");
gd.addNumericField("Image set inter-axis", interCenter, 2,6,"degrees");
gd.addNumericField("Tilt number of steps", tiltNumSteps, 0,3,"");
gd.addNumericField("Axial number of steps", axialNumSteps, 0,3,"");
gd.addNumericField("Tilt scan step", tiltStep, 2,5,"degrees");
gd.addNumericField("Axial scan step", axialStep, 2,5,"degrees");
gd.addCheckbox ("Use image sets data if available (false - use camera data)", useSetsData);
gd.addCheckbox("process all images (false - enabled only)", processAllImages);
gd.showDialog();
if (gd.wasCanceled()) return;
hintGridTolerance= gd.getNextNumber();
ignoreLaserPointers= gd.getNextBoolean();
tiltCenter= gd.getNextNumber();
axialCenter= gd.getNextNumber();
interCenter= gd.getNextNumber();
tiltNumSteps= (int) gd.getNextNumber();
axialNumSteps= (int) gd.getNextNumber();
tiltStep= gd.getNextNumber();
axialStep= gd.getNextNumber();
useSetsData= gd.getNextBoolean();
processAllImages= gd.getNextBoolean();
double [] initialTilt = new double [tiltNumSteps];
double [] initialAxial= new double [axialNumSteps];
double [][] finalTilt = new double [tiltNumSteps][axialNumSteps];
double [][] finalAxial= new double [tiltNumSteps][axialNumSteps];
double [][] finalInter= new double [tiltNumSteps][axialNumSteps];
double [][] finalError= new double [tiltNumSteps][axialNumSteps];
for (int tiltIndex=0; tiltIndex<tiltNumSteps;tiltIndex++) initialTilt[tiltIndex]=tiltCenter+tiltStep*(tiltIndex-0.5*(tiltNumSteps-1));
for (int axialIndex=0;axialIndex<axialNumSteps;axialIndex++) initialAxial[axialIndex]=axialCenter+axialStep*(axialIndex-0.5*(axialNumSteps-1));
for (int tiltIndex=0; tiltIndex<tiltNumSteps;tiltIndex++) for (int axialIndex=0;axialIndex<axialNumSteps;axialIndex++) {
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt=initialTilt[tiltIndex];
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial=initialAxial[axialIndex];
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle=interCenter; // no scanning, just use center value
if (DEBUG_LEVEL>0) System.out.println("Image Set #"+imageSetNumber+
" Initial tilt="+initialTilt[tiltIndex]+
" Initial inter="+interCenter);
int [][] imageSets=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.listImages(!processAllImages);
int [] imageSet=imageSets[imageSetNumber];
if (imageSet==null){
IJ.showMessage("Image set #"+imageSetNumber+" is empty");
return;
}
for (int i=0;i<imageSet.length;i++){
int imageNumber=imageSet[i];
LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
hintGridTolerance, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //processAll, //boolean processAll, // if true - process all images, false - only disabled
ignoreLaserPointers, //true, //ignoreLaserPointers,
true, //processBlind,
imageNumber,
useSetsData,
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
}
// set series 0 to this set images
boolean [] selection =LENS_DISTORTIONS.fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
for (int i=0;i<imageSet.length;i++) selection[imageSet[i]]=true;
LENS_DISTORTIONS.fittingStrategy.setImageSelection(0,selection);
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
LENS_DISTORTIONS.fittingStrategy.stopAfterThis[0]=true;
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.stopOnFailure=false;
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0]; // 0.001; // why it does not use fitting series lambda?
boolean LMA_OK=LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
if (LMA_OK) {
finalTilt[tiltIndex][axialIndex]=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
finalAxial[tiltIndex][axialIndex]=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
finalInter[tiltIndex][axialIndex]=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle;
finalError[tiltIndex][axialIndex]=LENS_DISTORTIONS.currentRMS;
} else {
finalTilt[tiltIndex][axialIndex]=initialTilt[tiltIndex];
finalAxial[tiltIndex][axialIndex]=initialAxial[axialIndex];
finalInter[tiltIndex][axialIndex]=interCenter;
finalError[tiltIndex][axialIndex]=Double.NaN;
if (DEBUG_LEVEL>0) System.out.println("----------------- LMA FAILED -------------------------");
}
}
int bestTiltIndex=0;
int bestAxialIndex=0;
double bestRMS=finalError[bestTiltIndex][bestAxialIndex];
for (int tiltIndex=0; tiltIndex<tiltNumSteps;tiltIndex++) for (int axialIndex=0;axialIndex<axialNumSteps;axialIndex++) {
if (Double.isNaN(bestRMS) || (bestRMS>finalError[tiltIndex][axialIndex])){
bestTiltIndex=tiltIndex;
bestAxialIndex=axialIndex;
bestRMS=finalError[bestTiltIndex][bestAxialIndex];
}
}
if (DEBUG_LEVEL>0) System.out.println("================ Image Set #"+imageSetNumber+" rms="+IJ.d2s(bestRMS, 6)+
" final tilt="+finalTilt[bestTiltIndex][bestAxialIndex]+" ("+tiltCenter+": "+initialTilt[bestTiltIndex]+") " +
" final axial="+finalAxial[bestTiltIndex][bestAxialIndex]+" ("+axialCenter+": "+initialAxial[bestAxialIndex]+")"+
" final inter="+finalInter[bestTiltIndex][bestAxialIndex]+" ("+interCenter+": "+interCenter+")");
// repeat with the best indices
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt=finalTilt[bestTiltIndex][bestAxialIndex]; //initialTilt[bestTiltIndex];
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial=finalAxial[bestTiltIndex][bestAxialIndex]; //initialAxial[bestAxialIndex];
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle=finalInter[bestTiltIndex][bestAxialIndex];
if (DEBUG_LEVEL>0) System.out.println(
"Image Set #"+imageSetNumber+
" Initial tilt="+finalTilt[bestTiltIndex][bestAxialIndex]+
" Initial axial="+finalAxial[bestTiltIndex][bestAxialIndex]+
" Initial inter="+finalInter[bestTiltIndex][bestAxialIndex]
);
int [][] imageSets=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.listImages(!processAllImages);
int [] imageSet=imageSets[imageSetNumber];
if (imageSet==null){
IJ.showMessage("Image set #"+imageSetNumber+" is empty");
return;
}
for (int i=0;i<imageSet.length;i++){
int imageNumber=imageSet[i];
LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
hintGridTolerance, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //processAll, //boolean processAll, // if true - process all images, false - only disabeld
ignoreLaserPointers, //ignoreLaserPointers,
true, //processBlind,
imageNumber,
useSetsData,
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
}
// set series 0 to this set images
boolean [] selection =LENS_DISTORTIONS.fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
for (int i=0;i<imageSet.length;i++) selection[imageSet[i]]=true;
LENS_DISTORTIONS.fittingStrategy.setImageSelection(0,selection);
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
LENS_DISTORTIONS.fittingStrategy.stopAfterThis[0]=true;
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
// save safe settings to run LMA manually
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
LENS_DISTORTIONS.stopEachSeries= true; // will not ask for confirmation after done
LENS_DISTORTIONS.stopOnFailure=true;
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
if (DEBUG_LEVEL>0) System.out.println("================ Image Set #"+imageSetNumber+" rms="+IJ.d2s(bestRMS, 6)+
" final tilt="+finalTilt[bestTiltIndex][bestAxialIndex]+" ("+tiltCenter+": "+initialTilt[bestTiltIndex]+") " +
" final axial="+finalAxial[bestTiltIndex][bestAxialIndex]+" ("+axialCenter+": "+initialAxial[bestAxialIndex]+")" +
" final inter="+finalInter[bestTiltIndex][bestAxialIndex]+" ("+interCenter+")");
recalibrateSet();
return;
}
......@@ -9730,6 +9551,318 @@ if (MORE_BUTTONS) {
}
public boolean recalibrateSet() {
GenericDialog gd=new GenericDialog ("Select image set to re-calibrate");
gd.addNumericField("Image set number", 0, 0);
gd.addCheckbox ("Set image set parameters from closest, (re-)estimate orientation", true);
gd.showDialog();
if (gd.wasCanceled()) return false;
int imageSetNumber=(int) gd.getNextNumber();
boolean reEstimate=gd.getNextBoolean();
if (imageSetNumber<0) return false;
if (reEstimate){
// boolean OK=
LENS_DISTORTIONS.setSetFromClosestAndEstimateOrientation(
imageSetNumber,
null, //boolean [] selectedImages,
null, //boolean [] parameterMask,
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData,
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.eyesisCameraParameters);
}
double tiltCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
double axialCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
double interCenter=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle;
double tiltHalfRange = 2.0; // degrees
double axialHalfRange = 15.0; // degrees
int scanHalfV = 10; // can be large - actual will be limited by angular range
int scanHalfU = 10; // can be large - actual will be limited by angular range
double stopRMS = 1.0; // exit when RMS falls below
boolean processAllImages=true;
boolean ignoreLaserPointers=false;
double hintGridTolerance=200.0;
boolean useSetsData= true;
gd=new GenericDialog ("Image set # "+imageSetNumber+" re-calibration without laser pointers");
gd.addMessage("Strategy 0 should have all parameters but 2 goniometer axes disabled");
gd.addMessage("Imgages belonging to the set will be selected, possible to check with \"Remove Outliers\" for strategy 0");
gd.addNumericField("Mismatch tolerance of match between the predicted and acquired grid", hintGridTolerance, 1,4,"fraction of grid half-period");
gd.addCheckbox("Ignore laser pointers", ignoreLaserPointers);
gd.addNumericField("Image set center tilt", tiltCenter, 2,6,"degrees");
gd.addNumericField("Image set center axial", axialCenter, 2,6,"degrees");
gd.addNumericField("Image set inter-axis", interCenter, 2,6,"degrees");
gd.addNumericField("Tilt scan half-range", tiltHalfRange, 2,6,"degrees");
gd.addNumericField("Axial scan half-range", axialHalfRange, 2,6,"degrees");
gd.addNumericField("Half scan in U (almost horizontal) grid nodes (large will be limited by angular range)", scanHalfU, 0,3,"");
gd.addNumericField("Half scan in V (almost vertical) grid nodes (large will be limited by angular range)", scanHalfV, 0,3,"");
gd.addNumericField("Stop RMS - exit scan when RMS falls below", stopRMS, 2,6,"pixels");
gd.addCheckbox ("Use image sets data if available (false - use camera data)", useSetsData);
gd.addCheckbox("process all images (false - enabled only)", processAllImages);
gd.showDialog();
if (gd.wasCanceled()) return false;
hintGridTolerance= gd.getNextNumber();
ignoreLaserPointers= gd.getNextBoolean();
tiltCenter= gd.getNextNumber();
axialCenter= gd.getNextNumber();
interCenter= gd.getNextNumber();
tiltHalfRange= gd.getNextNumber();
axialHalfRange= gd.getNextNumber();
scanHalfV= (int) gd.getNextNumber();
scanHalfU= (int) gd.getNextNumber();
stopRMS = gd.getNextNumber();
useSetsData= gd.getNextBoolean();
processAllImages= gd.getNextBoolean();
// Find channel with most weight
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt=tiltCenter;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial=axialCenter;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle=interCenter;
// Run once with center position or Goniometer angles to determine average derivatives
int [][] imageSets=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.listImages(!processAllImages);
int [] imageSet=imageSets[imageSetNumber];
if (imageSet==null){
IJ.showMessage("Image set #"+imageSetNumber+" is empty");
return false;
}
for (int i=0;i<imageSet.length;i++){
int imageNumber=imageSet[i];
LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
hintGridTolerance, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //processAll, //boolean processAll, // if true - process all images, false - only disabeld
ignoreLaserPointers, //ignoreLaserPointers,
true, //processBlind,
imageNumber,
useSetsData,
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
}
boolean [] selection =LENS_DISTORTIONS.fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
for (int i=0;i<imageSet.length;i++) selection[imageSet[i]]=true;
LENS_DISTORTIONS.fittingStrategy.setImageSelection(0,selection);
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
LENS_DISTORTIONS.fittingStrategy.stopAfterThis[0]=true;
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
Distortions distortions_dbg = LENS_DISTORTIONS;
LENS_DISTORTIONS.LevenbergMarquardt( // Index 0 out of bounds for length 0
false, // skip dialog
false, // new: dry_run use it here?
true);
double [][] dTA_dUV = LENS_DISTORTIONS.getDtaDuv();
if (DEBUG_LEVEL > 0) {
System.out.println(
"Grid dTilt/dU = "+dTA_dUV[0][0]+"\n"+
"Grid dAxial/dU = "+dTA_dUV[1][0]+"\n"+
"Grid dTilt/dV = "+dTA_dUV[0][1]+"\n"+
"Grid dAxial/dV = "+dTA_dUV[1][1]);
}
// update center angles
tiltCenter= LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
axialCenter= LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
interCenter = LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle;
double rms_last= LENS_DISTORTIONS.currentRMS;
double tilt_last = tiltCenter;
double axial_last = axialCenter;
double inter_last = interCenter;
double best_rms = rms_last;
double best_tilt = tilt_last;
double best_axial = axial_last;
double best_inter = inter_last;
Point best_pnt = new Point(0,0);
if (best_rms > stopRMS) { // do nothing if the original center is already OK
ArrayList<Point> nodeList = new ArrayList<Point>();
for (int dv = -scanHalfV; dv <= scanHalfV; dv++) {
for (int du = -scanHalfU; du <= scanHalfU; du++) {
if ((((dv+du) % 2) == 0) && ((dv !=0) || (du != 0))){
double dtilt = dTA_dUV[0][0]*du + dTA_dUV[0][1]*dv;
double daxial = dTA_dUV[1][0]*du + dTA_dUV[1][1]*dv;
if ((Math.abs(dtilt) <= tiltHalfRange) && (Math.abs(daxial) <= axialHalfRange)) {
nodeList.add(new Point(du,dv));
}
}
}
}
// sort list
Collections.sort(nodeList, new Comparator<Point>() {
@Override
public int compare(Point lhs, Point rhs) {
double rhsl2 = rhs.getX()*rhs.getX() + rhs.getY()*rhs.getY();
double lhsl2 = lhs.getX()*lhs.getX() + lhs.getY()*lhs.getY();
return (rhsl2 > lhsl2) ? -1 : (rhsl2 < lhsl2) ? 1 : 0;
}
});
for (Point pnt:nodeList) {
double dtilt = dTA_dUV[0][0]*pnt.getX() + dTA_dUV[0][1]*pnt.getY();
double daxial = dTA_dUV[1][0]*pnt.getX() + dTA_dUV[1][1]*pnt.getY();
double tilt0 = tiltCenter + dtilt;
double axial0 = axialCenter + daxial;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt = tilt0;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial = axial0;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle = interCenter; // no scanning, just use center value
if (DEBUG_LEVEL>0) System.out.println("Image Set #"+imageSetNumber+
" Initial tilt=" + tilt0+
" Initial axial=" + axial0+
" Initial inter=" + interCenter);
imageSets=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.listImages(!processAllImages);
imageSet=imageSets[imageSetNumber];
if (imageSet==null){
IJ.showMessage("Image set #"+imageSetNumber+" is empty");
return false;
}
for (int i=0;i<imageSet.length;i++){
int imageNumber=imageSet[i];
LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
hintGridTolerance, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //processAll, //boolean processAll, // if true - process all images, false - only disabled
ignoreLaserPointers, //true, //ignoreLaserPointers,
true, //processBlind,
imageNumber,
useSetsData,
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
}
selection =LENS_DISTORTIONS.fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
for (int i=0;i<imageSet.length;i++) selection[imageSet[i]]=true;
LENS_DISTORTIONS.fittingStrategy.setImageSelection(0,selection);
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
LENS_DISTORTIONS.fittingStrategy.stopAfterThis[0]=true;
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.stopOnFailure=false;
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0]; // 0.001; // why it does not use fitting series lambda?
boolean LMA_OK=LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false, // new: dry_run use it here?
false); // no need to calculate dTA_dUV
if (LMA_OK) {
tilt_last = LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
axial_last = LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
inter_last = LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle;
rms_last = LENS_DISTORTIONS.currentRMS;
if (rms_last < best_rms) { // no Double.NaN for best_rms here
best_rms = rms_last;
best_tilt = tilt_last;
best_axial = axial_last;
best_inter = inter_last;
best_pnt = pnt;
}
if (best_rms <= stopRMS) {
break;
}
} else {
if (DEBUG_LEVEL>0) System.out.println("----------------- LMA FAILED -------------------------");
}
}
if (DEBUG_LEVEL>0) System.out.println("================ Image Set #"+imageSetNumber+" rms="+IJ.d2s(best_rms, 6)+
" final tilt= "+best_tilt+ " ("+tiltCenter+")\n" +
" final axial="+best_axial+" ("+axialCenter+")\n"+
" final inter="+best_inter+" ("+interCenter+")");
if (best_rms != rms_last) {
// Restore best position if it was not the last
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt= best_tilt;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial=best_axial;
LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].interAxisAngle= best_inter;
if (DEBUG_LEVEL>0) System.out.println(
"Repeating with the best variant for Image Set #"+imageSetNumber+
" Initial tilt="+best_tilt+
" Initial axial="+best_axial+
" Initial inter="+best_inter
);
imageSets=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.listImages(!processAllImages);
imageSet=imageSets[imageSetNumber];
if (imageSet==null){
IJ.showMessage("Image set #"+imageSetNumber+" is empty");
return false;
}
for (int i=0;i<imageSet.length;i++){
int imageNumber=imageSet[i];
LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
hintGridTolerance, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //processAll, //boolean processAll, // if true - process all images, false - only disabeld
ignoreLaserPointers, //ignoreLaserPointers,
true, //processBlind,
imageNumber,
useSetsData,
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
}
// set series 0 to this set images
selection =LENS_DISTORTIONS.fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
for (int i=0;i<imageSet.length;i++) selection[imageSet[i]]=true;
LENS_DISTORTIONS.fittingStrategy.setImageSelection(0,selection);
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
LENS_DISTORTIONS.fittingStrategy.stopAfterThis[0]=true;
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
}
}
//save safe settings to run LMA manually
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
LENS_DISTORTIONS.initFittingSeries(false,LENS_DISTORTIONS.filterForAll,0); // will set this.currentVector
LENS_DISTORTIONS.stopEachSeries= true; // will not ask for confirmation after done
LENS_DISTORTIONS.stopOnFailure=true;
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
if (DEBUG_LEVEL > -1) System.out.println("================ Image Set #"+imageSetNumber+" rms="+IJ.d2s(best_rms, 6)+
" final tilt="+best_tilt+" ("+tiltCenter+") " +
" final axial="+best_axial+" ("+axialCenter+")" +
" final inter="+best_inter+" ("+interCenter+")" +
" final UV offset = ("+best_pnt.getX()+","+best_pnt.getY()+")");
return true;
}
public boolean lwirToEo() {
if (LENS_DISTORTIONS == null) {
System.out.println("LENS_DISTORTIONS is null");
......@@ -10204,8 +10337,14 @@ if (MORE_BUTTONS) {
String prefix="grid-";
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
DISTORTION_PROCESS_CONFIGURATION.debugLevel=MASTER_DEBUG_LEVEL;
if (matchSimulatedPattern==null) matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
/*
if (matchSimulatedPattern==null) {
int sensor_type = 0; // EO
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type)); //FIXME: works only for EO !!!
}
matchSimulatedPattern.debugLevel=MASTER_DEBUG_LEVEL;
*/
String [] sourceSetList = DISTORTION_PROCESS_CONFIGURATION.selectSourceSets();
LWIR_PARAMETERS.selectSourceChannels();
boolean [] sel_chn = LWIR_PARAMETERS.getSelected();
......@@ -10271,12 +10410,14 @@ if (MORE_BUTTONS) {
}
imp_sel=new ImagePlus(sourceFilesList[nset][nfile]); // read source file
EyesisTiff.decodeProperiesFromInfo(imp_sel);
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // TODO: is it needed each time?
int sensor_type = LwirReaderParameters.sensorType(imp_sel);
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type)); // FFTSize); // TODO: is it needed each time?
matchSimulatedPattern.debugLevel=MASTER_DEBUG_LEVEL;
matchSimulatedPattern.invalidateFlatFieldForGrid(); //Reset Flat Field calibration - different image.
matchSimulatedPattern.invalidateFocusMask();
boolean is_lwir = LWIR_PARAMETERS.is_LWIR(imp_sel); // Not used!
boolean is_lwir = (sensor_type == 1); // LWIR_PARAMETERS.is_LWIR(imp_sel); // Not used! sensorType(ImagePlus imp)
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions( // matchSimulatedPattern.PATTERN_GRID already set
LWIR_PARAMETERS, // LwirReaderParameters lwirReaderParameters,
DISTORTION, //
......@@ -10353,7 +10494,11 @@ if (MORE_BUTTONS) {
String prefix="grid-";
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
DISTORTION_PROCESS_CONFIGURATION.debugLevel=MASTER_DEBUG_LEVEL;
if (matchSimulatedPattern==null) matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
if (matchSimulatedPattern==null) {
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
}
matchSimulatedPattern.debugLevel=MASTER_DEBUG_LEVEL;
String [] sourceFilesList=DISTORTION_PROCESS_CONFIGURATION.selectSourceFiles(); // select files - with/without dialog
boolean saveGrids=DISTORTION_PROCESS_CONFIGURATION.saveGridImages;
......@@ -10384,7 +10529,9 @@ if (MORE_BUTTONS) {
}
imp_sel=new ImagePlus(sourceFilesList[numFile]); // read source file
JP4_INSTANCE.decodeProperiesFromInfo(imp_sel);
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // TODO: is it needed each time?
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // TODO: is it needed each time?
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
if (!DISTORTION_PROCESS_CONFIGURATION.useNoPonters && (MatchSimulatedPattern.getPointersXYUV(imp_sel,LASER_POINTERS)==null)) {
if (this.SYNC_COMMAND.stopRequested.get()>0) {
System.out.println("User requested stop");
......@@ -10499,7 +10646,9 @@ if (MORE_BUTTONS) {
true, // un-apply camera color gains
imp_sel); // reuse the same image window
//Remove for old method?
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
// matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
int sensor_type = 0; // EO
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type));
matchSimulatedPattern.calculateDistortions(
LWIR_PARAMETERS,
DISTORTION, //
......@@ -10900,6 +11049,8 @@ if (MORE_BUTTONS) {
numInBase2= (int) gd.getNextNumber();
binWidth2 = gd.getNextNumber();
gapWidth2 = gd.getNextNumber();
int sensor_type = 0; // EO
double [] defectsBayer=(new SFEPhases()).getDefectsBayer(
imp_sel,
tileClearSize,
......@@ -10915,7 +11066,9 @@ if (MORE_BUTTONS) {
numInBase2,
binWidth2,
gapWidth2,
new MatchSimulatedPattern(DISTORTION.FFTSize), //matchSimulatedPattern=
// new MatchSimulatedPattern(DISTORTION.FFTSize), //matchSimulatedPattern=
new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type)),
COMPONENTS,
THREADS_MAX,
DEBUG_LEVEL);
......@@ -10978,6 +11131,7 @@ if (MORE_BUTTONS) {
numInBase2= (int) gd.getNextNumber();
binWidth2 = gd.getNextNumber();
gapWidth2 = gd.getNextNumber();
int sensor_type = 0; // EO
SFEPhases.SensorDefects[] defectsStats=(new SFEPhases()).accummulateSensorDefects(
DISTORTION_PROCESS_CONFIGURATION,
// imp_sel,
......@@ -10994,7 +11148,9 @@ if (MORE_BUTTONS) {
numInBase2,
binWidth2,
gapWidth2,
new MatchSimulatedPattern(DISTORTION.FFTSize), //matchSimulatedPattern=
// new MatchSimulatedPattern(DISTORTION.FFTSize), //matchSimulatedPattern=
new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type)),
COMPONENTS,
this.SYNC_COMMAND.stopRequested,
THREADS_MAX,
......@@ -11061,6 +11217,7 @@ if (MORE_BUTTONS) {
}
if (showImages) for (ImagePlus imp:accImages) if (imp!=null) imp.show();
// SFEPhases sfe_phases= new SFEPhases();
int sensor_type = 0; // EO
defectList= (new SFEPhases()).interactiveExtractDefectListsFromAccumulatedImages(
accImages,
128, // tileClearSize,
......@@ -11080,7 +11237,8 @@ if (MORE_BUTTONS) {
true, // processCold,
true, // updateSensorCalibrationFiles
false, // clearDefects, // clear defects if none detected
new MatchSimulatedPattern(DISTORTION.FFTSize), //matchSimulatedPattern=
// new MatchSimulatedPattern(DISTORTION.FFTSize), //matchSimulatedPattern=
new MatchSimulatedPattern(DISTORTION.getFFTSize(sensor_type)),
COMPONENTS,
THREADS_MAX,
DEBUG_LEVEL);
......@@ -21043,180 +21201,12 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
/* ======================================================================== */
/* ======================================================================== */
public boolean showDistortionDialog(MatchSimulatedPattern.DistortionParameters distortionParameters) {
int i;
GenericDialog gd = new GenericDialog("Distrortion parameters");
gd.addNumericField("FFTSize (Initial pattern and aberraton kernels):", distortionParameters.FFTSize, 0); // 256
gd.addNumericField("FFTSize for LWIR sensors):", distortionParameters.FFTSize_lwir, 0); // 32
gd.addNumericField("FFTOverlap (aberration kernels):", distortionParameters.FFTOverlap, 0); // 32
gd.addNumericField("FFTOverlap for LWIR sensors):", distortionParameters.FFTOverlap_lwir, 0); // 4
gd.addNumericField("FFT Gaussian width (relative):", distortionParameters.fftGaussWidth, 3);
gd.addNumericField("Correlation size:", distortionParameters.correlationSize, 0); // 64
gd.addNumericField("Correlation size LWIR:", distortionParameters.correlationSizeLwir, 0); // 16
gd.addNumericField("Maximal correlation size:", distortionParameters.maximalCorrelationSize, 0); // 128
gd.addNumericField("Maximal correlation size LWIR:", distortionParameters.maximalCorrelationSizeLwir, 0); // 16
gd.addNumericField("Correlation Gauss width (relative):", distortionParameters.correlationGaussWidth, 3);
gd.addCheckbox("Keep Gaussian width absolute when increasing FFT size",distortionParameters.absoluteCorrelationGaussWidth);
// /phaseCorrelationFraction
//// leave this number of zeros on teh margins of the window (toatal from both sides). If correlationGaussWidth>0 will
// additionally multiply by Hamming
gd.addNumericField("Leave zeros on the window margins (toatal numbedr from both sides)", distortionParameters.zeros, 0);
gd.addNumericField("Phase correlation modifier (1.0 - phase corr., 0 - just corr.)", distortionParameters.phaseCorrelationFraction, 5);
gd.addNumericField("Correlation high-pass sigma:", distortionParameters.correlationHighPassSigma, 3);
gd.addNumericField("Correlation low-pass sigma (fraction of sqrt(2)*Nyquist, lower - more filtering, 0 -none):",distortionParameters.correlationLowPassSigma, 3);
gd.addNumericField("Correlation maximal offset from predicted:",distortionParameters.correlationMaxOffset, 3);
gd.addNumericField("Detection ring width (fraction):", distortionParameters.correlationRingWidth, 3);
gd.addNumericField("Correlation minimal contrast (normalized)", distortionParameters.correlationMinContrast, 3);
gd.addNumericField("Correlation minimal contrast for initial search (normalized)", distortionParameters.correlationMinInitialContrast, 3);
gd.addNumericField("Correlation minimal contrast (absolute)", distortionParameters.correlationMinAbsoluteContrast, 3);
gd.addNumericField("Correlation minimal contrast for initial search (absolute)", distortionParameters.correlationMinAbsoluteInitialContrast, 3);
gd.addNumericField("Decrease contrast of cells that are too close to the border to be processed in refinement pass", distortionParameters.scaleFirstPassContrast, 3);
gd.addNumericField("Gaussian sigma to select correlation center in pixels, 2.0", distortionParameters.contrastSelectSigmaCenter, 3);
gd.addNumericField("Gaussian sigma to select correlation off-centers (fraction of UV period), 0.1", distortionParameters.contrastSelectSigma, 3);
gd.addNumericField("Gaussian sigma to average correlation variations (as contrast reference), 0.5", distortionParameters.contrastAverageSigma, 3);
gd.addNumericField("Minimal initial pattern cluster size (0 - disable retries)", distortionParameters.minimalPatternCluster, 0); // 40
gd.addNumericField("Minimal initial LWIR pattern cluster size (0 - disable retries)", distortionParameters.minimalPatternClusterLwir, 0); // 10
gd.addNumericField("Scale minimal contrast if the initial cluster is nonzero but smaller", distortionParameters.scaleMinimalInitialContrast, 3);
gd.addNumericField("Overlap of FFT areas when searching for pattern", distortionParameters.searchOverlap, 3);
gd.addNumericField("Pattern subdivision:", distortionParameters.patternSubdiv, 0); // 4
gd.addNumericField("Blur pattern bitmap (sigma): ", distortionParameters.bPatternSigma, 3,5,"pattern cell"); // 0.02
gd.addNumericField("Blur pattern (sigma): ", distortionParameters.barraySigma, 3,5,"sensor pix"); // 0.5
gd.addNumericField("Correlation weights (around maximum):", distortionParameters.correlationWeightSigma, 3,5,"nodes"); // 2.5
gd.addNumericField("Correlation radius scale (0 - sharp sigma)", distortionParameters.correlationRadiusScale, 1,3,"sigmas"); //2.0
gd.addNumericField("Correlation maximal radius to use", distortionParameters.correlationRadius, 0,1,"pix"); // 2.0
gd.addNumericField("Correlation maximum calculation threshold", distortionParameters.correlationThreshold*100, 2,5,"%"); // .8
gd.addNumericField("Interpolate correlation (FFT*linear)", distortionParameters.correlationSubdiv, 0,3,"x"); // 16
gd.addNumericField("Interpolate correlation with FFT", distortionParameters.correlationFFTSubdiv, 0,3,"x"); // 4
gd.addNumericField("Correlation dx (debug)", distortionParameters.correlationDx, 3);
gd.addNumericField("Correlation dy (debug)", distortionParameters.correlationDy, 3);
gd.addNumericField("Maximal size of the pattern grid (square)", distortionParameters.gridSize, 0);
gd.addCheckbox ("Refine correlations", distortionParameters.refineCorrelations);
gd.addCheckbox ("Use fast correlation on first pass", distortionParameters.fastCorrelationOnFirstPass);
gd.addCheckbox ("Use fast correlation on refine pass", distortionParameters.fastCorrelationOnFinalPass);
gd.addCheckbox ("Average correlation measurements between neighbors (on refine)", distortionParameters.correlationAverageOnRefine);
gd.addCheckbox ("Update coordinates of the grid points as they are recalculated (false - then update all at once)", distortionParameters.refineInPlace);
gd.addNumericField("Distance to ortho neighbors (for averaging)", distortionParameters.averageOrthoDist, 3,5,"sensor pix");
gd.addNumericField("Combined weight of ortho neighbors (fraction of 1.0)", distortionParameters.averageOrthoWeight, 3);
gd.addNumericField("Distance to diagonal neighbors (for averaging)", distortionParameters.averageDiagDist, 3,5,"sensor pix");
gd.addNumericField("Combined weight of diagonal neighbors (fraction of 1.0)", distortionParameters.averageDiagWeight, 3);
gd.addCheckbox ("Use quadratic extrapolation (false - force linear)", distortionParameters.useQuadratic);
gd.addCheckbox ("Remove outer (unreliable) layer before extrapolation", distortionParameters.removeLast);
gd.addNumericField("Number of extrapolated layers of nodes (final stage)", distortionParameters.numberExtrapolated, 0);
gd.addNumericField("Sigma during final extrapolation stage", distortionParameters.extrapolationSigma, 3,5,"nodes");
gd.addNumericField("Minimal UV span in correlation window to trigger FFT size increase", distortionParameters.minUVSpan, 3);
gd.addCheckbox ("Compensate uneven pattern intensity", distortionParameters.flatFieldCorrection);
gd.addNumericField("Extrapolate pattern intensity map (relative to pattern period)", distortionParameters.flatFieldExtarpolate, 3);
gd.addNumericField("Blur pattern intensity map (relative to pattern period)", distortionParameters.flatFieldBlur, 3);
gd.addNumericField("Do not use areas where intensity map is below this part of maximal", distortionParameters.flatFieldMin, 3);
gd.addNumericField("Shrink before extrapolating intensity map (relative to the average grid period)", distortionParameters.flatFieldShrink, 3);
gd.addNumericField("Expand during extrapolation (relative to the average grid period)", distortionParameters.flatFieldExpand, 3);
gd.addNumericField("Extrapolation weight effective radius (relative to the average grid period)", distortionParameters.flatFieldSigmaRadius, 3);
gd.addNumericField("Consider pixels in a square with the side twice this (relative to flatFieldSigmaRadius)", distortionParameters.flatFieldExtraRadius, 3);
gd.addNumericField("Multiply the average grid period to determine the area for averaging the grig brightness", distortionParameters.averagingAreaScale, 3);
gd.addCheckbox ("Legacy mode (deprecated)", distortionParameters.legacyMode);
gd.addNumericField("Debug level inside the loop", distortionParameters.loop_debug_level, 0);
gd.addNumericField("Debug Level:", MASTER_DEBUG_LEVEL, 0);
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
distortionParameters.FFTSize = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.FFTSize_lwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.FFTOverlap = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.FFTOverlap_lwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.fftGaussWidth= gd.getNextNumber();
distortionParameters.correlationSize = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.correlationSizeLwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.maximalCorrelationSize = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.maximalCorrelationSizeLwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.correlationGaussWidth= gd.getNextNumber();
distortionParameters.absoluteCorrelationGaussWidth=gd.getNextBoolean();
distortionParameters.zeros= (int) gd.getNextNumber();
distortionParameters.phaseCorrelationFraction= gd.getNextNumber();
distortionParameters.correlationHighPassSigma= gd.getNextNumber();
distortionParameters.correlationLowPassSigma= gd.getNextNumber();
distortionParameters.correlationMaxOffset= gd.getNextNumber();
distortionParameters.correlationRingWidth= gd.getNextNumber();
distortionParameters.correlationMinContrast= gd.getNextNumber();
distortionParameters.correlationMinInitialContrast= gd.getNextNumber();
distortionParameters.correlationMinAbsoluteContrast= gd.getNextNumber();
distortionParameters.correlationMinAbsoluteInitialContrast= gd.getNextNumber();
distortionParameters.scaleFirstPassContrast= gd.getNextNumber();
distortionParameters.contrastSelectSigmaCenter= gd.getNextNumber();
distortionParameters.contrastSelectSigma= gd.getNextNumber();
distortionParameters.contrastAverageSigma= gd.getNextNumber();
distortionParameters.minimalPatternCluster=(int) gd.getNextNumber();
distortionParameters.minimalPatternClusterLwir=(int) gd.getNextNumber();
distortionParameters.scaleMinimalInitialContrast=gd.getNextNumber();
distortionParameters.searchOverlap= gd.getNextNumber();
distortionParameters.patternSubdiv= (int) gd.getNextNumber();
distortionParameters.bPatternSigma= gd.getNextNumber();
distortionParameters.barraySigma= gd.getNextNumber();
distortionParameters.correlationWeightSigma= gd.getNextNumber();
distortionParameters.correlationRadiusScale= gd.getNextNumber();
distortionParameters.correlationRadius= (int) gd.getNextNumber();
distortionParameters.correlationThreshold= 0.01*gd.getNextNumber();
distortionParameters.correlationSubdiv= (int) gd.getNextNumber();
distortionParameters.correlationFFTSubdiv=1;
for (i=(int) gd.getNextNumber(); i >1; i>>=1) distortionParameters.correlationFFTSubdiv <<=1; /* make it to be power of 2 */
distortionParameters.correlationDx= gd.getNextNumber();
distortionParameters.correlationDy= gd.getNextNumber();
distortionParameters.gridSize= (int) gd.getNextNumber();
distortionParameters.refineCorrelations= gd.getNextBoolean();
distortionParameters.fastCorrelationOnFirstPass=gd.getNextBoolean();
distortionParameters.fastCorrelationOnFinalPass=gd.getNextBoolean();
distortionParameters.correlationAverageOnRefine=gd.getNextBoolean();
distortionParameters.refineInPlace= gd.getNextBoolean();
distortionParameters.averageOrthoDist= gd.getNextNumber();
distortionParameters.averageOrthoWeight= gd.getNextNumber();
distortionParameters.averageDiagDist= gd.getNextNumber();
distortionParameters.averageDiagWeight= gd.getNextNumber();
distortionParameters.useQuadratic= gd.getNextBoolean();
distortionParameters.removeLast= gd.getNextBoolean();
distortionParameters.numberExtrapolated=(int) gd.getNextNumber();
distortionParameters.extrapolationSigma= gd.getNextNumber();
distortionParameters.minUVSpan= gd.getNextNumber();
distortionParameters.flatFieldCorrection= gd.getNextBoolean();
distortionParameters.flatFieldExtarpolate= gd.getNextNumber();
distortionParameters.flatFieldBlur= gd.getNextNumber();
distortionParameters.flatFieldMin= gd.getNextNumber();
distortionParameters.flatFieldShrink= gd.getNextNumber();
distortionParameters.flatFieldExpand= gd.getNextNumber();
distortionParameters.flatFieldSigmaRadius= gd.getNextNumber();
distortionParameters.flatFieldExtraRadius= gd.getNextNumber();
distortionParameters.averagingAreaScale= gd.getNextNumber();
distortionParameters.legacyMode= gd.getNextBoolean();
distortionParameters.loop_debug_level= (int) gd.getNextNumber();
MASTER_DEBUG_LEVEL= (int) gd.getNextNumber();
return true;
}
private int makePowerOfTwo(int v) {
int v2 = 1;
for (int i=v; i > 1; i>>=1 ) v2 <<=1; /* make it to be power of 2 */
return v2;
int [] mdl = {MASTER_DEBUG_LEVEL};
if (distortionParameters.showDistortionDialog(mdl)) {
MASTER_DEBUG_LEVEL = mdl[0];
return true;
}
return false;
}
/* ======================================================================== */
/* ======================================================================== */
......@@ -96,6 +96,7 @@ import ij.text.TextWindow;
return (eyesisCameraParameters==null)?0:eyesisCameraParameters.getNumStations();
}
public double getPixelSize(int station, int channel) {
return this.eyesisCameraParameters.eyesisSubCameras[station][channel].getPixelSize();
}
......
......@@ -36,6 +36,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.SwingUtilities;
import com.elphel.imagej.calibration.DistortionCalibrationData.GridImageParameters;
import com.elphel.imagej.calibration.hardware.CamerasInterface;
import com.elphel.imagej.cameras.EyesisCameraParameters;
import com.elphel.imagej.cameras.EyesisSubCameraParameters;
......@@ -78,6 +79,7 @@ public class Distortions {
public double [] Y=null; // array of "y" - for each grid image, each defined grid node - 2 elements
public int [] imageStartIndex=null; // elements containing index of the start point of the selected image, first element 0, last - total number of points.
public double [] weightFunction=null; // array of weights for pixels (to fade values near borders), corresponding to Y array
public double [][] dTA_dUV = null; // null or double [2][2] to return averaged {{dU/dAz,dU/dTl}{dV/dAz,dV/dTl}}.inverse
public double sumWeights;
public double [][] targetXYZ=null; // array of target {x,y,z} matching each image each grid point
......@@ -175,7 +177,10 @@ public class Distortions {
}
public void setSensorHeight(int subCam, int v) {fittingStrategy.distortionCalibrationData.eyesisCameraParameters.setSensorHeight(subCam, v);}
public void setDecimateMasks(int subCam, int v){fittingStrategy.distortionCalibrationData.eyesisCameraParameters.setDecimateMasks(subCam, v);}
public double [][] getDtaDuv(){
return dTA_dUV;
}
public class LMAArrays {
......@@ -399,7 +404,7 @@ public class Distortions {
System.out.println("initFittingSeries("+justSelection+","+filter+","+numSeries+"), pass="+pass);
//TODO: ********* Implement comments above ************
// calculate total number of x/y pairs in the selected images
if (numSeries<0) justSelection=true;
if (numSeries <0 ) justSelection=true;
if ((pass==1) && (numSeries>=0)) fittingStrategy.invalidateSelectedImages(numSeries); // next selectedImages() will select all, including empty
if (!justSelection) {
fittingStrategy.buildParameterMap (numSeries); // also sets currentSeriesNumber
......@@ -615,6 +620,14 @@ public class Distortions {
if ((this.pixelCorrection==null) || (this.pixelCorrection[chnNum] == null)){
this.Y[2*index]= fittingStrategy.distortionCalibrationData.gIP[imgNum].pixelsXY[pointNumber][0];
this.Y[2*index+1]=fittingStrategy.distortionCalibrationData.gIP[imgNum].pixelsXY[pointNumber][1];
if (Double.isNaN(this.Y[2*index]) || Double.isNaN(this.Y[2*index+1])) {
System.out.println("Bug 1 in initFittingSeries(): NaN! distortionCalibrationData.gIP["+imgNum+"].pixelsXY["+pointNumber+"][0]="+
fittingStrategy.distortionCalibrationData.gIP[imgNum].pixelsXY[pointNumber][0]+
", distortionCalibrationData.gIP["+imgNum+"].pixelsXY["+pointNumber+"][1]="+
fittingStrategy.distortionCalibrationData.gIP[imgNum].pixelsXY[pointNumber][1]);
this.Y[2*index]= 0.0;
this.Y[2*index + 1]= 0.0;
}
} else {
// TODO: remove and use new code (if tested OK)
double [] pXY={
......@@ -632,6 +645,17 @@ public class Distortions {
} else {
this.Y[2*index]= pXY[0]-this.pixelCorrection[chnNum][0][indexXY]; //java.lang.ArrayIndexOutOfBoundsException: 3204663
this.Y[2*index+1]=pXY[1]-this.pixelCorrection[chnNum][1][indexXY];
if (Double.isNaN(this.Y[2*index]) || Double.isNaN(this.Y[2*index+1])) {
System.out.println("Bug 2 in initFittingSeries(): NaN! this.pixelCorrection["+chnNum+"][0]["+indexXY+"]="+
this.pixelCorrection[chnNum][0][indexXY]+
", this.pixelCorrection["+chnNum+"][1]["+indexXY+"]="+
this.pixelCorrection[chnNum][1][indexXY]+
", pXY[0]="+pXY[0]+", pXY[1]="+pXY[1]+
", imgNum="+imgNum+", pointNumber="+pointNumber);
this.Y[2*index]= 0.0;
this.Y[2*index + 1]= 0.0;
}
}
// TODO: remove above and un-comment below (after testing)
/*
......@@ -686,7 +710,7 @@ public class Distortions {
}
}
// Normalize set weights
int numSetsUsed=0;
int numSetsUsed=0+0;
double totalSetWeight=0.0;
for (int imgSet=0;imgSet<this.fittingStrategy.distortionCalibrationData.gIS.length;imgSet++){
if (this.fittingStrategy.distortionCalibrationData.gIS[imgSet].setWeight>0){
......@@ -703,7 +727,7 @@ public class Distortions {
}
}
}
// last? not here!
// last? not here! numSetsUsed counted twice (should be = 1, is 2)
// this.imageStartIndex[numImg]=index;
if (justSelection) {
this.currentVector = null;
......@@ -3327,14 +3351,20 @@ For each point in the image
System.out.println("Processing debug image "+numGridImage);
System.out.println("Processing debug image "+numGridImage);
}
*/
int set_number = dcd.gIP[numGridImage].getSetNumber();
if ((set_number >= start_set) &&
(set_number <= end_set) &&
(((imageNumber<0) ||
((imageNumber==numGridImage)) &&(processAll) ||
(((imageNumber<0) || ((imageNumber==numGridImage)) && (processAll) ||
(!dcd.gIP[numGridImage].enabled &&
((hintGridTolerance>0.0) || ((dcd.gIP[numGridImage].matchedPointers>0)) && !ignoreLaserPointers))))){ // skip no-pointers if only orientation is hinted
((hintGridTolerance>0.0) ||
((dcd.gIP[numGridImage].matchedPointers>0)) && !ignoreLaserPointers))))){ // skip no-pointers if only orientation is hinted
*/
int set_number = dcd.gIP[numGridImage].getSetNumber();
if ((set_number >= start_set) && (set_number <= end_set) && // correct set range
((imageNumber < 0) || (imageNumber==numGridImage)) && // either all images or selected image
(processAll || !dcd.gIP[numGridImage].enabled) && // "process all" (including disabled) or this is disabled
((hintGridTolerance > 0.0) || ((dcd.gIP[numGridImage].matchedPointers>0) && !ignoreLaserPointers)) // hint tolerance is provided, or there are lasers not disabled
){ // skip no-pointers if only orientation is hinted
if (((dcd.gIP[numGridImage].matchedPointers==0) || ignoreLaserPointers)&&
(dcd.gIS[dcd.get_gIS_index(numGridImage)].orientationEstimated)) {
if ( !processBlind) {
......@@ -3708,6 +3738,11 @@ For each point in the image
public void manualGridHint(int imgNumber) {
int [][] markers = getImageMarkers(imgNumber);
if ((markers != null) && (markers.length > 0)) {
if (markers.length > 1) {
System.out.println("This image has multiple point marks - please remove extra");
IJ.showMessage("This image has multiple point marks - please remove extra");
return;
}
double [][] xyuv = new double [markers.length][4];
for (int i =0; i < markers.length; i++) {
xyuv[i][0]=markers[i][0];
......@@ -3771,25 +3806,28 @@ For each point in the image
}
int ix0 = indx_best % width;
int iy0 = indx_best / width;
int half_range = 2; // was 1;
PolynomialApproximation polynomialApproximation =new PolynomialApproximation(0);// no debug
double [][][] data = new double[9][3][];
// double [][][] data = new double[9][3][];
double [][][] data = new double[(2*half_range+1)*(2*half_range+1)][3][];
int indx = 0;
for (int idy = -1; idy <=1; idy++) {
for (int idy = -half_range; idy <=half_range; idy++) {
int iy = iy0+idy;
for (int idx = -1; idx <=1; idx++) {
for (int idx = -half_range; idx <= half_range; idx++) {
int ix = ix0 + idx;
data[indx][0] = new double[2];
data[indx][1] = new double[2];
data[indx][2] = new double[1];
data[indx][0][0] = idx;
data[indx][0][1] = idy;
data[indx][2][0] = 0.0;
if ((ix >= 0) && (ix < width) && (iy >= 0) && (iy < height)) {
int offs = iy * width + ix;
data[indx][1][0] = pixels[0][offs] - xyuv[0][0];
data[indx][1][1] = pixels[1][offs] - xyuv[0][1];
data[indx][2][0] = 1.0;
} else {
data[indx][2][0] = 0.0;
if ((pixels[0][offs] >= 0) && (pixels[1][offs] >= 0)) {
data[indx][1][0] = pixels[0][offs] - xyuv[0][0];
data[indx][1][1] = pixels[1][offs] - xyuv[0][1];
data[indx][2][0] = 1.0;
}
}
indx++;
}
......@@ -5877,7 +5915,7 @@ List calibration
final double [][] patternXYZ, // this.targetXYZ
final double [] weightFunction, // may be null - make it twice smaller? - same for X and Y?
final LensDistortionParameters lensDistortionParametersProto,
// final double lambda,
final double [][] dTA_dUV, // null or double [][] to return averaged per-image {{dU/dAz,dU/dTl}{dV/dAz,dV/dTl}}
int threadsMax,
boolean updateStatus){
......@@ -5906,6 +5944,8 @@ List calibration
if (selectedImages[i]) selectedIndex++;
if (selectedIndex>=numSelectedImages) selectedIndex--;
}
final double [][][] dUV_image = (dTA_dUV != null) ? new double [selectedImages.length][][]: null;
final double [] dUV_weights = (dTA_dUV != null) ? new double [selectedImages.length]: null;
final AtomicInteger stopRequested=this.stopRequested;
final AtomicBoolean interruptedAtomic=new AtomicBoolean();
for (int ithread = 0; ithread < threads.length; ithread++) {
......@@ -5915,6 +5955,11 @@ List calibration
LensDistortionParameters lensDistortionParameters=lensDistortionParametersProto.clone(); // see - if that is needed - maybe new is OK
// LensDistortionParameters lensDistortionParameters= new LensDistortionParameters();
for (int numImage=imageNumberAtomic.getAndIncrement(); (numImage<selectedImages.length) && !interruptedAtomic.get();numImage=imageNumberAtomic.getAndIncrement()){
int length=2*(imageStartIndex[numImage+1]-imageStartIndex[numImage]);
if (length == 0) {
continue;
}
int start= 2*imageStartIndex[numImage];
double [][] partialJacobian= calculatePartialFxAndJacobian(
numImage, // number of grid image
vector, // parameters vector
......@@ -5924,8 +5969,8 @@ List calibration
lensDistortionParameters, // initialize one per each tread? Or for each call?
true); // when false, modifies only this.lensDistortionParameters.*
int length=2*(imageStartIndex[numImage+1]-imageStartIndex[numImage]);
int start= 2*imageStartIndex[numImage];
// int length=2*(imageStartIndex[numImage+1]-imageStartIndex[numImage]);
// int start= 2*imageStartIndex[numImage];
double [][] partialJtByJmod=new double [numPars][numPars]; // out of heap space
double [] partialJtByDiff=new double [numPars];
......@@ -5947,20 +5992,102 @@ List calibration
for (int i=0;i<numPars;i++) if (partialJacobian[i]!=null) {
partialJtByDiff[i]=0.0;
if (weightFunction!=null)
for (int k=0;k<length;k++) partialJtByDiff[i]+=partialJacobian[i][k]*partialDiff[k]*weightFunction[start+k];
for (int k=0;k<length;k++) {
if (Double.isNaN(partialDiff[k])) {
System.out.println("calculateJacobianArrays() BUG1:partialDiff["+k+"]=NaN, i="+i);
} else {
partialJtByDiff[i]+=partialJacobian[i][k]*partialDiff[k]*weightFunction[start+k];
}
}
else
for (int k=0;k<length;k++) partialJtByDiff[i]+=partialJacobian[i][k]*partialDiff[k];
for (int k=0;k<length;k++) {
if (Double.isNaN(partialDiff[k])) {
System.out.println("calculateJacobianArrays() BUG2:partialDiff["+k+"]=NaN, i="+i);
} else {
partialJtByDiff[i]+=partialJacobian[i][k]*partialDiff[k];
}
}
}
// wrong! fix it
/*
synchronized(this){
for (int i=0;i<numPars;i++) if (partialJacobian[i]!=null){
JtByDiff[i]+=partialJtByDiff[i];
for (int j=i;j<numPars;j++) JtByJmod[i][j]+=partialJtByJmod[i][j];
int par_gh = -1;
int par_ga = -1;
if (dUV_image != null) {
dUV_image[numImage] = null; //new double [2][2];
for (int i = 0; i < numPars; i++) {
int parNum=fittingStrategy.parameterMap[i][1];
if (parNum == fittingStrategy.distortionCalibrationData.index_gh) {
par_gh = i;
} else if (parNum == fittingStrategy.distortionCalibrationData.index_ga) {
par_ga = i;
}
}
if ((par_gh >= 0) && (par_ga >= 0)) { // both defined
// partialJacobian[par_gh][2*k ] dPx/dGh
// partialJacobian[par_gh][2*k+1] dPy/dGh
// partialJacobian[par_gh][2*k ] dPx/dGa
// partialJacobian[par_gh][2*k+1] dPy/dGa
// d3780: public void updateGridToPointer(ImagePlus imp_grid, double[][] xyuv) {
// find average dX/dU, dY/dU, dX/dV, dY/dV
PolynomialApproximation polynomialApproximation =new PolynomialApproximation(0);// no debug
GridImageParameters gip = fittingStrategy.distortionCalibrationData.gIP[numImage];
int np = gip.pixelsXY.length;
double wsx=0.0, wsy=0.0, ws_dpx_dgh= 0.0, ws_dpy_dgh= 0.0, ws_dpx_dga= 0.0, ws_dpy_dga= 0.0;
for (int k = 0; k < length; k+=1) {
double w = (weightFunction!=null)? weightFunction[start+k] : 1.0;
wsx += w;
ws_dpx_dgh += w * partialJacobian[par_gh][k];
ws_dpx_dga += w * partialJacobian[par_ga][k];
k++;
w = (weightFunction!=null)? weightFunction[start+k] : 1.0;
wsy += w;
ws_dpy_dgh += w * partialJacobian[par_gh][k];
ws_dpy_dga += w * partialJacobian[par_ga][k];
}
if ((wsx == 0.0) || (wsy == 0.0)) {
if (debugLevel>2) {
System.out.println("Not enough data for dpx/dgh, dpy/dgh, dpx/dga, dpy/dga for image #"+numImage);
}
continue;
}
ws_dpx_dgh /= wsx;
ws_dpx_dga /= wsx;
ws_dpy_dgh /= wsy;
ws_dpy_dga /= wsy;
Matrix mXY_HA = new Matrix(new double[][] {{ws_dpx_dgh, ws_dpx_dga},{ws_dpy_dgh, ws_dpy_dga}});
double [][][] data = new double[np][3][];
for (int indx = 0; indx < np; indx++) {
data[indx][0] = new double[2];
data[indx][1] = new double[2];
data[indx][2] = new double[1];
data[indx][0][0] = gip.pixelsUV[indx][0]; // U
data[indx][0][1] = gip.pixelsUV[indx][1]; // V
data[indx][1][0] = gip.pixelsXY[indx][0]; // pX
data[indx][1][1] = gip.pixelsXY[indx][1]; // pY
data[indx][2][0] = gip.pixelsMask[indx]; // weighth
}
double [][] coeff = polynomialApproximation.quadraticApproximation(
data,
true); // force linear
Matrix mXY_UV=new Matrix(new double[][] {{coeff[0][0],coeff[0][1]},{coeff[1][0],coeff[1][1]}});
if (!(new LUDecomposition(mXY_UV)).isNonsingular()){
if (debugLevel>2) {
System.out.println("Skipping singular matrix for image #"+numImage);
}
continue;
}
Matrix mUV_XY= mXY_UV.inverse();
Matrix mUV_HA = mUV_XY.times(mXY_HA);
dUV_image [numImage] = mUV_HA.getArray();
dUV_weights[numImage] = wsx + wsy;
} else {
System.out.println ("Bug: ga/gh are not among the parameters, par_gh="+par_gh+", par_ga="+par_ga);
}
}
*/
synchronizedCombinePartialJacobians(
JtByJmod, //Transposed Jacobian multiplied by Jacobian
JtByDiff,
......@@ -5970,7 +6097,6 @@ List calibration
numPars );
final int numFinished=imageFinishedAtomic.getAndIncrement();
// IJ.showProgress(progressValues[numFinished]);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
......@@ -5983,8 +6109,6 @@ List calibration
if (stopRequested.get()==1){ // ASAP
interruptedAtomic.set(true);
}
// if (debugLevel>1) System.out.println("IJ.showProgress("+progressValues[numImage]+")");
// if (debugLevel>1) IJ.showStatus("Progress "+IJ.d2s(100*progressValues[numImage],2)+"%");
}
}
};
......@@ -6009,10 +6133,31 @@ List calibration
lMAArrays.jTByDiff=JtByDiff;
if (debugLevel>3){
String msg="calculateJacobianArrays() lMAArrays.jTByJ trace=";
for (int ii=0;ii<numPars;ii++) msg+=IJ.d2s(lMAArrays.jTByJ[ii][ii],5);
for (int ii=0;ii<numPars;ii++) msg+=IJ.d2s(lMAArrays.jTByJ[ii][ii],5)+" ";
System.out.println(msg);
}
if (dTA_dUV != null) {
double [][] dUV_average = new double [2][2];
for (int i = 0; i < 2; i++) for (int j=0; j<2; j++) dUV_average[i][j] = 0.0;
double sw = 0.0;
for (int ni = 0; ni < dUV_weights.length; ni++) {
double w = dUV_weights[ni];
if (w > 0.0) {
for (int i = 0; i < 2; i++) for (int j=0; j<2; j++) {
dUV_average[i][j] += w *dUV_image[ni][i][j] ;
}
sw += w;
}
}
if (sw > 0) {
for (int i = 0; i < 2; i++) for (int j=0; j<2; j++) {
dUV_average[i][j] /= sw;
}
Matrix mdTA_dUV = (new Matrix(dUV_average)).inverse();
this.dTA_dUV = mdTA_dUV.getArray();
}
}
return lMAArrays;
}
......@@ -6052,7 +6197,7 @@ List calibration
M.print(10, 5);
}
Matrix Mb=new Matrix(lMAArrays.jTByDiff,numPars); // single column
Matrix Mb=new Matrix(lMAArrays.jTByDiff,numPars); // single column {NaN,NaN}
if (!(new LUDecomposition(M)).isNonsingular()){
double [][] arr=M.getArray();
System.out.println("Singular Matrix "+arr.length+"x"+arr[0].length);
......@@ -6081,9 +6226,11 @@ List calibration
* @param numSeries
* @return array of two booleans: { improved, finished}
*/
public boolean [] stepLevenbergMarquardtFirst(int numSeries){
public boolean [] stepLevenbergMarquardtFirst(
int numSeries,
boolean calc_dUV){
double [] deltas=null;
if (this.currentVector==null) {
if ((this.currentVector==null) || (this.currentVector.length==0)) { // length==0 was debugging
int filter=this.filterForAll;
if (this.askFilter) filter=selectFilter(filter);
initFittingSeries(false,filter,numSeries); // first step in series
......@@ -6108,11 +6255,12 @@ List calibration
// IJ.showStatus(this.seriesNumber+": "+"Step #"+this.iterationStepNumber+" RMS="+IJ.d2s(this.currentRMS,8)+ " ("+IJ.d2s(this.firstRMS,8)+")");
IJ.showStatus(this.seriesNumber+": initial Jacobian matrix calculation. Points:"+this.Y.length+" Parameters:"+this.currentVector.length);
}
if (this.debugLevel>1) {
if (this.debugLevel >1) {
System.out.println(this.seriesNumber+": initial Jacobian matrix calculation. Points:"+this.Y.length+" Parameters:"+this.currentVector.length);
}
if (this.threadedLMA) {
this.currentfX=new double[this.Y.length];
this.dTA_dUV = calc_dUV ? (new double [2][2]): null;
// deltas=solveLevenbergMarquardtThreaded(
this.lMAArrays=calculateJacobianArrays(
this.fittingStrategy.selectedImages(), // selected images to process
......@@ -6123,6 +6271,7 @@ List calibration
this.targetXYZ, // this.targetXYZ
this.weightFunction, // may be null - make it twice smaller? - same for X and Y?
this.lensDistortionParameters,
this.dTA_dUV,// final double [][][] dUV_average, // null or double [selectedImages.length][][] to return per-image {{dU/dAz,dU/dTl}{dV/dAz,dV/dTl}}
// this.lambda,
this.threadsMax,
this.updateStatus);
......@@ -6135,7 +6284,7 @@ List calibration
// deltas=solveLevenbergMarquardt(this.currentfX,this.lambda);
}
// add termes that push selected extrinsic parameters towards average (global, per station, per tilt-station)
this.currentRMSPure= calcErrorDiffY(this.currentfX);
this.currentRMSPure= calcErrorDiffY(this.currentfX) +0.0;
if ((this.fittingStrategy.varianceModes!=null) && (this.fittingStrategy.varianceModes[numSeries]!=this.fittingStrategy.varianceModeDisabled)) {
this.fittingStrategy.addVarianceToLMA(
numSeries,
......@@ -6238,6 +6387,7 @@ List calibration
this.targetXYZ, // this.targetXYZ
this.weightFunction, // may be null - make it twice smaller? - same for X and Y?
this.lensDistortionParameters,
this.dTA_dUV,// final double [][][] dUV_average, // null or double [selectedImages.length][][] to return per-image {{dU/dAz,dU/dTl}{dV/dAz,dV/dTl}}
// this.lambda,
this.threadsMax,
this.updateStatus);
......@@ -6719,7 +6869,7 @@ List calibration
/// this.pixelCorrectionHeight=height;
// }
if (this.pixelCorrection==null) {
if (this.debugLevel>1) System.out.println("Initializing pixelCorrection array");
if (this.debugLevel>1) System.out.println("Initializing pixelCorrection array...");
this.pixelCorrection=new double [sensorXYCorr.length][][];
this.pathNames=new String[sensorXYCorr.length];
for (int i=0;i<this.pixelCorrection.length;i++){
......@@ -6775,8 +6925,15 @@ List calibration
this.pixelCorrection[i][5]=sensorXYCorr[i][indxB];
} else {
for (int n=3;n<numLayers;n++){
this.pixelCorrection[i][n]=new double[this.pixelCorrection[0].length];
for (int j=0;j<this.pixelCorrection[i][0].length;j++) this.pixelCorrection[i][n][j]=1.0;
// this.pixelCorrection[i][n]=new double[this.pixelCorrection[0].length];
this.pixelCorrection[i][n]=new double[this.pixelCorrection[i][0].length]; // number of pixels
for (int j=0;j<this.pixelCorrection[i][0].length;j++) {
if ((i >= pixelCorrection.length) || (n >= pixelCorrection[i].length) || (j >= pixelCorrection[i][n].length)){
System.out.println("i="+i+", n="+n+", j="+j);
continue;
}
this.pixelCorrection[i][n][j]=1.0; // java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 6
}
}
}
......@@ -6910,7 +7067,15 @@ List calibration
float [][]pixels=new float [titles.length][length]; // dx, dy, sensor mask,v-r,v-g,v-b
// assuming all sensors have the same dimension
double [] mask=null;
if (distortionCalibrationData.sensorMasks.length<=numSensor) return null; // no data
if (distortionCalibrationData.sensorMasks == null) {
if (this.debugLevel>0) {
System.out.println("sensorMasks are null, calculating");
}
distortionCalibrationData.calculateSensorMasks();
}
if (distortionCalibrationData.sensorMasks.length<=numSensor) return null; // no data (make if distortionCalibrationData.sensorMasks==null
if ((distortionCalibrationData.sensorMasks!=null) &&
(distortionCalibrationData.sensorMasks[numSensor]!=null)){
mask=distortionCalibrationData.sensorMasks[numSensor];
......@@ -6924,7 +7089,15 @@ List calibration
} else {
pixels[0][index]= (float) pixelCorr[0][index];
pixels[1][index]= (float) pixelCorr[1][index];
for (int n=3;n<pixels.length;n++) pixels[n][index]= (float) pixelCorr[n][index];
for (int n=3;n<pixels.length;n++) {
if (pixelCorr[n] != null) {
if ((n>=pixels.length) || (index >= pixels[n].length) || (n>=pixelCorr.length) || (index >= pixelCorr[n].length)) {
System.out.println (" Bug: n="+n+", index="+index);
continue;
}
pixels[n][index]= (float) pixelCorr[n][index]; // java.lang.NullPointerException
}
}
}
// get sensor mask here
pixels[2][index]= (mask==null)? 1.0f:((float) mask[index]);
......@@ -8273,11 +8446,20 @@ List calibration
return true;
}
public boolean LevenbergMarquardt(
boolean openDialog,
boolean dry_run){ // do not save results
return LevenbergMarquardt(
openDialog,
dry_run,
false);
}
public boolean LevenbergMarquardt(
boolean openDialog,
boolean dry_run, // do not save results
boolean calc_dUV){
if (this.fittingStrategy==null) {
String msg="Fitting strategy does not exist, exiting";
IJ.showMessage("Error",msg);
......@@ -8294,7 +8476,7 @@ List calibration
boolean wasLastSeries=false;
while (true) { // loop for the same series
boolean [] state=stepLevenbergMarquardtFirst(this.seriesNumber);
boolean [] state=stepLevenbergMarquardtFirst(this.seriesNumber, calc_dUV);
if (!this.fittingStrategy.isSeriesValid(this.seriesNumber)){
System.out.println("Series "+this.seriesNumber+" is invalid when weight function filters are applied (probably removed some images)");
return false;
......
......@@ -1248,10 +1248,16 @@ public class EyesisAberrations {
if (debugLevel>0) System.out.println("Processing file #"+(imgNum+1)+ " ( of "+files.length+") :"+files[imgNum][0]);
ImagePlus imp=new ImagePlus(files[imgNum][0]); // read source file
JP4_INSTANCE.decodeProperiesFromInfo(imp);
boolean is_lwir = lwirReaderParameters.is_LWIR(imp);
int fft_size = is_lwir ? distortionParameters.FFTSize_lwir : distortionParameters.FFTSize;
int fft_overlap = is_lwir ? distortionParameters.FFTOverlap_lwir : distortionParameters.FFTOverlap;
imp.setProperty("MONOCHROME",""+is_lwir);
// boolean is_lwir = lwirReaderParameters.is_LWIR(imp);
int sensor_type = LwirReaderParameters.sensorType(imp);
// int fft_size = is_lwir ? distortionParameters.FFTSize_lwir : distortionParameters.FFTSize;
// int fft_overlap = is_lwir ? distortionParameters.FFTOverlap_lwir : distortionParameters.FFTOverlap;
int fft_size = distortionParameters.getFFTSize(sensor_type);
int fft_overlap = distortionParameters.getFFTOverlap(sensor_type);
imp.setProperty("MONOCHROME",""+(sensor_type == 1));
// pad image to full sensor size
int numGridImage=fileIndices[imgNum];
int chn = distortions.fittingStrategy.distortionCalibrationData.gIP[numGridImage].getChannel();
......@@ -1261,7 +1267,8 @@ public class EyesisAberrations {
sensor_width_height, // eyesisCorrections.pixelMapping.sensors[srcChannel].getSensorWH(),
true); // boolean replicate);
// TODO: Add vignetting correction ?
MatchSimulatedPattern matchSimulatedPattern= new MatchSimulatedPattern(distortionParameters.FFTSize);
// MatchSimulatedPattern matchSimulatedPattern= new MatchSimulatedPattern(distortionParameters.FFTSize);
MatchSimulatedPattern matchSimulatedPattern= new MatchSimulatedPattern(distortionParameters.getFFTSize(sensor_type));
boolean [] correlationSizesUsed=null;
float [][] simArray= null;
......@@ -1348,7 +1355,7 @@ public class EyesisAberrations {
fft_size, // FFT_SIZE, // int fft_size,
colorComponents, //COMPONENTS, // ColorComponents colorComponents,
PSF_subpixel, //PSF_SUBPIXEL, // int PSF_subpixel,
(is_lwir?otfFilterParameters_lwir:otfFilterParameters),
((sensor_type == 1) ?otfFilterParameters_lwir:otfFilterParameters),
// otfFilterParameters, // OTF_FILTER, // OTFFilterParameters otfFilterParameters,
psfParameters, //PSF_PARS, // final PSFParameters psfParameters
psfParameters.minDefinedArea , //PSF_PARS.minDefinedArea, // final double minDefinedArea,
......
......@@ -632,6 +632,9 @@ horizontal axis:
int nImg=indices[index];
int subCam= distortionCalibrationData.getImageChannel(images[nImg]);
int sensor_type = eyesisCameraParameters.getSensorType(subCam);
// int stationNumber= distortionCalibrationData.getImageStation(numGridImage), // station number
double timeStamp= distortionCalibrationData.getImageTimestamp(images[nImg]);
......@@ -673,7 +676,9 @@ horizontal axis:
if (this.debugLevel>1) lensDistortions.showHintGrid(hintGrid);
MatchSimulatedPattern matchSimulatedPattern = new MatchSimulatedPattern(this.distortionParametersDefault.FFTSize); // new instance, all reset
/// MatchSimulatedPattern matchSimulatedPattern = new MatchSimulatedPattern(this.distortionParametersDefault.FFTSize); // new instance, all reset
MatchSimulatedPattern matchSimulatedPattern = new MatchSimulatedPattern(distortionParametersDefault.getFFTSize(sensor_type)); // new instance, all reset
//sensort_type
// next 2 lines are not needed for the new instance, but can be
// used alternatively if keeping it
matchSimulatedPattern.invalidateFlatFieldForGrid(); // Reset Flat Filed calibration - different image.
......@@ -690,7 +695,7 @@ horizontal axis:
", initial number of pointers was "+numPointers);
}
//matchSimulatedPatterns[numSensor].getChannel(images[numSensor])+" ");
MatchSimulatedPattern.DistortionParameters distortionParameters = modifyDistortionParameters();
MatchSimulatedPattern.DistortionParameters distortionParameters = modifyDistortionParameters(sensor_type);
SimulationPattern.SimulParameters simulParameters = modifySimulParameters();
boolean noMessageBoxes=true;
......@@ -729,34 +734,13 @@ horizontal axis:
}
/*
* private showDoubleFloatArrays SDFA_INSTANCE= new showDoubleFloatArrays(); // just for debugging?
this.SDFA_INSTANCE.showArrays(gridXYZCorr, getGridWidth(), getGridHeight(), true, "Grid corrections", titles);
*
gd.addChoice( // ArrayIndexOutOfBoundsException: 21
this.distortionCalibrationData.getParameterName(parIndex)+
" ("+sValue+" "+
this.distortionCalibrationData.getParameterUnits(parIndex)+")"+
(this.distortionCalibrationData.isSubcameraParameter(parIndex)?(" s"+subCam):"com "),
this.definedModes, this.definedModes[this.parameterMode[numSeries][i]]);
*
* this.parameterMode[numSeries][i]=gd.getNextChoiceIndex();
PatternParameters patternParameters, // should not be null
boolean equalizeGreens,
int threadsMax,
boolean updateStatus,
int debug_level) {// debug level used inside loops
*
*
*/
public MatchSimulatedPattern.DistortionParameters modifyDistortionParameters(){
public MatchSimulatedPattern.DistortionParameters modifyDistortionParameters(int sensor_type){
MatchSimulatedPattern.DistortionParameters distortionParameters = this.distortionParametersDefault.clone();
distortionParameters.refineInPlace = false;
distortionParameters.correlationMaxOffset = this.goniometerParameters.maxCorr;
distortionParameters.correlationSize = this.goniometerParameters.correlationSize;
// distortionParameters.correlationSize = this.goniometerParameters.correlationSize;
distortionParameters.setCorrelationSize(this.goniometerParameters.correlationSize, sensor_type);
distortionParameters.correlationGaussWidth = this.goniometerParameters.correlationGaussWidth;
distortionParameters.refineCorrelations = false;
distortionParameters.fastCorrelationOnFirstPass = true;
......@@ -767,7 +751,8 @@ horizontal axis:
distortionParameters.flatFieldExpand = this.goniometerParameters.flatFieldExpand;
distortionParameters.numberExtrapolated = 1; // measuring distortions -
distortionParameters.correlationMinInitialContrast=this.goniometerParameters.correlationMinInitialContrast;
distortionParameters.minimalPatternCluster=this.goniometerParameters.minimalPatternCluster;
// distortionParameters.minimalPatternCluster=this.goniometerParameters.minimalPatternCluster;
distortionParameters.setMinimalPatternCluster(this.goniometerParameters.minimalPatternCluster, sensor_type);
distortionParameters.scaleMinimalInitialContrast=this.goniometerParameters.scaleMinimalInitialContrast;
distortionParameters.searchOverlap=this.goniometerParameters.searchOverlap;
return distortionParameters;
......@@ -781,7 +766,7 @@ horizontal axis:
return simulParameters;
}
public double[] estimateOrientation(
public double[] estimateOrientation( // FIXME: Does not use LWIR parameters, assumes EO!
ImagePlus[] images, // last acquire images with number of pointers
// detected>0
DistortionCalibrationData distortionCalibrationData,
......@@ -792,6 +777,7 @@ horizontal axis:
int threadsMax,
boolean updateStatus,
int debug_level) {// debug level used inside loops
int sensor_type = 0; // EO
long startTime = System.nanoTime();
if (lensDistortions == null) {
String msg = "lensDistortions is not initialized";
......@@ -801,7 +787,7 @@ horizontal axis:
// remove unneeded, copied from updateFocusGrid() Now it is not needed?
SimulationPattern.SimulParameters simulParameters = modifySimulParameters();
MatchSimulatedPattern.DistortionParameters distortionParameters = modifyDistortionParameters();
MatchSimulatedPattern.DistortionParameters distortionParameters = modifyDistortionParameters(sensor_type);
int numImages = 0;
for (int i = 0; i < images.length; i++)
......@@ -834,8 +820,8 @@ horizontal axis:
for (int numSensor = 0; numSensor < images.length; numSensor++)
if (images[numSensor] != null) {
// reset matchSimulatedPattern, so it will start from scratch
this.matchSimulatedPatterns[numSensor] = new MatchSimulatedPattern(
this.distortionParametersDefault.FFTSize); // new instance, all reset
// this.matchSimulatedPatterns[numSensor] = new MatchSimulatedPattern( this.distortionParametersDefault.FFTSize); // new instance, all reset
this.matchSimulatedPatterns[numSensor] = new MatchSimulatedPattern(distortionParametersDefault.getFFTSize(sensor_type)); // new instance, all reset
// next 2 lines are not needed for the new instance, but can be
// used alternatively if keeping it
this.matchSimulatedPatterns[numSensor].invalidateFlatFieldForGrid(); // Reset Flat Filed calibration - different image.
......
......@@ -63,8 +63,9 @@ public class LensAdjustment {
distortionParameters.refineInPlace=false;
distortionParameters.correlationMaxOffset=focusMeasurementParameters.maxCorr;
distortionParameters.correlationSize=focusMeasurementParameters.correlationSize;
int sensor_type = 0; // EO
// distortionParameters.correlationSize=focusMeasurementParameters.correlationSize;
distortionParameters.setCorrelationSize(focusMeasurementParameters.correlationSize,sensor_type);
distortionParameters.correlationGaussWidth=focusMeasurementParameters.correlationGaussWidth;
distortionParameters.refineCorrelations=false;
distortionParameters.fastCorrelationOnFirstPass=true;
......
......@@ -43,6 +43,7 @@ import com.elphel.imagej.common.DoubleFHT;
import com.elphel.imagej.common.DoubleGaussianBlur;
import com.elphel.imagej.common.PolynomialApproximation;
import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.common.WindowTools;
import com.elphel.imagej.jp4.JP46_Reader_camera;
import com.elphel.imagej.lwir.LwirReaderParameters;
......@@ -51,6 +52,7 @@ import Jama.Matrix; // Download here: http://math.nist.gov/javanumerics/jama/
import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.gui.GenericDialog;
import ij.gui.PointRoi;
import ij.gui.Roi;
import ij.process.FHT; // get rid, change to double
......@@ -100,6 +102,10 @@ public class MatchSimulatedPattern {
public MatchSimulatedPattern() {
}
// public MatchSimulatedPattern(int fft_size) {
// this.FFT_SIZE = fft_size;
// }
public MatchSimulatedPattern(int fft_size) {
this.FFT_SIZE = fft_size;
}
......@@ -3409,16 +3415,19 @@ public class MatchSimulatedPattern {
/*
* ============================= Distortions ===================================
*/
public void distortionsTest(final DistortionParameters distortionParameters, //
public void distortionsTest(
final DistortionParameters distortionParameters, //
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
final SimulationPattern.SimulParameters simulParameters, final boolean equalizeGreens, final ImagePlus imp, // image
// to
// process
final int threadsMax, final boolean updateStatus, final int debug_level) {// debug level used inside loops
final SimulationPattern.SimulParameters simulParameters,
final boolean equalizeGreens,
final ImagePlus imp, // image to process
final int threadsMax,
final boolean updateStatus,
final int debug_level) {// debug level used inside loops
if (imp == null)
return;
final int sensor_type = LwirReaderParameters.sensorType(imp);
Roi roi = imp.getRoi();
final Rectangle selection;
if (roi == null) {
......@@ -3427,10 +3436,10 @@ public class MatchSimulatedPattern {
selection = (roi instanceof PointRoi) ? (new Rectangle(0, 0, imp.getWidth(), imp.getHeight()))
: roi.getBounds();
}
MatchSimulatedPattern matchSimulatedPattern = new MatchSimulatedPattern(distortionParameters.FFTSize);
MatchSimulatedPattern matchSimulatedPattern = new MatchSimulatedPattern(distortionParameters.getFFTSize(sensor_type));
matchSimulatedPattern.debugLevel = debugLevel;
MatchSimulatedPattern matchSimulatedPatternCorr = new MatchSimulatedPattern(
distortionParameters.correlationSize);
distortionParameters.getCorrelationSize(sensor_type));
matchSimulatedPatternCorr.debugLevel = debugLevel;
final SimulationPattern.SimulParameters thisSimulParameters = simulParameters.clone();
thisSimulParameters.subdiv = distortionParameters.patternSubdiv;
......@@ -3452,12 +3461,12 @@ public class MatchSimulatedPattern {
if (debugLevel > 2)
SDFA_INSTANCE.showArrays(input_bayer, true, "selection-bayer-distortionsTest");
double[] windowFunction = initWindowFunction(distortionParameters.FFTSize, distortionParameters.fftGaussWidth);
final double[] windowFunctionCorr = initWindowFunction(distortionParameters.correlationSize,
final double[] windowFunctionCorr = initWindowFunction(distortionParameters.getCorrelationSize(sensor_type),
distortionParameters.correlationGaussWidth, distortionParameters.zeros);
double[] greens = normalizeAndWindow(input_bayer[4], windowFunction);
double[][] pattern = matchSimulatedPattern.findPattern(null, // DoubleFHT doubleFHT,
greens, distortionParameters.FFTSize, patternDetectParameters,
greens, distortionParameters.getFFTSize(sensor_type), patternDetectParameters,
patternDetectParameters.minGridPeriod / 2, patternDetectParameters.maxGridPeriod / 2, true, // this is a
// pattern
// for
......@@ -3906,14 +3915,22 @@ public class MatchSimulatedPattern {
if (imp == null)
return 0;
final int debugThreshold = 1;
final boolean is_lwir = ((lwirReaderParameters != null) && lwirReaderParameters.is_LWIR(imp));
final int fft_size = is_lwir ? distortionParameters.FFTSize_lwir : distortionParameters.FFTSize;
final int correlation_size = is_lwir ? distortionParameters.correlationSizeLwir
: distortionParameters.correlationSize;
final int max_correlation_size = is_lwir ? distortionParameters.maximalCorrelationSizeLwir
: distortionParameters.maximalCorrelationSize;
final int minimal_pattern_cluster = is_lwir ? distortionParameters.minimalPatternClusterLwir
: distortionParameters.minimalPatternCluster;
// final boolean is_lwir = ((lwirReaderParameters != null) && lwirReaderParameters.is_LWIR(imp));
// final int fft_size = is_lwir ? distortionParameters.FFTSize_lwir : distortionParameters.FFTSize;
// final int correlation_size = is_lwir ? distortionParameters.correlationSizeLwir
// : distortionParameters.correlationSize;
// final int max_correlation_size = is_lwir ? distortionParameters.maximalCorrelationSizeLwir
// : distortionParameters.maximalCorrelationSize;
// final int minimal_pattern_cluster = is_lwir ? distortionParameters.minimalPatternClusterLwir
// : distortionParameters.minimalPatternCluster;
final int sensor_type = LwirReaderParameters.sensorType(imp);
final int fft_size = distortionParameters.getFFTSize(sensor_type);
final int correlation_size = distortionParameters.getCorrelationSize(sensor_type);
// final int max_correlation_size = distortionParameters.getMaximalCorrelationSize(sensor_type);
final int minimal_pattern_cluster = distortionParameters.getMinimalPatternCluster(sensor_type);
final int[][] directionsUV = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } }; // should have opposite direction
// shifted by half
final int[][] directionsUV8 = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 1 }, { -1, 1 }, { -1, -1 },
......@@ -4329,8 +4346,8 @@ public class MatchSimulatedPattern {
@Override
public void run() {
SimulationPattern simulationPattern = new SimulationPattern(bPattern);
MatchSimulatedPattern matchSimulatedPatternCorr = new MatchSimulatedPattern(
distortionParameters.correlationSize);
MatchSimulatedPattern matchSimulatedPatternCorr = new MatchSimulatedPattern(correlation_size);
// distortionParameters.correlationSize);
DoubleFHT fht_instance = new DoubleFHT(); // provide DoubleFHT instance to save on
// initializations (or null)
String dbgStr = "";
......@@ -4770,7 +4787,7 @@ public class MatchSimulatedPattern {
// return numDefinedCells;
}
if (roi != null) { // don't use this feature with ROI as it can be small
if ((roi != null) && !(roi instanceof PointRoi)) { // don't use this feature with ROI as it can be small
if (global_debug_level > 0)
System.out.println(
"Initial pattern cluster is small (" + numDefinedCells + "), but ROI is set - no retries");
......@@ -5048,45 +5065,37 @@ public class MatchSimulatedPattern {
}
/* ================================================================ */
public double refineDistortionCorrelation(final LwirReaderParameters lwirReaderParameters, // null is OK
public double refineDistortionCorrelation(
final LwirReaderParameters lwirReaderParameters, // null is OK
final DistortionParameters distortionParameters, //
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
final SimulationPattern.SimulParameters simulParameters, final boolean equalizeGreens, final ImagePlus imp, // image
// to
// process
final SimulationPattern.SimulParameters simulParameters,
final boolean equalizeGreens,
final ImagePlus imp, // image to process
final double maxCorr, // maximal allowed correction, in pixels (0.0) - any
final int threadsMax, final boolean updateStatus, final int debug_level) {// debug level used inside loops
final int threadsMax,
final boolean updateStatus,
final int debug_level) {// debug level used inside loops
scaleContrast(distortionParameters.scaleFirstPassContrast);
final int sensor_type = LwirReaderParameters.sensorType(imp);
final double[][][][] patternGrid = this.PATTERN_GRID;
final int debugThreshold = 1;
final Rectangle selection = new Rectangle(0, 0, imp.getWidth(), imp.getHeight());
MatchSimulatedPattern matchSimulatedPatternCorr = new MatchSimulatedPattern(
distortionParameters.correlationSize);
final int correlation_size = distortionParameters.getCorrelationSize(sensor_type);
MatchSimulatedPattern matchSimulatedPatternCorr = new MatchSimulatedPattern(correlation_size);
// distortionParameters.correlationSize);
matchSimulatedPatternCorr.debugLevel = debugLevel;
SimulationPattern simulationPattern = new SimulationPattern();
final SimulationPattern.SimulParameters thisSimulParameters = simulParameters.clone();
thisSimulParameters.subdiv = distortionParameters.patternSubdiv;
final double[] bPattern = simulationPattern.patternGenerator(simulParameters); // reuse pattern for next time
/*
* final double [] windowFunctionCorr= initWindowFunction(
* distortionParameters.correlationSize,distortionParameters.
* correlationGaussWidth); final double []
* windowFunctionCorr2=initWindowFunction(2*distortionParameters.
* correlationSize,
* (distortionParameters.absoluteCorrelationGaussWidth?0.5:1.0)*
* distortionParameters.correlationGaussWidth); final double []
* windowFunctionCorr4=initWindowFunction(4*distortionParameters.
* correlationSize,
* (distortionParameters.absoluteCorrelationGaussWidth?0.25:1.0)*
* distortionParameters.correlationGaussWidth);
*/
final double[] windowFunctionCorr = initWindowFunction(distortionParameters.correlationSize,
final double[] windowFunctionCorr = initWindowFunction(correlation_size, // distortionParameters.correlationSize,
distortionParameters.correlationGaussWidth, distortionParameters.zeros);
final double[] windowFunctionCorr2 = initWindowFunction(2 * distortionParameters.correlationSize,
final double[] windowFunctionCorr2 = initWindowFunction(2 * correlation_size, // distortionParameters.correlationSize,
(distortionParameters.absoluteCorrelationGaussWidth ? 0.5 : 1.0)
* distortionParameters.correlationGaussWidth,
distortionParameters.zeros);
final double[] windowFunctionCorr4 = initWindowFunction(4 * distortionParameters.correlationSize,
final double[] windowFunctionCorr4 = initWindowFunction(4 * correlation_size, // distortionParameters.correlationSize,
(distortionParameters.absoluteCorrelationGaussWidth ? 0.25 : 1.0)
* distortionParameters.correlationGaussWidth,
distortionParameters.zeros);
......@@ -5161,8 +5170,7 @@ public class MatchSimulatedPattern {
@Override
public void run() {
SimulationPattern simulationPattern = new SimulationPattern(bPattern);
MatchSimulatedPattern matchSimulatedPatternCorr = new MatchSimulatedPattern(
distortionParameters.correlationSize);
MatchSimulatedPattern matchSimulatedPatternCorr = new MatchSimulatedPattern(correlation_size); // distortionParameters.correlationSize);
DoubleFHT fht_instance = new DoubleFHT(); // provide DoubleFHT instance to save on initializations
// (or null)
int[] iUV = new int[2];
......@@ -5190,7 +5198,7 @@ public class MatchSimulatedPattern {
// of the
// pattern cross
// point
distortionParameters.correlationSize);
correlation_size/2); // distortionParameters.correlationSize);
if (!selection.contains(centerCross)) {
cellNumDoneAtomic.getAndIncrement();
continue; // the correlation selection does not fit into WOI selection ??? WOI is now full
......@@ -5275,23 +5283,24 @@ public class MatchSimulatedPattern {
}
}
double[] centerXY = correctedPatternCrossLocation(lwirReaderParameters, // LwirReaderParameters
// lwirReaderParameters,
// // null is OK
double[] centerXY = correctedPatternCrossLocation(
lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, null is OK
patternGrid[iUV[1]][iUV[0]][0], // initial coordinates of the pattern cross point
patternGrid[iUV[1]][iUV[0]][1][0], patternGrid[iUV[1]][iUV[0]][1][1],
patternGrid[iUV[1]][iUV[0]][2][0], patternGrid[iUV[1]][iUV[0]][2][1], simulPars, imp, // image
// data
// (Bayer
// mosaic)
patternGrid[iUV[1]][iUV[0]][2][0], patternGrid[iUV[1]][iUV[0]][2][1], simulPars, imp, // image data (Bayer mosaic)
distortionParameters, //
patternDetectParameters, matchSimulatedPatternCorr, // correlationSize
thisSimulParameters, equalizeGreens, windowFunctionCorr, windowFunctionCorr2,
windowFunctionCorr4, simulationPattern, ((iUV[0] ^ iUV[1]) & 1) != 0, // if true -
// invert
// pattern
fht_instance, distortionParameters.fastCorrelationOnFinalPass, //
locsNeib, thisDebug, // thisDebug
patternDetectParameters,
matchSimulatedPatternCorr, // correlationSize
thisSimulParameters,
equalizeGreens,
windowFunctionCorr,
windowFunctionCorr2,
windowFunctionCorr4,
simulationPattern, ((iUV[0] ^ iUV[1]) & 1) != 0, // if true - invert pattern
fht_instance,
distortionParameters.fastCorrelationOnFinalPass, //
locsNeib,
thisDebug, // thisDebug
null);
if (centerXY != null) {
......@@ -5299,6 +5308,13 @@ public class MatchSimulatedPattern {
System.out.println("==>iUV={" + iUV[0] + ", " + iUV[1] + "}. "
+ patternGrid[iUV[1]][iUV[0]][0][0] + " / " + patternGrid[iUV[1]][iUV[0]][0][1]
+ " -> " + centerXY[0] + " / " + centerXY[1]);
// refine should provide higher contrast than was there, it is so for EO, but not for LWIR
// LWIR refined contrast is approximately the same as that of non-refined, twice less than EO
// boosting it here
if (sensor_type == 1) {
centerXY[2] *= 2.0; // boosting refined LWIR
}
if (refineInPlace)
setPatternGridCell(patternGrid, iUV, centerXY, null, // double [] wv1,
null); // double [] wv2);
......@@ -5381,13 +5397,33 @@ public class MatchSimulatedPattern {
}
// Copy new values for the grid cells
boolean debug_bias = true;
double lwir_refine_dx = -0.25;
double lwir_refine_dy = -0.25;
double sw = 0.0, swx = 0.0, swy = 0.0; // finding x,y bias of refining
for (iUV[1] = 0; iUV[1] < height; iUV[1]++)
for (iUV[0] = 0; iUV[0] < width; iUV[0]++)
if (newGrid[iUV[1]][iUV[0]] != null) {
if (debug_bias) {
double [] center_refined = newGrid[iUV[1]][iUV[0]];
double [] center_orig = patternGrid[iUV[1]][iUV[0]][0];
sw += center_refined[2];
swx += center_refined[2] * (center_refined[0] - center_orig[0]);
swy += center_refined[2] * (center_refined[1] - center_orig[1]);
}
setPatternGridCell(patternGrid, iUV, newGrid[iUV[1]][iUV[0]], null, // double [] wv1,
null); // double [] wv2);
} else if (sensor_type == 1) { // FIXME: correcting LWIR refine bias
if (isCellDefined(patternGrid, iUV)) {
patternGrid[iUV[1]][iUV[0]][0][0] += lwir_refine_dx;
patternGrid[iUV[1]][iUV[0]][0][1] += lwir_refine_dy;
}
}
if (debug_bias && (sw > 0.0)) {
swx /= sw;
swy /= sw;
System.out.println("Refine bias dx = "+swx+"pix, dy = "+swy+"pix");
}
// correction is only calculated for simultaneous update (not for in-place)
if (debug_level > 1) {
System.out.println("refineDistortionCorrelation(): maximal correction=" + maxActualCorr + " pixels");
......@@ -5449,12 +5485,18 @@ public class MatchSimulatedPattern {
* average grid period)
*
*/
public ImagePlus equalizeGridIntensity(ImagePlus imp, double[][][][] patternGrid,
public ImagePlus equalizeGridIntensity(
ImagePlus imp,
double[][][][] patternGrid,
DistortionParameters distortionParameters, //
boolean equalizeGreens, int debugLevel, boolean updateStatus, int threadsMax) {
boolean equalizeGreens,
int debugLevel,
boolean updateStatus,
int threadsMax) {
int dbgThreshold = 1;
final int sensor_type = LwirReaderParameters.sensorType(imp);
double[][] gridIntensity = calcGridIntensity(4, // bayerComponent
distortionParameters.correlationSize, // size
distortionParameters.getCorrelationSize(sensor_type), // correlationSize, // size
distortionParameters, //
equalizeGreens, imp, // image to process
patternGrid, threadsMax);// debug level used inside loops
......@@ -5470,6 +5512,10 @@ public class MatchSimulatedPattern {
double[] fffg = calcFlatFieldForGrid(gridIntensity, patternGrid, imp.getWidth(), imp.getHeight());
double averageGridPeriod = averageGridPeriod(patternGrid);
// if (debugLevel > (dbgThreshold + 2)) {
// this.SDFA_INSTANCE.showArrays(fffg, imp.getWidth(), imp.getHeight(),
// imp.getTitle() + "-fftg");
// }
int preShrink = (int) (averageGridPeriod * distortionParameters.flatFieldShrink);
int expand = (int) (averageGridPeriod * distortionParameters.flatFieldExpand);
......@@ -5584,16 +5630,21 @@ public class MatchSimulatedPattern {
return this.gridContrastBrightness;
}
public double[][] calcGridIntensity(final int bayerComponent, final int size,
public double[][] calcGridIntensity(
final int bayerComponent,
final int size,
final DistortionParameters distortionParameters, //
final boolean equalizeGreens, final ImagePlus imp, // image to process
final double[][][][] patternGrid, final int threadsMax) {// debug level used inside loops
final boolean equalizeGreens,
final ImagePlus imp, // image to process
final double[][][][] patternGrid,
final int threadsMax) {// debug level used inside loops
final int sensor_type = LwirReaderParameters.sensorType(imp);
final double[][] gridIntensity = new double[patternGrid.length][patternGrid[0].length];
for (int i = 0; i < gridIntensity.length; i++)
for (int j = 0; j < gridIntensity[0].length; j++)
gridIntensity[i][j] = (bayerComponent >= 0) ? -1.0 : 0.0; // undefined
MatchSimulatedPattern matchSimulatedPatternCorr = new MatchSimulatedPattern(
distortionParameters.correlationSize);
distortionParameters.getCorrelationSize(sensor_type)); // correlationSize);
matchSimulatedPatternCorr.debugLevel = debugLevel;
final double[] windowFunctionCorr = initWindowFunction(size, // distortionParameters.correlationSize,
distortionParameters.correlationGaussWidth, distortionParameters.zeros);
......@@ -5650,7 +5701,7 @@ public class MatchSimulatedPattern {
if (isCellDefined(patternGrid, iUV[0], iUV[1])) {
double[][] patternCell = patternGrid[iUV[1]][iUV[0]];
if (patternCell[0].length > 2)
gridIntensity[iUV[1]][iUV[0]] = patternCell[0][2];
gridIntensity[iUV[1]][iUV[0]] = patternCell[0][2]; // just copy from patternGrid[v][u][0][2]
}
/*
* gridIntensity[iUV[1]][iUV[0]]=localGridContrast( imp, equalizeGreens,
......@@ -6713,6 +6764,10 @@ public class MatchSimulatedPattern {
setWOI(0, 0, imp.getWidth(), imp.getHeight());
selection = new Rectangle(0, 0, imp.getWidth(), imp.getHeight());
// without setting roi to null (maybe setting image roi too?) will not retry if first attempt gets too few points
// there is also ignoring PointRoi later, but alone it outputs "Removing failed node (normally should not happen!), u=4, v=2"
// roi = null;
// imp.setRoi(roi,false);
} else {
setWOI(roi.getBounds());
selection = roi.getBounds();
......@@ -6811,35 +6866,48 @@ public class MatchSimulatedPattern {
if (distortionParameters.flatFieldCorrection && (this.flatFieldForGrid == null)) // if it is not null it is
// already supposed to be
// applied!
imp_eq = equalizeGridIntensity(imp, this.PATTERN_GRID, distortionParameters, //
equalizeGreens, global_debug_level, updateStatus, threadsMax);
imp_eq = equalizeGridIntensity(
imp,
this.PATTERN_GRID,
distortionParameters, // // makes no sense for LWIR as it normalizes absolute data - actually it does!
equalizeGreens,
global_debug_level,
updateStatus,
threadsMax);
else
imp_eq = imp;
if (distortionParameters.refineCorrelations) {
refineDistortionCorrelation(lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, // null is
// OK
refineDistortionCorrelation(
lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters, simulParameters, equalizeGreens, imp_eq, 0.0, // final double maxCorr, //
// maximal allowed
// correction, in pixels
// (0.0) - any
threadsMax, updateStatus, debug_level); // debug level
recalculateWaveVectors(updateStatus, debug_level);// debug level used inside loops
patternDetectParameters,
simulParameters,
equalizeGreens,
imp_eq,
0.0, // final double maxCorr, maximal allowed correction, in pixels (0.0) - any
threadsMax,
updateStatus,
debug_level); // debug level
recalculateWaveVectors(
updateStatus,
debug_level);// debug level used inside loops
if (global_debug_level > (debugThreshold + 1))
System.out.println("Second pass over at " + IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3));
}
// hack gridSize
if ((distortionParameters.gridSize & 1) != 0) {
refineDistortionCorrelation(lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, // null is
// OK
refineDistortionCorrelation(lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters, simulParameters, equalizeGreens, imp_eq, 0.0, // final double maxCorr, //
// maximal allowed
// correction, in pixels
// (0.0) - any
threadsMax, updateStatus, debug_level); // debug level
patternDetectParameters,
simulParameters,
equalizeGreens,
imp_eq,
0.0, // final double maxCorr, maximal allowed correction, in pixels (0.0) - any
threadsMax,
updateStatus,
debug_level); // debug level
recalculateWaveVectors(updateStatus, debug_level);// debug level used inside loops
if (global_debug_level > 0)
......@@ -6847,7 +6915,7 @@ public class MatchSimulatedPattern {
// hack gridSize
}
patternCells = numDefinedCells();
if ((roi != null) && (patternCells < minimal_pattern_cluster)) {
if ((roi != null) && (patternCells < minimal_pattern_cluster) && !(roi instanceof PointRoi)) {
if (global_debug_level > (debugThreshold + 0))
System.out.println("Detected pattern is too small: " + patternCells + ", minimum is set to "
+ minimal_pattern_cluster);
......@@ -9653,16 +9721,21 @@ public class MatchSimulatedPattern {
*/
//
/* ======================================================================== */
private double[] correctedPatternCrossLocation(LwirReaderParameters lwirReaderParameters, // null is OK
private double[] correctedPatternCrossLocation(
LwirReaderParameters lwirReaderParameters, // null is OK
double[] beforeXY, // initial coordinates of the pattern cross point
double wv0x, double wv0y, double wv1x, double wv1y, double[][] correction, ImagePlus imp, // image data
// (Bayer
// mosaic)
double wv0x,
double wv0y,
double wv1x,
double wv1y,
double[][] correction,
ImagePlus imp, // image data (Bayer mosaic)
DistortionParameters distortionParameters, //
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
MatchSimulatedPattern matchSimulatedPattern, // correlationSize
SimulationPattern.SimulParameters thisSimulParameters, boolean equalizeGreens, double[] window, // window
// function
SimulationPattern.SimulParameters thisSimulParameters,
boolean equalizeGreens,
double[] window, // window function
double[] window2, // window function - twice FFT size (or null)
double[] window4, // window function - 4x FFT size (or null)
SimulationPattern simulationPattern, boolean negative, // invert cross phase
......@@ -9670,31 +9743,52 @@ public class MatchSimulatedPattern {
double[][] locsNeib, // locations and weights of neighbors to average
int debug_level, String dbgStr) {
if (distortionParameters.legacyMode)
return correctedPatternCrossLocationOld(beforeXY, // initial coordinates of the pattern cross point
wv0x, wv0y, wv1x, wv1y, correction, imp, // image data (Bayer mosaic)
return correctedPatternCrossLocationOld(
beforeXY, // initial coordinates of the pattern cross point
wv0x,
wv0y,
wv1x,
wv1y,
correction,
imp, // image data (Bayer mosaic)
distortionParameters, //
patternDetectParameters, matchSimulatedPattern, // correlationSize
thisSimulParameters, equalizeGreens, window, // window function
patternDetectParameters,
matchSimulatedPattern, // correlationSize
thisSimulParameters,
equalizeGreens,
window, // window function
window2, // window function - twice FFT size (or null)
window4, // window function - 4x FFT size (or null)
simulationPattern, negative, // invert cross phase
simulationPattern,
negative, // invert cross phase
fht_instance, fast, // use fast measuring of the maximum on the correlation
locsNeib, // locations and weights of neighbors to average
debug_level);
else
return correctedPatternCrossLocationAverage4(lwirReaderParameters, // LwirReaderParameters
// lwirReaderParameters, // null is OK
return correctedPatternCrossLocationAverage4(
lwirReaderParameters, // LwirReaderParameters
beforeXY, // initial coordinates of the pattern cross point
wv0x, wv0y, wv1x, wv1y, correction, imp, // image data (Bayer mosaic)
wv0x,
wv0y,
wv1x,
wv1y,
correction,
imp, // image data (Bayer mosaic)
distortionParameters, //
patternDetectParameters, matchSimulatedPattern, // correlationSize
thisSimulParameters, equalizeGreens, window, // window function
patternDetectParameters,
matchSimulatedPattern, // correlationSize
thisSimulParameters,
equalizeGreens,
window, // window function
window2, // window function - twice FFT size (or null)
window4, // window function - 4x FFT size (or null)
simulationPattern, negative, // invert cross phase
fht_instance, fast, // use fast measuring of the maximum on the correlation
simulationPattern,
negative, // invert cross phase
fht_instance,
fast, // use fast measuring of the maximum on the correlation
locsNeib, // locations and weights of neighbors to average
debug_level, dbgStr);
debug_level,
dbgStr);
}
private double[] correctedPatternCrossLocationOld(double[] beforeXY, // initial coordinates of the pattern cross
......@@ -9984,36 +10078,50 @@ public class MatchSimulatedPattern {
return result;
}
private double[] correctedPatternCrossLocationAverage4(LwirReaderParameters lwirReaderParameters, // null is OK
private double[] correctedPatternCrossLocationAverage4(
LwirReaderParameters lwirReaderParameters, // null is OK
double[] beforeXY, // initial coordinates of the pattern cross point
double wv0x, double wv0y, double wv1x, double wv1y, double[][] correction, ImagePlus imp, // image data
// (Bayer
// mosaic)
double wv0x,
double wv0y,
double wv1x,
double wv1y,
double[][] correction,
ImagePlus imp, // image data (Bayer mosaic)
DistortionParameters distortionParameters, // distortionParameters.refineCorrelations
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
MatchSimulatedPattern matchSimulatedPattern, // correlationSize
SimulationPattern.SimulParameters thisSimulParameters, boolean equalizeGreens, double[] window, // window
// function
SimulationPattern.SimulParameters thisSimulParameters,
boolean equalizeGreens,
double[] window, // window function
double[] window2, // window function - twice FFT size (or null)
double[] window4, // window function - 4x FFT size (or null)
SimulationPattern simulationPattern, boolean negative, // invert cross phase
DoubleFHT fht_instance, boolean fast, // use fast measuring of the maximum on the correlation
SimulationPattern simulationPattern,
boolean negative, // invert cross phase
DoubleFHT fht_instance,
boolean fast, // use fast measuring of the maximum on the correlation
double[][] locsNeib, // locations and weights of neighbors to average
int debug_level, String dbgStr) {
int debug_level,
String dbgStr) {
if (imp == null) {
return null;
}
/*
boolean is_lwir = ((lwirReaderParameters != null) && lwirReaderParameters.is_LWIR(imp));
int correlation_size = is_lwir ? distortionParameters.correlationSizeLwir
: distortionParameters.correlationSize;
int max_correlation_size = is_lwir ? distortionParameters.maximalCorrelationSizeLwir
: distortionParameters.maximalCorrelationSize;
*/
final int sensor_type = LwirReaderParameters.sensorType(imp);
final int correlation_size = distortionParameters.getCorrelationSize(sensor_type);
final int max_correlation_size = distortionParameters.getMaximalCorrelationSize(sensor_type);
boolean is_mono = false;
try {
is_mono = Boolean.parseBoolean((String) imp.getProperty("MONOCHROME"));
} catch (Exception e) {
}
is_mono |= is_lwir;
is_mono |= (sensor_type == 1); // is_lwir;
int debug_threshold = 3;
// next print - same for good and bad, correction==null
......@@ -10036,7 +10144,7 @@ public class MatchSimulatedPattern {
beforeXY[1] += distortionParameters.correlationDy; // offset y (in pixels)
double[][] invConvMatrix = { { 1, 0 }, { 0, 1 } }; // identity
if (!is_lwir) {
if (sensor_type != 1) { //(!is_lwir) {
double[][] convMatrix = { { 1.0, -1.0 }, { 1.0, 1.0 } }; // from greens2 to pixel WV
invConvMatrix = matrix2x2_scale(matrix2x2_invert(convMatrix), 2.0);
}
......@@ -10112,19 +10220,26 @@ public class MatchSimulatedPattern {
if ((debug_level > (debug_threshold - 2)) && (thisCorrelationSize > correlation_size))
System.out.println("**** u/v span too small, increasing FFT size to " + thisCorrelationSize);
Rectangle centerCross = correlationSelection(beforeXY, // initial coordinates of the pattern cross point
(is_lwir ? (thisCorrelationSize / 2) : (thisCorrelationSize)));
// (is_lwir ? (thisCorrelationSize / 2) : (thisCorrelationSize)));
((sensor_type == 1) ? (thisCorrelationSize / 2) : (thisCorrelationSize)));
int ixc = centerCross.x + centerCross.width / 2;
int iyc = centerCross.y + centerCross.height / 2;
double[] diffBeforeXY = { beforeXY[0] - ixc, beforeXY[1] - iyc };
double[] greens_mono; // greens or mono
if (is_lwir) {
// if (is_lwir) {
if (sensor_type == 1) {
greens_mono = getNoBayer(imp, centerCross);
if (debug_level > (debug_threshold + 0))
SDFA_INSTANCE.showArrays(greens_mono, "greens_mono");
if (debug_level > (debug_threshold + 0))
System.out.println("ixc=" + ixc + " iyc=" + iyc);
normalizeAndWindow(greens_mono, thisWindow);
// Twice lower contrast than EO - doubling below - did not work
// for (int i = 0; i < greens_mono.length; i++) {
// greens_mono[i] *= 2.0;
// }
} else {
double[][] input_bayer = splitBayer(imp, centerCross, equalizeGreens);
if (debug_level > (debug_threshold + 1))
......@@ -10176,7 +10291,8 @@ public class MatchSimulatedPattern {
double[][] modelCorrs = new double[numOfNeib][];
double[][] debugGreens = new double[numOfNeib][0];
for (numNeib = 0; numNeib < numOfNeib; numNeib++) {
if (is_lwir) { // monochrome, use all pixels
// if (is_lwir) { // monochrome, use all pixels
if (sensor_type == 1) { // monochrome, use all pixels
neibCenter[0] = diffBeforeXY[0] + gridNeib[numNeib][0];
neibCenter[1] = diffBeforeXY[1] + gridNeib[numNeib][1];
} else {
......@@ -10184,11 +10300,13 @@ public class MatchSimulatedPattern {
neibCenter[1] = diffBeforeXY[1] + 0.5 * (gridNeib[numNeib][0] - gridNeib[numNeib][1]);
}
double[] barray;
if (is_lwir) {
// if (is_lwir) {
if (sensor_type == 1) {
// negative=!negative;
dUV = matrix2x2_scale(matrix2x2_mul(wv, neibCenter), -2 * Math.PI);
// dUV[0] = 0.0; dUV[1] = 0.0;
if (debug_level > (debug_threshold + 20)) {
boolean dbg_once = false;
if (dbg_once || (debug_level > (debug_threshold + 20))) {
double[] barray0 = simulationPattern.simulatePatternFullPatternSafe( // Is it the most
// time-consuming part?
// should it be done once
......@@ -10429,11 +10547,11 @@ public class MatchSimulatedPattern {
WVgreensMono[i][j] *= 0.5;
}
double[] contrasts = correlationContrast(modelCorr, greens_mono, WVgreensMono, // wave vectors (same units as
// the pixels array)
double[] contrasts = correlationContrast(modelCorr,
greens_mono,
WVgreensMono, // wave vectors (same units as the pixels array)
distortionParameters.contrastSelectSigmaCenter, // 2.0 Gaussian sigma to select correlation (pixels, 2.0)
distortionParameters.contrastSelectSigma, // 0.1 Gaussian sigma to select correlation centers (fraction of
// UV period), 0.1
distortionParameters.contrastSelectSigma, // 0.1 Gaussian sigma to select correlation centers (fraction of UV period), 0.1
centerXY[0], // x0, // center coordinates
centerXY[1], // y0,
"test-contrast"); // title base for optional plots names
......@@ -10497,9 +10615,12 @@ public class MatchSimulatedPattern {
+ IJ.d2s(beforeXY[1], 3) + ")->" + IJ.d2s(result[0], 3) + ":" + IJ.d2s(result[1], 3));
// FIXME: maybe wrong for mono?
if (is_lwir) {
// if (is_lwir) {
if (sensor_type == 1) {
result[0] = ixc + diffBeforeXY[0] + centerXY[0];
result[1] = iyc + diffBeforeXY[1] + centerXY[1];
// Twice lower contrast than EO - doubling below - did not work
// result[2] *= 2.0; // not just for refine
} else {
result[0] = ixc + diffBeforeXY[0] - (-centerXY[0] - centerXY[1]);
result[1] = iyc + diffBeforeXY[1] - (centerXY[0] - centerXY[1]);
......@@ -12409,103 +12530,337 @@ public class MatchSimulatedPattern {
/* ======================================================================== */
public static class DistortionParameters {
public int correlationSize; // FFTSize/4
public int correlationSizeLwir;
public int maximalCorrelationSize; // FFTSize/2
public int maximalCorrelationSizeLwir;
public double correlationGaussWidth; // 0 - no window, <0 - use Hamming
public boolean absoluteCorrelationGaussWidth = false; // do not scale correlationGaussWidth when the FFT size is
private int correlationSize; // FFTSize/4
private int correlationSizeLwir;
private int maximalCorrelationSize; // FFTSize/2
private int maximalCorrelationSizeLwir;
public double correlationGaussWidth; // 0 - no window, <0 - use Hamming
public boolean absoluteCorrelationGaussWidth = false; // do not scale correlationGaussWidth when the FFT size is
// increased
public int zeros; // leave this number of zeros on the margins of the window (toatal from both
public int zeros; // leave this number of zeros on the margins of the window (toatal from both
// sides). If correlationGaussWidth>0 will
// additionally multiply by Hamming
public int FFTSize;
public int FFTSize_lwir;
public int FFTOverlap; // 32 used for aberration kernels, former FFT_OVERLAP
public int FFTOverlap_lwir; // 4
public double fftGaussWidth;
public double phaseCorrelationFraction = 1.0; // 1.0 - phase correlation, 0.0 - just cross-correlation
public double correlationHighPassSigma;
public double correlationLowPassSigma;
public double correlationRingWidth; // ring (around r=0.5 dist to opposite corr) width , center circle
private int FFTSize;
private int FFTSize_lwir;
private int FFTOverlap; // 32 used for aberration kernels, former FFT_OVERLAP
private int FFTOverlap_lwir; // 4
public double fftGaussWidth;
public double phaseCorrelationFraction = 1.0; // 1.0 - phase correlation, 0.0 - just cross-correlation
public double correlationHighPassSigma;
public double correlationLowPassSigma;
public double correlationRingWidth; // ring (around r=0.5 dist to opposite corr) width , center circle
// r=0.5*correlationRingWidth
public double correlationMaxOffset; // maximal distance between predicted and actual pattern node
public double correlationMinContrast; // minimal contrast for the pattern to pass
public double correlationMinInitialContrast; // minimal contrast for the pattern of the center (initial point)
public double correlationMinAbsoluteContrast; // minimal contrast for the pattern to pass, does not compensate
public double correlationMaxOffset; // maximal distance between predicted and actual pattern node
public double correlationMinContrast; // minimal contrast for the pattern to pass
public double correlationMinInitialContrast; // minimal contrast for the pattern of the center (initial point)
public double correlationMinAbsoluteContrast; // minimal contrast for the pattern to pass, does not compensate
// for low ligt
public double correlationMinAbsoluteInitialContrast; // minimal contrast for the pattern of the center (initial
public double correlationMinAbsoluteInitialContrast; // minimal contrast for the pattern of the center (initial
// point)
public double scaleFirstPassContrast; // Decrease contrast of cells that are too close to the border to be
public double scaleFirstPassContrast; // Decrease contrast of cells that are too close to the border to be
// processed in refinement pass
public double contrastSelectSigmaCenter; // Gaussian sigma to select correlation centers in pixels, 2.0 (center
public double contrastSelectSigmaCenter; // Gaussian sigma to select correlation centers in pixels, 2.0 (center
// spot)
public double contrastSelectSigma; // Gaussian sigma to select correlation centers (fraction of UV period), 0.1
public double contrastAverageSigma; // Gaussian sigma to average correlation variations (as contrast reference)
public double contrastSelectSigma; // Gaussian sigma to select correlation centers (fraction of UV period), 0.1
public double contrastAverageSigma; // Gaussian sigma to average correlation variations (as contrast reference)
// 0.5
public int minimalPatternCluster; // minimal pattern cluster size (0 - disable retries)
public int minimalPatternClusterLwir; // minimal pattern cluster size (0 - disable retries)
public double scaleMinimalInitialContrast; // increase/decrease minimal contrast if initial cluster is >0 but
private int minimalPatternCluster; // minimal pattern cluster size (0 - disable retries)
private int minimalPatternClusterLwir; // minimal pattern cluster size (0 - disable retries)
public double scaleMinimalInitialContrast; // increase/decrease minimal contrast if initial cluster is >0 but
// less than minimalPatternCluster
public double searchOverlap; // when searching for grid, step this amount of the FFTSize
public int patternSubdiv;
public double correlationDx; // not saved
public double correlationDy; // not saved
public int gridSize;
public int loop_debug_level;
public boolean refineCorrelations;
public boolean fastCorrelationOnFirstPass;
public boolean fastCorrelationOnFinalPass;
public double bPatternSigma; // blur bPattern with this sigma
public double barraySigma; // blur barray with this sigma, multiplied by subdiv
public double correlationWeightSigma; // sigma (in pixels) for maximum approximation - UNUSED (other maximum
public double searchOverlap; // when searching for grid, step this amount of the FFTSize
public int patternSubdiv;
public double correlationDx; // not saved
public double correlationDy; // not saved
public int gridSize;
public int loop_debug_level;
public boolean refineCorrelations;
public boolean fastCorrelationOnFirstPass;
public boolean fastCorrelationOnFinalPass;
public double bPatternSigma; // blur bPattern with this sigma
public double barraySigma; // blur barray with this sigma, multiplied by subdiv
public double correlationWeightSigma; // sigma (in pixels) for maximum approximation - UNUSED (other maximum
// methods)
public double correlationRadiusScale; // maximal radius to consider, in sigmas (if 0 - use sigma as radius) -
public double correlationRadiusScale; // maximal radius to consider, in sigmas (if 0 - use sigma as radius) -
// UNUSED
public int correlationRadius; // radius (green pixel) of the correlation maximum to use for x/y measurement
public double correlationThreshold; // fraction of the value of the maximum fro the point to be included in
public int correlationRadius; // radius (green pixel) of the correlation maximum to use for x/y measurement
public double correlationThreshold; // fraction of the value of the maximum fro the point to be included in
// centroid calculation
public int correlationSubdiv; // Total subdivision of the correlation maximum (linear and FFT)
public int correlationFFTSubdiv; // Increase density of the correlation using FFT
public boolean correlationAverageOnRefine; // average position between neighbor samples
public boolean refineInPlace; // Update coordinates of the grid points as they are recalculated (false - then
public int correlationSubdiv; // Total subdivision of the correlation maximum (linear and FFT)
public int correlationFFTSubdiv; // Increase density of the correlation using FFT
public boolean correlationAverageOnRefine; // average position between neighbor samples
public boolean refineInPlace; // Update coordinates of the grid points as they are recalculated (false - then
// update all at once)
public double averageOrthoDist; // distance to up/down/right left neighbors (0.5)
public double averageOrthoWeight; // weight of 4 ortho neighbors (combined) - 0.4), weight of center -s
public double averageOrthoDist; // distance to up/down/right left neighbors (0.5)
public double averageOrthoWeight; // weight of 4 ortho neighbors (combined) - 0.4), weight of center -s
// 1.0-averageOrthoWeight-averageDiagWeight
public double averageDiagDist; // distance to diagonal neighbors (projection on x/y) (0.5)
public double averageDiagWeight; // weight of 4 diagonal neighbors (combined) - 0.4)
public boolean useQuadratic; // use quadratic extrapolation to predict position/wave vectors of a new pixel
public double averageDiagDist; // distance to diagonal neighbors (projection on x/y) (0.5)
public double averageDiagWeight; // weight of 4 diagonal neighbors (combined) - 0.4)
public boolean useQuadratic; // use quadratic extrapolation to predict position/wave vectors of a new pixel
// (false - use linear)
public boolean removeLast; // remove outer (unreliable) row of nodes
public int numberExtrapolated; // add this number of extrapolated nodes
public double extrapolationSigma; // use instead of the correlationWeightSigma during final extrapolation
public double minUVSpan; // Minimal u/v span in correlation window that triggers increase of the
public boolean removeLast; // remove outer (unreliable) row of nodes
public int numberExtrapolated; // add this number of extrapolated nodes
public double extrapolationSigma; // use instead of the correlationWeightSigma during final extrapolation
public double minUVSpan; // Minimal u/v span in correlation window that triggers increase of the
// correlation FFT size
public boolean flatFieldCorrection = true; // compensate grid uneven intensity (vignetting, illumination)
public double flatFieldExtarpolate = 1.0; // extrapolate flat field intensity map (relative to the average grid
public boolean flatFieldCorrection = true; // compensate grid uneven intensity (vignetting, illumination)
public double flatFieldExtarpolate = 1.0; // extrapolate flat field intensity map (relative to the average grid
// period)
public double flatFieldBlur = 1.0; // blur the intensity map (relative to the average grid period)
public double flatFieldMin = 0.1; // do not try to compensate if intensity less than this part of maximal
public double flatFieldShrink = 1.0; // Shrink before extrapolating intensity map (relative to the average grid
public double flatFieldBlur = 1.0; // blur the intensity map (relative to the average grid period)
public double flatFieldMin = 0.1; // do not try to compensate if intensity less than this part of maximal
public double flatFieldShrink = 1.0; // Shrink before extrapolating intensity map (relative to the average grid
// period)
public double flatFieldExpand = 3.0; // Expand during extrapolation (relative to the average grid period)
public double flatFieldSigmaRadius = 1.0;// Extrapolation weight effective radius (relative to the average grid
public double flatFieldExpand = 3.0; // Expand during extrapolation (relative to the average grid period)
public double flatFieldSigmaRadius = 1.0;// Extrapolation weight effective radius (relative to the average grid
// period)
public double flatFieldExtraRadius = 1.5;// Consider pixels in a square with the side twice this (relative to
public double flatFieldExtraRadius = 1.5;// Consider pixels in a square with the side twice this (relative to
// flatFieldSigmaRadius)
public double averagingAreaScale = 2.0; // multiply the average grid period to determine the area for averaging
public double averagingAreaScale = 2.0; // multiply the average grid period to determine the area for averaging
// the grig brightness
// match pointers errors
public int errTooFewCells = -10;
public int errPatternNotFound = -11;
public boolean legacyMode = false; // legacy mode
public int errTooFewCells = -10;
public int errPatternNotFound = -11;
public boolean legacyMode = false; // legacy mode
public int getCorrelationSize(int sensor_type) {
switch (sensor_type) {
case 1: return correlationSizeLwir;
default: return correlationSize;}
}
public void setCorrelationSize(int size, int sensor_type) {
switch (sensor_type) {
case 1: correlationSizeLwir = size; break;
default: correlationSize = size;}
}
public int getMaximalCorrelationSize(int sensor_type) {
switch (sensor_type) {
case 1: return maximalCorrelationSizeLwir;
default: return maximalCorrelationSize;}
}
public int getFFTSize(int sensor_type) {
switch (sensor_type) {
case 1: return FFTSize_lwir;
default: return FFTSize;}
}
/*
public void setFFTSize(int size, int sensor_type) {
switch (sensor_type) {
case 1: FFTSize_lwir = size; break;
default: FFTSize = size; }
}
*/
public int getFFTOverlap(int sensor_type) {
switch (sensor_type) {
case 1: return FFTOverlap_lwir;
default: return FFTOverlap;}
}
public int getMinimalPatternCluster(int sensor_type) {
switch (sensor_type) {
case 1: return minimalPatternClusterLwir;
default: return minimalPatternCluster;}
}
public void setMinimalPatternCluster(int size, int sensor_type) {
switch (sensor_type) {
case 1: minimalPatternClusterLwir = size; break;
default: minimalPatternCluster = size;}
}
public boolean showDistortionDialog(int [] mdl) { //MatchSimulatedPattern.DistortionParameters distortionParameters) {
MatchSimulatedPattern.DistortionParameters distortionParameters = this;
int i;
GenericDialog gd = new GenericDialog("Distrortion parameters");
gd.addNumericField("FFTSize (Initial pattern and aberraton kernels):", distortionParameters.FFTSize, 0); // 256
gd.addNumericField("FFTSize for LWIR sensors):", distortionParameters.FFTSize_lwir, 0); // 32
gd.addNumericField("FFTOverlap (aberration kernels):", distortionParameters.FFTOverlap, 0); // 32
gd.addNumericField("FFTOverlap for LWIR sensors):", distortionParameters.FFTOverlap_lwir, 0); // 4
gd.addNumericField("FFT Gaussian width (relative):", distortionParameters.fftGaussWidth, 3);
gd.addNumericField("Correlation size:", distortionParameters.correlationSize, 0); // 64
gd.addNumericField("Correlation size LWIR:", distortionParameters.correlationSizeLwir, 0); // 16
gd.addNumericField("Maximal correlation size:", distortionParameters.maximalCorrelationSize, 0); // 128
gd.addNumericField("Maximal correlation size LWIR:", distortionParameters.maximalCorrelationSizeLwir, 0); // 16
gd.addNumericField("Correlation Gauss width (relative):", distortionParameters.correlationGaussWidth, 3);
gd.addCheckbox("Keep Gaussian width absolute when increasing FFT size",distortionParameters.absoluteCorrelationGaussWidth);
// /phaseCorrelationFraction
//// leave this number of zeros on teh margins of the window (toatal from both sides). If correlationGaussWidth>0 will
// additionally multiply by Hamming
gd.addNumericField("Leave zeros on the window margins (toatal numbedr from both sides)", distortionParameters.zeros, 0);
gd.addNumericField("Phase correlation modifier (1.0 - phase corr., 0 - just corr.)", distortionParameters.phaseCorrelationFraction, 5);
gd.addNumericField("Correlation high-pass sigma:", distortionParameters.correlationHighPassSigma, 3);
gd.addNumericField("Correlation low-pass sigma (fraction of sqrt(2)*Nyquist, lower - more filtering, 0 -none):",distortionParameters.correlationLowPassSigma, 3);
gd.addNumericField("Correlation maximal offset from predicted:",distortionParameters.correlationMaxOffset, 3);
gd.addNumericField("Detection ring width (fraction):", distortionParameters.correlationRingWidth, 3);
gd.addNumericField("Correlation minimal contrast (normalized)", distortionParameters.correlationMinContrast, 3);
gd.addNumericField("Correlation minimal contrast for initial search (normalized)", distortionParameters.correlationMinInitialContrast, 3);
gd.addNumericField("Correlation minimal contrast (absolute)", distortionParameters.correlationMinAbsoluteContrast, 3);
gd.addNumericField("Correlation minimal contrast for initial search (absolute)", distortionParameters.correlationMinAbsoluteInitialContrast, 3);
gd.addNumericField("Decrease contrast of cells that are too close to the border to be processed in refinement pass", distortionParameters.scaleFirstPassContrast, 3);
gd.addNumericField("Gaussian sigma to select correlation center in pixels, 2.0", distortionParameters.contrastSelectSigmaCenter, 3);
gd.addNumericField("Gaussian sigma to select correlation off-centers (fraction of UV period), 0.1", distortionParameters.contrastSelectSigma, 3);
gd.addNumericField("Gaussian sigma to average correlation variations (as contrast reference), 0.5", distortionParameters.contrastAverageSigma, 3);
gd.addNumericField("Minimal initial pattern cluster size (0 - disable retries)", distortionParameters.minimalPatternCluster, 0); // 40
gd.addNumericField("Minimal initial LWIR pattern cluster size (0 - disable retries)", distortionParameters.minimalPatternClusterLwir, 0); // 10
gd.addNumericField("Scale minimal contrast if the initial cluster is nonzero but smaller", distortionParameters.scaleMinimalInitialContrast, 3);
gd.addNumericField("Overlap of FFT areas when searching for pattern", distortionParameters.searchOverlap, 3);
gd.addNumericField("Pattern subdivision:", distortionParameters.patternSubdiv, 0); // 4
gd.addNumericField("Blur pattern bitmap (sigma): ", distortionParameters.bPatternSigma, 3,5,"pattern cell"); // 0.02
gd.addNumericField("Blur pattern (sigma): ", distortionParameters.barraySigma, 3,5,"sensor pix"); // 0.5
gd.addNumericField("Correlation weights (around maximum):", distortionParameters.correlationWeightSigma, 3,5,"nodes"); // 2.5
gd.addNumericField("Correlation radius scale (0 - sharp sigma)", distortionParameters.correlationRadiusScale, 1,3,"sigmas"); //2.0
gd.addNumericField("Correlation maximal radius to use", distortionParameters.correlationRadius, 0,1,"pix"); // 2.0
gd.addNumericField("Correlation maximum calculation threshold", distortionParameters.correlationThreshold*100, 2,5,"%"); // .8
gd.addNumericField("Interpolate correlation (FFT*linear)", distortionParameters.correlationSubdiv, 0,3,"x"); // 16
gd.addNumericField("Interpolate correlation with FFT", distortionParameters.correlationFFTSubdiv, 0,3,"x"); // 4
gd.addNumericField("Correlation dx (debug)", distortionParameters.correlationDx, 3);
gd.addNumericField("Correlation dy (debug)", distortionParameters.correlationDy, 3);
gd.addNumericField("Maximal size of the pattern grid (square)", distortionParameters.gridSize, 0);
gd.addCheckbox ("Refine correlations", distortionParameters.refineCorrelations);
gd.addCheckbox ("Use fast correlation on first pass", distortionParameters.fastCorrelationOnFirstPass);
gd.addCheckbox ("Use fast correlation on refine pass", distortionParameters.fastCorrelationOnFinalPass);
gd.addCheckbox ("Average correlation measurements between neighbors (on refine)", distortionParameters.correlationAverageOnRefine);
gd.addCheckbox ("Update coordinates of the grid points as they are recalculated (false - then update all at once)", distortionParameters.refineInPlace);
gd.addNumericField("Distance to ortho neighbors (for averaging)", distortionParameters.averageOrthoDist, 3,5,"sensor pix");
gd.addNumericField("Combined weight of ortho neighbors (fraction of 1.0)", distortionParameters.averageOrthoWeight, 3);
gd.addNumericField("Distance to diagonal neighbors (for averaging)", distortionParameters.averageDiagDist, 3,5,"sensor pix");
gd.addNumericField("Combined weight of diagonal neighbors (fraction of 1.0)", distortionParameters.averageDiagWeight, 3);
gd.addCheckbox ("Use quadratic extrapolation (false - force linear)", distortionParameters.useQuadratic);
gd.addCheckbox ("Remove outer (unreliable) layer before extrapolation", distortionParameters.removeLast);
gd.addNumericField("Number of extrapolated layers of nodes (final stage)", distortionParameters.numberExtrapolated, 0);
gd.addNumericField("Sigma during final extrapolation stage", distortionParameters.extrapolationSigma, 3,5,"nodes");
gd.addNumericField("Minimal UV span in correlation window to trigger FFT size increase", distortionParameters.minUVSpan, 3);
gd.addCheckbox ("Compensate uneven pattern intensity", distortionParameters.flatFieldCorrection);
gd.addNumericField("Extrapolate pattern intensity map (relative to pattern period)", distortionParameters.flatFieldExtarpolate, 3);
gd.addNumericField("Blur pattern intensity map (relative to pattern period)", distortionParameters.flatFieldBlur, 3);
gd.addNumericField("Do not use areas where intensity map is below this part of maximal", distortionParameters.flatFieldMin, 3);
gd.addNumericField("Shrink before extrapolating intensity map (relative to the average grid period)", distortionParameters.flatFieldShrink, 3);
gd.addNumericField("Expand during extrapolation (relative to the average grid period)", distortionParameters.flatFieldExpand, 3);
gd.addNumericField("Extrapolation weight effective radius (relative to the average grid period)", distortionParameters.flatFieldSigmaRadius, 3);
gd.addNumericField("Consider pixels in a square with the side twice this (relative to flatFieldSigmaRadius)", distortionParameters.flatFieldExtraRadius, 3);
gd.addNumericField("Multiply the average grid period to determine the area for averaging the grig brightness", distortionParameters.averagingAreaScale, 3);
gd.addCheckbox ("Legacy mode (deprecated)", distortionParameters.legacyMode);
gd.addNumericField("Debug level inside the loop", distortionParameters.loop_debug_level, 0);
gd.addNumericField("Debug Level:", mdl[0], 0);
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
distortionParameters.FFTSize = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.FFTSize_lwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.FFTOverlap = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.FFTOverlap_lwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.fftGaussWidth= gd.getNextNumber();
distortionParameters.correlationSize = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.correlationSizeLwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.maximalCorrelationSize = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.maximalCorrelationSizeLwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.correlationGaussWidth= gd.getNextNumber();
distortionParameters.absoluteCorrelationGaussWidth=gd.getNextBoolean();
distortionParameters.zeros= (int) gd.getNextNumber();
distortionParameters.phaseCorrelationFraction= gd.getNextNumber();
distortionParameters.correlationHighPassSigma= gd.getNextNumber();
distortionParameters.correlationLowPassSigma= gd.getNextNumber();
distortionParameters.correlationMaxOffset= gd.getNextNumber();
distortionParameters.correlationRingWidth= gd.getNextNumber();
distortionParameters.correlationMinContrast= gd.getNextNumber();
distortionParameters.correlationMinInitialContrast= gd.getNextNumber();
distortionParameters.correlationMinAbsoluteContrast= gd.getNextNumber();
distortionParameters.correlationMinAbsoluteInitialContrast= gd.getNextNumber();
distortionParameters.scaleFirstPassContrast= gd.getNextNumber();
distortionParameters.contrastSelectSigmaCenter= gd.getNextNumber();
distortionParameters.contrastSelectSigma= gd.getNextNumber();
distortionParameters.contrastAverageSigma= gd.getNextNumber();
distortionParameters.minimalPatternCluster=(int) gd.getNextNumber();
distortionParameters.minimalPatternClusterLwir=(int) gd.getNextNumber();
distortionParameters.scaleMinimalInitialContrast=gd.getNextNumber();
distortionParameters.searchOverlap= gd.getNextNumber();
distortionParameters.patternSubdiv= (int) gd.getNextNumber();
distortionParameters.bPatternSigma= gd.getNextNumber();
distortionParameters.barraySigma= gd.getNextNumber();
distortionParameters.correlationWeightSigma= gd.getNextNumber();
distortionParameters.correlationRadiusScale= gd.getNextNumber();
distortionParameters.correlationRadius= (int) gd.getNextNumber();
distortionParameters.correlationThreshold= 0.01*gd.getNextNumber();
distortionParameters.correlationSubdiv= (int) gd.getNextNumber();
distortionParameters.correlationFFTSubdiv=1;
for (i=(int) gd.getNextNumber(); i >1; i>>=1) distortionParameters.correlationFFTSubdiv <<=1; /* make it to be power of 2 */
distortionParameters.correlationDx= gd.getNextNumber();
distortionParameters.correlationDy= gd.getNextNumber();
distortionParameters.gridSize= (int) gd.getNextNumber();
distortionParameters.refineCorrelations= gd.getNextBoolean();
distortionParameters.fastCorrelationOnFirstPass=gd.getNextBoolean();
distortionParameters.fastCorrelationOnFinalPass=gd.getNextBoolean();
distortionParameters.correlationAverageOnRefine=gd.getNextBoolean();
distortionParameters.refineInPlace= gd.getNextBoolean();
distortionParameters.averageOrthoDist= gd.getNextNumber();
distortionParameters.averageOrthoWeight= gd.getNextNumber();
distortionParameters.averageDiagDist= gd.getNextNumber();
distortionParameters.averageDiagWeight= gd.getNextNumber();
distortionParameters.useQuadratic= gd.getNextBoolean();
distortionParameters.removeLast= gd.getNextBoolean();
distortionParameters.numberExtrapolated=(int) gd.getNextNumber();
distortionParameters.extrapolationSigma= gd.getNextNumber();
distortionParameters.minUVSpan= gd.getNextNumber();
distortionParameters.flatFieldCorrection= gd.getNextBoolean();
distortionParameters.flatFieldExtarpolate= gd.getNextNumber();
distortionParameters.flatFieldBlur= gd.getNextNumber();
distortionParameters.flatFieldMin= gd.getNextNumber();
distortionParameters.flatFieldShrink= gd.getNextNumber();
distortionParameters.flatFieldExpand= gd.getNextNumber();
distortionParameters.flatFieldSigmaRadius= gd.getNextNumber();
distortionParameters.flatFieldExtraRadius= gd.getNextNumber();
distortionParameters.averagingAreaScale= gd.getNextNumber();
distortionParameters.legacyMode= gd.getNextBoolean();
distortionParameters.loop_debug_level= (int) gd.getNextNumber();
mdl[0]= (int) gd.getNextNumber();
return true;
}
private int makePowerOfTwo(int v) {
int v2 = 1;
for (int i=v; i > 1; i>>=1 ) v2 <<=1; /* make it to be power of 2 */
return v2;
}
public DistortionParameters(int correlationSize, int correlationSizeLwir, int maximalCorrelationSize,
int maximalCorrelationSizeLwir, double correlationGaussWidth, boolean absoluteCorrelationGaussWidth,
int zeros, int FFTSize, int FFTSize_lwir, int FFTOverlap, int FFTOverlap_lwir, double fftGaussWidth,
......
......@@ -1407,6 +1407,10 @@ import ij.gui.GenericDialog;
return eyesisSubCameras[0][ncam].isLWIR();
}
public int getSensorType(int ncam) {
return eyesisSubCameras[0][ncam].isLWIR()? 1 : 0;
}
/**
* Setting default camera geometry parameters for LWIR16 prototype system
* @return false if number of cameras is not 20
......
......@@ -44,6 +44,7 @@ public class LwirReaderParameters {
public final static int [] FFC_GROUPS= {1,2,4};
public static final String [] SENSOR_TYPES = {"EO","LWIR"};
public static final String SENSOR_TYPE = "SENSOR_TYPE";
protected static int MAX_LWIR_WIDTH = 1024; //
private boolean parameters_updated = false;
protected String camera_name = "Talon"; // "LWIR16";
......@@ -73,7 +74,6 @@ public class LwirReaderParameters {
protected double eo_gain_rg = 0.7705; // 1.116; halogen/fluorescent
protected double eo_gain_bg = 2.401; // 1.476;
protected boolean [] selected_channels = {true, true, true, true, true, true, true, true};
protected int max_lwir_width = 1024; //
/*
protected double [] eo_exp_corr = {1.0, 1.0, 1.0, 1.0};
protected double [] eo_gcorr_rbgb = {
......@@ -145,11 +145,11 @@ public class LwirReaderParameters {
return 20;
}
public boolean is_LWIR(int width) {
return width <= max_lwir_width;
public static boolean is_LWIR(int width) {
return width <= MAX_LWIR_WIDTH;
}
public boolean is_LWIR(ImagePlus imp){
public static boolean is_LWIR(ImagePlus imp){
// See if image has LwirReaderParameters.SENSOR_TYPE property, then use is_LWIR(String property_value),
// if not - use old width property
if (imp.getProperty("WOI_WIDTH")==null) {
......@@ -160,6 +160,16 @@ public class LwirReaderParameters {
}
return is_LWIR(imp.getWidth());
}
public static int sensorType(ImagePlus imp) {
if (imp.getProperty("WOI_WIDTH")==null) {
EyesisTiff.decodeProperiesFromInfo(imp);
}
if (imp.getProperty(SENSOR_TYPE)!=null) {
return (is_LWIR((String) imp.getProperty(SENSOR_TYPE)))? 1:0;
}
return is_LWIR(imp.getWidth())? 1 : 0;
}
public int getDebugLevel() {
return this.debug_level;
......
......@@ -51,6 +51,22 @@ public class ImagejJp4TiffMulti {
final boolean scale,
final String std) throws IOException, FormatException // std - include non-elphel properties with prefix std
{
return getMultiImages(
urls,
imps,
0.0, // final double timeout_sec,
scale,
std);
}
public ImagePlus [] getMultiImages(
final String [] urls,
final ImagePlus [] imps,
final double timeout_sec,
final boolean scale,
final String std) throws IOException, FormatException // std - include non-elphel properties with prefix std
{
// final ImagePlus [] imps = new ImagePlus [urls.length];
LOGGER.error("Please ignore 'File has length 0 and may be corrupt' - caused by bioformat reading memory file");
final Thread[] threads = newThreadArray(MAX_THREADS);
......
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