Commit 6733a12d authored by Andrey Filippov's avatar Andrey Filippov

Implemented LWIR grids calculation

parent 41b1b50e
......@@ -361,12 +361,15 @@ public class Aberration_Calibration extends PlugInFrame implements ActionListene
public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSimulatedPattern.DistortionParameters(
64, //32, // use 64 for less artifacts, // correlationSize
64, // Maximal correlation size
16, // int correlationSizeLwir,
128, // 64, // Maximal correlation size
16, // int maximalCorrelationSizeLwir,
0.75,// reduce to 0.5 when correlationSize==64 // correlationGaussWidth
false, // boolean absoluteCorrelationGaussWidth=false; // do not scale correlationGaussWidth when the FFT size is increased
0, //zeros - // leave this number of zeros on the margins of the window (toatal from both sides). If correlationGaussWidth>0 will
// additionally multiply by Hamming
128, // FFT size
256, // FFTSize (was 128)
32, // FFTSize_lwir
0.5, //fftGaussWidth
0.0, //phaseCorrelationFraction
1.5, // 2.5, //6.0, // 2.0, // 0.0, // correlationHighPassSigma, - pixels in frequency domain
......@@ -385,7 +388,8 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
0.1, // contrastSelectSigma, // Gaussian sigma to select correlation centers (fraction of UV period), 0.1
0.5, //contrastAverageSigma, // Gaussian sigma to average correlation variations (as contrast reference) 0.5
150, // minimalPatternCluster minimal pattern cluster size (0 - disable retries)
40, // 150, // minimalPatternCluster minimal pattern cluster size (0 - disable retries)
10, // 150, // minimalPatternClusterLwir minimal pattern cluster size (0 - disable retries)
2.0, // scaleMinimalInitialContrast increase/decrease minimal contrast if initial cluster is >0 but less than minimalPatternCluster
0.5, // when searching for grid, step this amount of the FFTSize
4, // public int patternSubdiv;
......@@ -1417,10 +1421,9 @@ if (MORE_BUTTONS) {
// matchSimulatedPattern.invalidateFlatFieldForGrid(); //It is already reset, no need to do it again
// matchSimulatedPattern.invalidateFocusMask();
matchSimulatedPattern.calculateDistortions(
null, // LwirReaderParameters lwirReaderParameters,
DISTORTION, //
PATTERN_DETECT,
PATTERN_DETECT.minGridPeriod/2,
PATTERN_DETECT.maxGridPeriod/2,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
......@@ -1815,10 +1818,9 @@ if (MORE_BUTTONS) {
// matchSimulatedPattern.invalidateFlatFieldForGrid(); //It is already reset, no need to do it again
// matchSimulatedPattern.invalidateFocusMask();
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
null, // LwirReaderParameters lwirReaderParameters,
DISTORTION, //
PATTERN_DETECT,
PATTERN_DETECT.minGridPeriod/2,
PATTERN_DETECT.maxGridPeriod/2,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
......@@ -9416,10 +9418,6 @@ if (MORE_BUTTONS) {
}
/* ======================================================================== */
if (label.equals("LWIR grids")) {
// if ((LASER_POINTERS==null) || (LASER_POINTERS.laserUVMap.length==0)){
// IJ.showMessage("Laser pointer data needed for this function is not provided");
// return;
// }
calculateLwirGrids();
return;
}
......@@ -9449,23 +9447,20 @@ if (MORE_BUTTONS) {
matchSimulatedPattern.debugLevel=MASTER_DEBUG_LEVEL;
String [] sourceSetList = DISTORTION_PROCESS_CONFIGURATION.selectSourceSets();
LWIR_PARAMETERS.selectSourceChannels();
boolean [] sel_chn = LWIR_PARAMETERS.getSelectedVnir(); // start with regular cameras only
// boolean [] sel_chn = LWIR_PARAMETERS.getSelectedVnir(); // start with regular cameras only
boolean [] sel_chn = LWIR_PARAMETERS.getSelected();
int numFiles = LWIR_PARAMETERS.getSourceFilesFlat(sourceSetList, sel_chn).length; // just the number
String [][] sourceFilesList=LWIR_PARAMETERS.getSourceFiles(sourceSetList, sel_chn);
// String [] sourceFilesList=DISTORTION_PROCESS_CONFIGURATION.selectSourceFiles(); // select files - with/without dialog
boolean saveGrids=DISTORTION_PROCESS_CONFIGURATION.saveGridImages;
boolean overwriteGrids=DISTORTION_PROCESS_CONFIGURATION.overwriteResultFiles;
if (sourceSetList==null) return;
showPatternMinMaxPeriodDialog(PATTERN_DETECT, true);
int this_file = 0;
// if (DEBUG_LEVEL <100) return;
int saved_file = 0;
int in_file = 0;
String gridDir=DISTORTION_PROCESS_CONFIGURATION.selectGridFileDirectory(
true,DISTORTION_PROCESS_CONFIGURATION.gridDirectory,true);
if (gridDir == null) saveGrids=false; // do not ask about the next ones too
for (int nset = 0; nset < sourceFilesList.length; nset++){
String set_name = sourceSetList[nset];
int i = set_name.lastIndexOf(Prefs.getFileSeparator());
......@@ -9481,11 +9476,12 @@ if (MORE_BUTTONS) {
}
for (int nfile = 0; nfile < sourceFilesList[nset].length; nfile++) if (sourceFilesList[nset][nfile] != null){
in_file++;
long startFileTime=System.nanoTime();
if (DEBUG_LEVEL>0){
System.out.println(IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+"s: Processing set "+(nset+1) +" (of "+
sourceFilesList.length+"), channel # "+(nfile + 1)+
" (of "+ sourceFilesList[nset].length+"), file " +(this_file + 1)+" (of "+ numFiles+ ") - "+sourceFilesList[nset][nfile]);
" (of "+ sourceFilesList[nset].length+"), file "+in_file+" (of "+ numFiles+ ") success in "+saved_file+" - "+sourceFilesList[nset][nfile]);
}
String grid_path = null;
if (saveGrids && !overwriteGrids){ // check if result already exists
......@@ -9506,11 +9502,11 @@ if (MORE_BUTTONS) {
matchSimulatedPattern.invalidateFlatFieldForGrid(); //Reset Flat Field calibration - different image.
matchSimulatedPattern.invalidateFocusMask();
boolean is_lwir = LWIR_PARAMETERS.is_LWIR(imp_sel);
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
LWIR_PARAMETERS, // LwirReaderParameters lwirReaderParameters,
DISTORTION, //
PATTERN_DETECT,
PATTERN_DETECT.minGridPeriod/2,
PATTERN_DETECT.maxGridPeriod/2,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
......@@ -9526,7 +9522,7 @@ if (MORE_BUTTONS) {
if (DEBUG_LEVEL>1) System.out.println("numAbsolutePoints="+numAbsolutePoints);
if ((numAbsolutePoints==DISTORTION.errPatternNotFound) || (numAbsolutePoints==DISTORTION.errTooFewCells)) {
if (DEBUG_LEVEL>0) System.out.println("Grid "+(this_file+1)+" not found or too small ("+numAbsolutePoints+"), wasted "+
if (DEBUG_LEVEL>0) System.out.println("Grid "+(in_file)+" not found or too small ("+numAbsolutePoints+"), wasted "+
IJ.d2s(0.000000001*(System.nanoTime()-startFileTime),3)+" seconds )\n");
if (this.SYNC_COMMAND.stopRequested.get()>0) {
System.out.println("User requested stop");
......@@ -9561,7 +9557,7 @@ if (MORE_BUTTONS) {
}
}
}
if (DEBUG_LEVEL>0) System.out.println("Grid "+(this_file+1)+" calculation done at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+" (in "+
if (DEBUG_LEVEL>0) System.out.println("Grid "+(saved_file+1)+" calculation done at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+" (in "+
IJ.d2s(0.000000001*(System.nanoTime()-startFileTime),3)+"s )\n");
//
......@@ -9569,7 +9565,7 @@ if (MORE_BUTTONS) {
System.out.println("User requested stop");
break;
}
this_file++;
saved_file++;
}
}
if (DEBUG_LEVEL>0) System.out.println(((this.SYNC_COMMAND.stopRequested.get()>0)?"Partial (interrupted by user) set of grids":"All")+ " grids calculation done at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
......@@ -9628,10 +9624,9 @@ if (MORE_BUTTONS) {
matchSimulatedPattern.invalidateFlatFieldForGrid(); //Reset Flat Field calibration - different image.
matchSimulatedPattern.invalidateFocusMask();
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
LWIR_PARAMETERS, // LwirReaderParameters lwirReaderParameters,,
DISTORTION, //
PATTERN_DETECT,
PATTERN_DETECT.minGridPeriod/2,
PATTERN_DETECT.maxGridPeriod/2,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
......@@ -9733,12 +9728,10 @@ if (MORE_BUTTONS) {
imp_sel); // reuse the same image window
//Remove for old method?
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
matchSimulatedPattern.calculateDistortions(
LWIR_PARAMETERS,
DISTORTION, //
PATTERN_DETECT,
PATTERN_DETECT.minGridPeriod/2,
PATTERN_DETECT.maxGridPeriod/2,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
......@@ -17208,7 +17201,8 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
null, // no mesh distortion here
thisSimulParameters.subdiv,// SIMUL.subdiv, - do not need high quality here
size,
true); // center for greens
true, // center for greens
false);//boolean mono
sim_pix= simulationPattern.extractSimulPatterns (
thisSimulParameters,
1,
......@@ -17783,7 +17777,8 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
distortedPattern[2], //
simulParameters.subdiv,
fft_size,
simulParameters.center_for_g2);
simulParameters.center_for_g2,
false);//boolean mono
wVectors[0][0]=2.0*distortedPattern[0][0]/subpixel;
wVectors[0][1]=2.0*distortedPattern[0][1]/subpixel;
wVectors[1][0]=2.0*distortedPattern[1][0]/subpixel;
......@@ -17835,7 +17830,8 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
simCorr, //
simulParameters.subdiv,
fft_size,
simulParameters.center_for_g2);
simulParameters.center_for_g2,
false);//boolean mono
}
simul_pixels= simulationPattern.extractSimulPatterns (
simulParameters,
......@@ -20302,10 +20298,13 @@ 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 detection only):", distortionParameters.FFTSize, 0); // 128
gd.addNumericField("FFTSize (Initial pattern detection only):", distortionParameters.FFTSize, 0); // 256
gd.addNumericField("FFTSize for LWIR sensors):", distortionParameters.FFTSize_lwir, 0); // 32
gd.addNumericField("FFT Gaussian width (relative):", distortionParameters.fftGaussWidth, 3);
gd.addNumericField("Correlation size:", distortionParameters.correlationSize, 0); // 64
gd.addNumericField("Maximal correlation size:", distortionParameters.maximalCorrelationSize, 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);
......@@ -20330,20 +20329,21 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
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);
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);
gd.addNumericField("Blur pattern bitmap (sigma): ", distortionParameters.bPatternSigma, 3,5,"pattern cell");
gd.addNumericField("Blur pattern (sigma): ", distortionParameters.barraySigma, 3,5,"sensor pix");
gd.addNumericField("Correlation weights (around maximum):", distortionParameters.correlationWeightSigma, 3,5,"nodes");
gd.addNumericField("Correlation radius scale (0 - sharp sigma)", distortionParameters.correlationRadiusScale, 1,3,"sigmas");
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");
gd.addNumericField("Correlation maximum calculation threshold", distortionParameters.correlationThreshold*100, 2,5,"%");
gd.addNumericField("Interpolate correlation (FFT*linear)", distortionParameters.correlationSubdiv, 0,1,"x");
gd.addNumericField("Interpolate correlation with FFT", distortionParameters.correlationFFTSubdiv, 0,1,"x");
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);
......@@ -20386,19 +20386,18 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
distortionParameters.FFTSize=1;
for (i=(int) gd.getNextNumber(); i >1; i>>=1) distortionParameters.FFTSize <<=1; /* make it to be power of 2 */
distortionParameters.FFTSize = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.FFTSize_lwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.fftGaussWidth= gd.getNextNumber();
distortionParameters.correlationSize=1;
for (i=(int) gd.getNextNumber(); i >1; i>>=1) distortionParameters.correlationSize <<=1; /* make it to be power of 2 */
distortionParameters.maximalCorrelationSize=1;
for (i=(int) gd.getNextNumber(); i >1; i>>=1) distortionParameters.maximalCorrelationSize <<=1; /* make it to be power of 2 */
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.phaseCorrelationFraction= gd.getNextNumber();
distortionParameters.correlationHighPassSigma= gd.getNextNumber();
distortionParameters.correlationLowPassSigma= gd.getNextNumber();
distortionParameters.correlationMaxOffset= gd.getNextNumber();
distortionParameters.correlationRingWidth= gd.getNextNumber();
......@@ -20414,6 +20413,8 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
distortionParameters.contrastAverageSigma= gd.getNextNumber();
distortionParameters.minimalPatternCluster=(int) gd.getNextNumber();
distortionParameters.minimalPatternClusterLwir=(int) gd.getNextNumber();
distortionParameters.scaleMinimalInitialContrast=gd.getNextNumber();
distortionParameters.searchOverlap= gd.getNextNumber();
......@@ -20460,6 +20461,12 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
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;
}
/* ======================================================================== */
/* ======================================================================== */
public boolean showGaussianStackDialog(EyesisAberrations.InverseParameters inverseParameters) {
......@@ -1278,10 +1278,11 @@ public class EyesisAberrations {
}
int rslt=matchSimulatedPattern.calculateDistortions(
null, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
patternDetectParameters.maxGridPeriod/2,
// patternDetectParameters.minGridPeriod/2,
// patternDetectParameters.maxGridPeriod/2,
simulParameters,
colorComponents.equalizeGreens,
imp,
......@@ -2709,7 +2710,8 @@ public class EyesisAberrations {
distortedPattern[2], //
simulParameters.subdiv,
fft_size,
simulParameters.center_for_g2);
simulParameters.center_for_g2,
false);//boolean mono
wVectors[0][0]=2.0*distortedPattern[0][0]/subpixel;
wVectors[0][1]=2.0*distortedPattern[0][1]/subpixel;
wVectors[1][0]=2.0*distortedPattern[1][0]/subpixel;
......@@ -2752,7 +2754,8 @@ public class EyesisAberrations {
simCorr, //
simulParameters.subdiv,
fft_size,
simulParameters.center_for_g2);
simulParameters.center_for_g2,
false);//boolean mono
}
// simul_pixels= simulationPattern.extractSimulPatterns (
simul_pixels= simulationPattern.extractSimulPatterns (
......
......@@ -665,11 +665,12 @@ horizontal axis:
boolean noMessageBoxes=true;
int numAbsolutePoints = matchSimulatedPattern.calculateDistortions(
null, // LwirReaderParameters lwirReaderParameters, // null is OK
// allow more of grid around pointers?
distortionParameters, //
this.patternDetectParameters,
this.patternDetectParameters.minGridPeriod/2,
this.patternDetectParameters.maxGridPeriod/2,
// this.patternDetectParameters.minGridPeriod/2,
// this.patternDetectParameters.maxGridPeriod/2,
simulParameters,
equalizeGreens, imp_eq,
this.laserPointers, // null, //LASER_POINTERS, //
......@@ -840,11 +841,12 @@ horizontal axis:
// matchSimulatedPatterns[numSensor].getChannel(images[numSensor])+" ");
int numAbsolutePoints = this.matchSimulatedPatterns[numSensor].calculateDistortions(
null, // LwirReaderParameters lwirReaderParameters, // null is OK
// allow more of grid around pointers?
distortionParameters, //
this.patternDetectParameters,
this.patternDetectParameters.minGridPeriod/2,
this.patternDetectParameters.maxGridPeriod/2,
// this.patternDetectParameters.minGridPeriod/2,
// this.patternDetectParameters.maxGridPeriod/2,
simulParameters,
equalizeGreens, imp_eq,
this.laserPointers, // null, //LASER_POINTERS, //
......
......@@ -99,6 +99,7 @@ public class LensAdjustment {
ImagePlus imp_eq=matchSimulatedPattern.applyFlatField (imp); // will throw if image size mismatch
if (updating) {
double maxActualCorr= matchSimulatedPattern.refineDistortionCorrelation (
null, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters,
simulParameters,
......@@ -132,7 +133,8 @@ public class LensAdjustment {
System.out.println("updateFocusGrid(), number of already defined grid cells (before distortions()) = "+matchSimulatedPattern.numDefinedCells());
}
matchSimulatedPattern.distortions(
null, // is not used in update mode
null, //LwirReaderParameters lwirReaderParameters, // null is OK
null, // final boolean [] triedIndices, // is not used in update mode
distortionParameters, //
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
......@@ -157,10 +159,11 @@ public class LensAdjustment {
// matchSimulatedPattern.invalidateFlatFieldForGrid(); //Keep these!
// matchSimulatedPattern.invalidateFocusMask();
numAbsolutePoints=matchSimulatedPattern.calculateDistortions( // allow more of grid around pointers?
null, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
patternDetectParameters.maxGridPeriod/2,
// patternDetectParameters.minGridPeriod/2,
// patternDetectParameters.maxGridPeriod/2,
simulParameters,
equalizeGreens,
imp_eq,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -35,11 +35,11 @@ import ij.IJ;
*/
public class SimulationPattern {
// private double [] bPattern; // pattern bitmap (does not change)
// private double[][] barray; // high resolution boolean pattern array (specific to distortions in each area)
// private double [] bPattern; // pattern bitmap (does not change)
// private double[][] barray; // high resolution boolean pattern array (specific to distortions in each area)
public double [] bPattern=null; // pattern bitmap (does not change)
public int bPatternSize=0;
/// public double[][] barray; // high resolution boolean pattern array (specific to distortions in each area)
/// public double[][] barray; // high resolution boolean pattern array (specific to distortions in each area)
public double[] barray; // high resolution boolean pattern array (specific to distortions in each area)
public double bPatternSigma=0.0;
public double barraySigma=0.0;
......@@ -116,10 +116,10 @@ public class SimulationPattern {
break;
default: for (index=0;index<this.bPattern.length;index++) this.bPattern[index]=1.0;
}
// blur pattern
// blur pattern
if (this.bPatternSigma>0) {
if (this.bPatternSigma>0.25) this.bPatternSigma=0.25;
// 1 - add margins around the pattern
// 1 - add margins around the pattern
int i1,j1;
int margin= (int) Math.ceil(3*size*this.bPatternSigma);
int sizeM=size+2*margin;
......@@ -134,11 +134,11 @@ public class SimulationPattern {
bPatternM[i*sizeM+j]= (invertX ^ invertY)?(1.0-this.bPattern[i1*size+j1]):this.bPattern[i1*size+j1];
}
}
// apply blur
// apply blur
if (this.debugLevel>3) SDFA_INSTANCE.showArrays(bPatternM,sizeM,sizeM, "bPatternM");
this.gb.blurDouble(bPatternM,sizeM,sizeM,size*this.bPatternSigma,size*this.bPatternSigma, 0.01);
if (this.debugLevel>3) SDFA_INSTANCE.showArrays(bPatternM,sizeM,sizeM, "bPatternM-blured");
// remove margins
// remove margins
for (i=0;i<size;i++) for (j=0;j<size;j++) {
this.bPattern[i*size+j]= bPatternM[(i+margin)*sizeM+(j+margin)];
}
......@@ -146,7 +146,7 @@ public class SimulationPattern {
return this.bPattern;
}
/* ======================================================================== */
/* ======================================================================== */
public void simulatePatternFullPattern(
double freqX1,
double freqY1,
......@@ -157,7 +157,8 @@ public class SimulationPattern {
double [] corr,
int subdiv,
int size,
boolean center_for_g2) {
boolean center_for_g2,
boolean mono) {// takes precedence over center_for_g2, makes symmetrical around center of array (between pixels)
this.barray=simulatePatternFullPatternSafe(
freqX1,
freqY1,
......@@ -168,7 +169,9 @@ public class SimulationPattern {
corr,
subdiv,
size,
center_for_g2);
center_for_g2,
mono);
}
......@@ -182,7 +185,8 @@ public class SimulationPattern {
double [] corr,
int subdiv,
int size,
boolean center_for_g2) {
boolean center_for_g2,
boolean mono) {// takes precedence over center_for_g2, makes symmetrical around center of array (between pixels)
int patternSize= (this.bPattern!=null)?((int) Math.sqrt(this.bPattern.length)):0;
double twicePatternSize=2*patternSize;
int i,j;
......@@ -211,12 +215,16 @@ public class SimulationPattern {
double [] phases={phase1/(Math.PI*2)+0.25,phase2/(Math.PI*2)+0.25}; // period=1.0;
int iu,iv;
boolean invert;
for (i=0;i<fullSize;i++) {
yl=(i-0.5*fullSize)/subdiv-(center_for_g2?0.5:1.0); // center in the middle of Bayer
for (j=0;j<fullSize;j++) {
xl=(j-0.5*fullSize)/subdiv-(center_for_g2?0.5:1.0); // center in the middle of Bayer
/* apply second order polynomial correction to x,y
double offset = mono? 0.0: ((center_for_g2?0.5:1.0));
double center = 0.5*fullSize; // +(mono?-0.5: 0.0); // see if it is needed!
// in mono mode result barray is symmetrical around [fullSize/2,fullSize/2], but
// after extractSimulMono result will be symmetrical around [size/2-0.5, size/2 - 0.5]
for (i=0; i<fullSize; i++) {
yl=(i - center) / subdiv - offset; // center in the middle of Bayer
for (j=0; j<fullSize; j++) {
xl=(j - center) / subdiv - offset; // center in the middle of Bayer
/* apply second order polynomial correction to x,y
x=xl+Ax*xl^2+Bx*yl^2+2*Cx*xl*yl;
y=xl+Ay*xl^2+By*yl^2+2*Cy*xl*yl; */
if (corr==null) {
......@@ -256,7 +264,7 @@ public class SimulationPattern {
}
}
}
// Blur barray pattern if sigma >0
// Blur barray pattern if sigma >0
if (this.barraySigma>0) {
double sigma=this.barraySigma*subdiv; //*/ 2?
if (this.debugLevel>3) SDFA_INSTANCE.showArrays(localBarray, "localBarray");
......@@ -265,7 +273,7 @@ public class SimulationPattern {
}
return localBarray;
}
/* ======================================================================== */
/* ======================================================================== */
public double [] recursiveFillPixels ( // invert pattern in the caller, return signed value (-1..1 - pattern is 0..1)
SimulParameters simulParameters,
double [] xy, // top-left corner
......@@ -273,7 +281,7 @@ public class SimulationPattern {
double [][][] cornersXY, // xy pairs for the 4 corners of the square in UV (pattern) coordinates (u0v0,u1v0,u0v1,u1v1)
double [] uv, // UV value for the top-left corner (matching cornersXY[0][0])
double [] duv, // distances to the opposite corner in UV
// final boolean maskOnly, // just mark defined cells
// final boolean maskOnly, // just mark defined cells
int debug
){ //use this.bPattern, this.bPatternSize (side of the square)
......@@ -289,7 +297,7 @@ public class SimulationPattern {
}
if (debug>21){
String dbgStr="";
// IJ.d2s(quarter_patterns[iq][0][0],4)
// IJ.d2s(quarter_patterns[iq][0][0],4)
dbgStr+="xy={"+IJ.d2s(xy[0],2)+","+IJ.d2s(xy[1],2)+"} ";
dbgStr+=" dxy={"+IJ.d2s(dxy[0],2)+","+IJ.d2s(dxy[1],2)+"} ";
dbgStr+=" uv={"+IJ.d2s(uv[0],2)+","+IJ.d2s(uv[1],2)+"} ";
......@@ -307,25 +315,25 @@ public class SimulationPattern {
}
if (numInside==0) return result; // all corners outside of the (sub)pattern cell
// if (maskOnly) {
// if (maskOnly) {
if (simulParameters==null) {
result[1]=dxy[0]*dxy[1];
result[0]=result[1];
return result;
}
// recalculate to the full uv
// recalculate to the full uv
boolean cornersInvert;
double [][] cornerValue=new double [2][2];
int [] iPat=new int [2];
double min=1.0,max=-1.0;
for (int i=0;i<2;i++) for (int j=0;j<2;j++) {
// cornersUV[i][j][0]=uv[0]+j*cornersUV[i][j][0]*duv[0];
// cornersUV[i][j][1]=uv[1]+i*cornersUV[i][j][1]*duv[1];
// cornersUV[i][j][0]=uv[0]+j*cornersUV[i][j][0]*duv[0];
// cornersUV[i][j][1]=uv[1]+i*cornersUV[i][j][1]*duv[1];
cornersUV[i][j][0]=uv[0]+cornersUV[i][j][0]*duv[0];
cornersUV[i][j][1]=uv[1]+cornersUV[i][j][1]*duv[1];
cornersInvert=false;
for (int k=0;k<2;k++) {
// iPat[k] = (int) Math.floor(cornersUV[i][j][k]*this.bPatternSize*2.0); // 0.5 ->bPatternSize
// iPat[k] = (int) Math.floor(cornersUV[i][j][k]*this.bPatternSize*2.0); // 0.5 ->bPatternSize
iPat[k] = (int) Math.floor(cornersUV[i][j][k]*this.bPatternSize); // 1.0 ->bPatternSize
if (iPat[k]<0){
iPat[k]+=this.bPatternSize;
......@@ -347,7 +355,7 @@ public class SimulationPattern {
(dxy[0]>simulParameters.smallestSubPix) &&
(dxy[1]>simulParameters.smallestSubPix)) {
// divide this square into 4 quadrants, return sum of the recursively called method on them
// divide this square into 4 quadrants, return sum of the recursively called method on them
double [][] quadrants={{0.0,0.0},{0.5,0.0},{0.0,0.5},{0.5,0.5}};
double [] subResult;
double [] subxy=new double [2];
......@@ -375,7 +383,7 @@ public class SimulationPattern {
cornersXY, // xy pairs for the 4 corners of the square in UV (pattern) coordinates (u0v0,u1v0,u0v1,u1v1)
uv, // UV value for the top-left corner (matching cornersXY[0][0])
duv, // distances to the opposite corner in UV
// maskOnly, // just mark defined cells //always false - will never get here
// maskOnly, // just mark defined cells //always false - will never get here
debug
);
result[0]+=subResult[0];
......@@ -402,7 +410,7 @@ public class SimulationPattern {
}
return result;
}
/* ======================================================================== */
/* ======================================================================== */
/**
* @param cornersXY first index V, second index U, third index:0 - x, 1-y
* @param xy 0-x,1-y of the point, for which UV should be generated
......@@ -431,7 +439,7 @@ public class SimulationPattern {
double quadThreshold, // if abs(4*a*c)/b^2 is less than this, use linear, not quadratic equations
int debug
) {
/*
/*
x,y -> u,v
(1) x= v*u*Ax + v*Bx + u*Cx + Dx
......@@ -479,26 +487,26 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
double Av=(By*Ax-Bx*Ay);
double Bv=((-Bx*Cy-Ay*Dx+By*Cx+Ax*Dy)+Ay*xy[0]-Ax*xy[1]);
double Cv=(Cy*xy[0]-Cx*xy[1])+(-Cy*Dx+Cx*Dy);
// double [] UV={-Cv/Bv,-Cu/Bu}; // linear solution - use for linear grid
// double [] UV={-Cv/Bv,-Cu/Bu}; // linear solution - use for linear grid
double [] UV={-Cu/Bu,-Cv/Bv}; // linear solution - use for linear grid
double au=0.0,bu=0.0,av=0.0,bv=0.0;
if (Math.abs(Au*Cu)/(Bu*Bu)>quadThreshold) { // use quadratic equation for U
au=-Bu/(2*Au);
bu=Math.sqrt(Bu*Bu-4*Au*Cu)/Math.abs(2*Au);
// Use solution that is closer to linear one
// Use solution that is closer to linear one
if (UV[0]>au) UV[0]=au+bu;
else UV[0]=au-bu;
}
if (Math.abs(Av*Cv)/(Bv*Bv)>quadThreshold) { // use quadratic equation for V
av=-Bv/(2*Av);
bv=Math.sqrt(Bv*Bv-4*Av*Cv)/Math.abs(2*Av);
// Use solution that is closer to linear one
// Use solution that is closer to linear one
if (UV[1]>av) UV[1]=av+bv;
else UV[1]=av-bv;
}
if (debug>2){
String dbgStr="";
// IJ.d2s(quarter_patterns[iq][0][0],4)
// IJ.d2s(quarter_patterns[iq][0][0],4)
dbgStr+=" Ax="+IJ.d2s(Ax,5)+", Bx="+IJ.d2s(Bx,5)+", Cx="+IJ.d2s(Cx,5)+", Dx="+IJ.d2s(Dx,5);
dbgStr+=" Ay="+IJ.d2s(Ay,5)+", By="+IJ.d2s(By,5)+", Cy="+IJ.d2s(Cy,5)+", Dy="+IJ.d2s(Dy,5);
dbgStr+=" Au="+IJ.d2s(Au,5)+", Bu="+IJ.d2s(Bu,5)+", Cu="+IJ.d2s(Cu,5);
......@@ -511,7 +519,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
return UV;
}
/* ======================================================================== */
/* ======================================================================== */
private boolean isCellValid(
double [][][][] grid,
int [] uv){
......@@ -521,14 +529,14 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
}
return false;
}
/*
/*
private boolean isCellDefined(
double [][][][] grid,
int [] uv){
return ((uv[1]>=0) && (uv[0]>=0) && (uv[1]<grid.length) && (uv[0]<grid[uv[1]].length) &&
(grid[uv[1]][uv[0]]!=null) && (grid[uv[1]][uv[0]][0]!=null));
}
*/
*/
public float [] combineWithCanvas(
double canvasFill,
int width,
......@@ -588,25 +596,25 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
}
return canvas;
}
//===================== Moved from Aberration_Calibration
//===================== Moved from Aberration_Calibration
public float[][] simulateGridAll (
int width, // extend to full image, width, height - original (not scaled) image size
int height,
MatchSimulatedPattern matchSimulatedPattern,
// double [][][][] patternGrid, // should be aligned to gridFrac
// double [][][][] patternGrid, // should be aligned to gridFrac
int gridFrac, // number of grid steps per pattern full period
SimulParameters simulParameters,
int threadsMax,
boolean updateStatus,
int globalDebugLevel,
int debug_level){// debug level used inside loops
// SimulationPattern simulationPattern=new SimulationPattern(simulParameters);
// SimulationPattern simulationPattern=new SimulationPattern(simulParameters);
float [][] simArray0=simulateGridAll (
matchSimulatedPattern,
// patternGrid, // should be aligned to gridFrac
// patternGrid, // should be aligned to gridFrac
gridFrac, // number of grid steps per pattern full period
simulParameters,
// simulationPattern,
// simulationPattern,
threadsMax,
updateStatus,
globalDebugLevel,
......@@ -624,17 +632,17 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
public float[][] simulateGridAll (
MatchSimulatedPattern matchSimulatedPattern,
// double [][][][] patternGrid, // should be aligned to gridFrac
// double [][][][] patternGrid, // should be aligned to gridFrac
int gridFrac, // number of grid steps per pattern full period
SimulationPattern.SimulParameters simulParameters,
// SimulationPattern simulationPattern, // or null
// SimulationPattern simulationPattern, // or null
int threadsMax,
boolean updateStatus,
int globalDebugLevel,
int debug_level){// debug level used inside loops
long startTime=System.nanoTime();
double [][] xy0={{simulParameters.offsetX,simulParameters.offsetY},{simulParameters.offsetX-0.5,simulParameters.offsetY-0.5}} ;
// if (simulationPattern==null) simulationPattern=new SimulationPattern(simulParameters);
// if (simulationPattern==null) simulationPattern=new SimulationPattern(simulParameters);
float[][] simArray=new float[2][];
simArray[0]= simulateGrid (
matchSimulatedPattern.getDArray(),
......@@ -661,7 +669,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
return simArray;
}
//========================
//========================
public float [] simulateGrid (
final double [][][][] patternGrid, // should be aligned to gridFrac
final int gridFrac, // number of grid steps per pattern full period: black+white
......@@ -669,7 +677,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
final Rectangle woi,
final int subdiv, // subdivide output array from woi (normally 2)
double[] shift_xy, // add to patterGrid xy, null OK
// final boolean maskOnly, // just mark defined cells
// final boolean maskOnly, // just mark defined cells
final int threadsMax,
final boolean updateStatus,
final int debug_level){// debug level used inside loops
......@@ -705,8 +713,9 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
cellNum.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
// String dbgStr="";
// String dbgStr="";
int [][][] iUV=new int [2][2][2];
double [][][] dUV=new double [2][2][2];
double [][][] xy=new double [2][2][2];
......@@ -764,7 +773,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
for (int iy=rcell.y;iy<(rcell.y+rcell.height);iy++) for (int ix=rcell.x;ix<(rcell.x+rcell.width);ix++)
if (woiOut.contains (ix,iy))
{
double [] pixXY={(double) ix,(double) iy};
double [] pixXY={ix,iy};
double [] pixData=recursiveFillPixels ( // invert pattern in the caller, return signed value (-1..1 - pattern is 0..1)
simulParameters,
pixXY, // top-left corner
......@@ -811,6 +820,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
}
final int numFinished=finishedAtomic.getAndIncrement();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
IJ.showProgress(numFinished,cellsToProcess);
}
......@@ -823,8 +833,8 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
startAndJoin(threads);
}
for (int i=0;i<pixels.length;i++ ) {
// /(simulParameters!=null)
// if (maskOnly) {
// /(simulParameters!=null)
// if (maskOnly) {
if (simulParameters==null) {
if (pixelsDenom[i]==0.0F) pixels[i]=-1;
} else {
......@@ -868,9 +878,9 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
}
}
/* ======================================================================== */
/* make it faster when outSubdiv =2*n (usually so) */
/* TODO: cleanup shifts - they seem now to work correctly */
/* ======================================================================== */
/* make it faster when outSubdiv =2*n (usually so) */
/* TODO: cleanup shifts - they seem now to work correctly */
public double [][] extractSimulPatterns (
SimulParameters simulParameters,
int outSubdiv, // subdivide output pixels
......@@ -949,7 +959,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
}
} else { // just reuse available greens
if (this.debugLevel>2)System.out.println("Generating combined greens pattern from individual greens");
/* now combine greens - same as in splitBayer() */
/* now combine greens - same as in splitBayer() */
int base, base_b;
base_b=0;
......@@ -984,6 +994,69 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
return simul_pixels;
}
public double [] extractSimulMono (
SimulParameters simulParameters,
int outSubdiv, // subdivide output pixels
int size, // number of Bayer cells in width of the square selection (half number of pixels)
double x0, // selection center, X (in pixels)
double y0) {
return extractSimulMono (
this.barray,
simulParameters,
outSubdiv, // subdivide output pixels
size, // number of Bayer cells in width of the square selection (half number of pixels)
x0, // selection center, X (in pixels)
y0);
}
public double [] extractSimulMono ( // TODO: can use twice smaller barray
double [] localbArray,
SimulParameters simulParameters,
int outSubdiv, // subdivide output pixels - now 4
int size, // number of Bayer cells in width of the square selection (half number of pixels)
double x0, // selection center, X (in pixels)
double y0) {
int sampleWidth=(int) (Math.sqrt(simulParameters.fill)*simulParameters.subdiv);
int sampleN=sampleWidth*sampleWidth;
if (sampleWidth<1) sampleWidth=1;
else if (sampleWidth>simulParameters.subdiv)sampleWidth=simulParameters.subdiv;
double sampleAverage=0.5*sampleN;
int fullSize=(int) Math.sqrt(localbArray.length);
double [] simul_pixels=new double [size*size];
int ix,iy, iy0,ix0,px,py;
double s;
double span=((double) size)/outSubdiv;
int sampLow=-sampleWidth/2;
int sampHigh=sampLow+sampleWidth;
for (iy=0;iy<size;iy++) {
iy0=(fullSize/2) + (int) (( -span/2 + y0 + 0.5 + 1.0 * iy / outSubdiv)*simulParameters.subdiv);
for (ix=0;ix<size;ix++) {
ix0=(fullSize/2) + (int) ((-span/2 + x0 + 0.5 + 1.0 * ix / outSubdiv)*simulParameters.subdiv);
s=0.0;
for (py=iy0+sampLow;py<iy0+sampHigh;py++) for (px=ix0+sampLow;px<ix0+sampHigh;px++) {
try {
s+=localbArray[py*fullSize+px];
} catch (Exception e){
System.out.println("Bug in extractSimulMono(): px="+px+" py="+py+" fullSize="+fullSize+" size="+size+" x0="+x0+" y0="+y0);
e.printStackTrace();
return null;
}
}
simul_pixels[iy*size+ix]= (s-sampleAverage)/sampleAverage;
}
}
if (this.debugLevel>2) {
System.out.println("extractSimulMono, x0="+x0+" y0="+y0+" fullSize="+fullSize+" size="+size+" subdiv="+simulParameters.subdiv+" outSubdiv="+outSubdiv);
System.out.println(" sampLow="+sampLow+" sampHigh="+sampHigh+" span="+span+" size="+size);
s=0.0;
for (int i=0;i<simul_pixels.length;i++) s+=simul_pixels[i];
System.out.println("sum of pixels="+s);
}
if (this.debugLevel>2) SDFA_INSTANCE.showArrays(simul_pixels,size,size, "SIMUL");
return simul_pixels;
}
private double [] matrix2x2_mul(double [][] a, double [] b ){
double [] rslt={a[0][0]*b[0]+a[0][1]*b[1],
a[1][0]*b[0]+a[1][1]*b[1]};
......@@ -1019,8 +1092,8 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
if (colorComp==4) { // checkerboard greens
r.y+=r.width/2; // now it is the "top left" corner of the diagonal greens
for (index=0;index<result.length;index++){
// int iy=r.y+(index / r.width);
// int ix=r.x+(index % r.width);
// int iy=r.y+(index / r.width);
// int ix=r.x+(index % r.width);
int iyi=index / r.width;
int ixi=index % r.width;
int iy=r.y+(iyi+ixi)/2 -ixi;
......@@ -1052,7 +1125,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
return result;
}
//=====================
//=====================
public static class SimulParameters {
public int patternSize;
public int pattern_type;
......@@ -1115,6 +1188,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
this.offsetY= offsetY;
}
@Override
public SimulParameters clone() {
return new SimulParameters(
this.patternSize,
......
......@@ -32,6 +32,7 @@ import java.util.Properties;
import com.elphel.imagej.common.GenericJTabbedDialog;
import ij.ImagePlus;
import ij.Prefs;
public class LwirReaderParameters {
......@@ -54,6 +55,7 @@ public class LwirReaderParameters {
protected double vnir_gain_rg = 0.7705; // 1.116; halogen/fluorescent
protected double vnir_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 [] vnir_exp_corr = {1.0, 1.0, 1.0, 1.0};
......@@ -79,9 +81,18 @@ public class LwirReaderParameters {
protected boolean show_images = false;
// --- interface methods
public boolean is_LWIR(int width) {
return width <= max_lwir_width;
}
public boolean is_LWIR(ImagePlus imp){
return is_LWIR(imp.getWidth());
}
public int getDebugLevel() {
return this.debug_level;
}
public void setDebugLevel(int level) {
this.debug_level = level;
}
......
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