Commit 4ffb8a32 authored by Andrey Filippov's avatar Andrey Filippov

working on calculating grids for low frequency pattern

parent 78aea970
......@@ -1413,9 +1413,13 @@ Exception in thread "Thread-3564" java.lang.ArrayIndexOutOfBoundsException: 8970
NodeList allNodes=doc.getDocumentElement().getElementsByTagName("*");
for (int i=0;i<allNodes.getLength();i++) {
String name= allNodes.item(i).getNodeName();
String value=allNodes.item(i).getFirstChild().getNodeValue();
imp.setProperty(name, value);
String value="";
try {
value=allNodes.item(i).getFirstChild().getNodeValue();
} catch(Exception e) {
}
imp.setProperty(name, value);
}
return true;
......
......@@ -70,6 +70,7 @@ import com.elphel.imagej.common.WindowTools;
import com.elphel.imagej.jp4.JP46_Reader_camera;
import com.elphel.imagej.lwir.LwirReader;
import com.elphel.imagej.lwir.LwirReaderParameters;
import com.elphel.imagej.readers.EyesisTiff;
import Jama.Matrix; // Download here: http://math.nist.gov/javanumerics/jama/
import ij.IJ;
......@@ -223,9 +224,19 @@ public class Aberration_Calibration extends PlugInFrame implements ActionListene
5.0, // minCorrContrast - discrimination threshold between good and bad pattern correlation
0.0, // minGridPeriod
0.0, // maxGridPeriod
0.0, // minGridPeriodLwir
0.0, // maxGridPeriodLwir
0.0, // debugX+"");
0.0, // debugY+"");
-1.0 // this.debugRadius+"");
-1.0, // this.debugRadius+"");
false, // public boolean use_large_cells = false; // new method based on phase correlation should work with large cells,
// so only first negative correlation (1/2 period) fits in window
0.5, // public double phaseCoeff = 0.5; // "phasiness" of correlation
0.3, // public double lowpass_sigma = 0.3; // for phase correlation - frequency fraction of maximal
0.03, // public double min_frac = 0.03; // do not use higher order autocorrelation if min/max
// is weaker than this fraction of the zero maximum
0.5, //public double min_sin = 0.5; // minimal sine for the angle between two pattern vectors
true //public boolean no_crazy = true; // fail if quadratic approximation fails or returns outside of +/- 1.5
);
......@@ -674,11 +685,11 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
panelConf1 = new Panel();
panelConf1.setLayout(new GridLayout(1, 0, 5, 5));
addButton("Configure Globals",panelConf1);
addButton("Conf. Components",panelConf1);
addButton("Conf. Multifile",panelConf1,color_configure);
addButton("Conf. Simulation",panelConf1);
addButton("Conf. Pattern Detection",panelConf1);
addButton("Configure Globals", panelConf1,color_configure);
addButton("Conf. Components", panelConf1,color_configure);
addButton("Conf. Multifile", panelConf1,color_configure);
addButton("Conf. Simulation", panelConf1,color_configure);
addButton("Conf. Pattern Detection",panelConf1,color_configure);
addButton("Waves",panelConf1);
//WavePatternGenerator
add(panelConf1);
......@@ -994,6 +1005,8 @@ if (MORE_BUTTONS) {
addButton("Configure Goniometer", panelLWIR,color_configure);
addButton("Goniometer Move", panelLWIR,color_debug);
addButton("LWIR Goniometer", panelLWIR,color_conf_process);
addButton("LWIR grids", panelLWIR,color_process);
add(panelLWIR);
pack();
......@@ -1141,7 +1154,7 @@ if (MORE_BUTTONS) {
return;
/* ======================================================================== */
} else if (label.equals("Conf. Pattern Detection")) {
showPatternDetectParametersDialog(PATTERN_DETECT);
showPatternDetectParametersDialog(PATTERN_DETECT, (LWIR_READER != null));
return;
/* ======================================================================== */
} else if (label.equals("Waves")) {
......@@ -1404,6 +1417,8 @@ if (MORE_BUTTONS) {
matchSimulatedPattern.calculateDistortions(
DISTORTION, //
PATTERN_DETECT,
PATTERN_DETECT.minGridPeriod/2,
PATTERN_DETECT.maxGridPeriod/2,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
......@@ -1800,6 +1815,8 @@ if (MORE_BUTTONS) {
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
DISTORTION, //
PATTERN_DETECT,
PATTERN_DETECT.minGridPeriod/2,
PATTERN_DETECT.maxGridPeriod/2,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
......@@ -2567,113 +2584,7 @@ if (MORE_BUTTONS) {
IJ.showMessage("Laser pointer data needed for this function is not provided");
return;
}
long startTime=System.nanoTime();
boolean noMessageBoxes=true;
String prefix="grid-";
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
DISTORTION_PROCESS_CONFIGURATION.debugLevel=MASTER_DEBUG_LEVEL;
if (matchSimulatedPattern==null) matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
matchSimulatedPattern.debugLevel=MASTER_DEBUG_LEVEL;
String [] sourceFilesList=DISTORTION_PROCESS_CONFIGURATION.selectSourceFiles(); // select files - with/without dialog
boolean saveGrids=DISTORTION_PROCESS_CONFIGURATION.saveGridImages;
boolean overwriteGrids=DISTORTION_PROCESS_CONFIGURATION.overwriteResultFiles;
if (sourceFilesList==null) return;
showPatternMinMaxPeriodDialog(PATTERN_DETECT);
for (int numFile=0;numFile<sourceFilesList.length;numFile++){
long startFileTime=System.nanoTime();
if (DEBUG_LEVEL>0){
System.out.println(IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+"s: Processing file # "+(numFile+1)+ " (of "+ sourceFilesList.length+"): "+sourceFilesList[numFile]);
}
if (saveGrids && !overwriteGrids){ // check if result already exists
int i = sourceFilesList[numFile].lastIndexOf('/');
if (i>0){
String path=prefix+sourceFilesList[numFile].substring(i+1);
String srcDir=DISTORTION_PROCESS_CONFIGURATION.selectGridFileDirectory(true,DISTORTION_PROCESS_CONFIGURATION.gridDirectory,true);
if (srcDir==null){
saveGrids=false; // do not ask about the next ones too
} else {
path=DISTORTION_PROCESS_CONFIGURATION.gridDirectory+Prefs.getFileSeparator()+path;
// File rsltFile=new File(path);
if ((new File(path)).exists()){
if (DEBUG_LEVEL>0) System.out.println("-->>> Skipping existing "+path+" (as requested in \"Configure Process Distortions\")");
continue;
}
}
}
}
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?
if (!DISTORTION_PROCESS_CONFIGURATION.useNoPonters && (matchSimulatedPattern.getPointersXY(imp_sel,LASER_POINTERS.laserUVMap.length)==null)) {
if (this.SYNC_COMMAND.stopRequested.get()>0) {
System.out.println("User requested stop");
break;
}
continue; // no pointers in this image
}
// /getPointersXY(ImagePlus imp, int numPointers){ if
// calculate distortion grid for it
matchSimulatedPattern.invalidateFlatFieldForGrid(); //Reset Flat Field calibration - different image.
matchSimulatedPattern.invalidateFocusMask();
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
DISTORTION, //
PATTERN_DETECT,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
LASER_POINTERS, // LaserPointer laserPointer, // LaserPointer object or null
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, //
null, // double [][][] hintGrid, // predicted grid array (or null)
0, // double hintGridTolerance, // allowed mismatch (fraction of period) or 0 - orientation only
THREADS_MAX,
UPDATE_STATUS,
DEBUG_LEVEL,
DISTORTION.loop_debug_level, // debug level
noMessageBoxes);
if (DEBUG_LEVEL>1) System.out.println("numAbsolutePoints="+numAbsolutePoints);
if ((numAbsolutePoints==DISTORTION.errPatternNotFound) || (numAbsolutePoints==DISTORTION.errTooFewCells)) {
if (DEBUG_LEVEL>0) System.out.println("Grid "+(numFile+1)+" 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");
break;
}
continue; // too few cells detected
}
if (DISTORTION_PROCESS_CONFIGURATION.useNoPonters || (numAbsolutePoints>0)){
//Calculate grid contrast and brightness for each color component
matchSimulatedPattern.calcGridIntensities (
DISTORTION, //final DistortionParameters distortionParameters, //
COMPONENTS.equalizeGreens,
imp_sel, // image to process
THREADS_MAX);
ImagePlus imp_calibrated=matchSimulatedPattern.getCalibratedPatternAsImage(imp_sel,prefix, numAbsolutePoints);
if (DISTORTION_PROCESS_CONFIGURATION.showGridImages) imp_calibrated.show();
if (saveGrids){
FileSaver fs=new FileSaver(imp_calibrated);
String srcDir=DISTORTION_PROCESS_CONFIGURATION.selectGridFileDirectory(true,DISTORTION_PROCESS_CONFIGURATION.gridDirectory,true);
if (srcDir==null){
saveGrids=false; // do not ask about the next ones too
} else {
String path=DISTORTION_PROCESS_CONFIGURATION.gridDirectory+Prefs.getFileSeparator()+imp_calibrated.getTitle();
if (UPDATE_STATUS) IJ.showStatus("Saving "+path);
if (DEBUG_LEVEL>0) System.out.println("-->>> Saving "+path+" - using "+numAbsolutePoints+" laser pointer references");
fs.saveAsTiffStack(path);
}
}
}
if (DEBUG_LEVEL>0) System.out.println("Grid "+(numFile+1)+" calculation done at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+" (in "+
IJ.d2s(0.000000001*(System.nanoTime()-startFileTime),3)+"s )\n");
//
if (this.SYNC_COMMAND.stopRequested.get()>0) {
System.out.println("User requested stop");
break;
}
}
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));
calculateGrids();
return;
}
/* ======================================================================== */
......@@ -9506,6 +9417,15 @@ if (MORE_BUTTONS) {
/// POWER_CONTROL.lightsOff();
return;
}
/* ======================================================================== */
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;
}
......@@ -9522,7 +9442,250 @@ if (MORE_BUTTONS) {
/* ======================================================================== */
/* ======================================================================== */
public void calculateLwirGrids() {
long startTime=System.nanoTime();
boolean noMessageBoxes=true;
String prefix="grid-";
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
DISTORTION_PROCESS_CONFIGURATION.debugLevel=MASTER_DEBUG_LEVEL;
if (matchSimulatedPattern==null) matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
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
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;
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());
if (i >=0) set_name = set_name.substring (set_name.lastIndexOf(Prefs.getFileSeparator())+1);
// create directory if it does not exist yet
String gridSetPath = null;
if (saveGrids) {
gridSetPath = gridDir + Prefs.getFileSeparator() + set_name;
File set_dir = new File(gridSetPath);
if (!set_dir.exists()) {
set_dir.mkdirs(); // including parent
}
}
for (int nfile = 0; nfile < sourceFilesList[nset].length; nfile++) if (sourceFilesList[nset][nfile] != null){
long startFileTime=System.nanoTime();
if (DEBUG_LEVEL>0){
System.out.println(IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+"s: Processing file # "+(this_file+1)+
" (of "+ sourceFilesList.length+"): " + numFiles);
}
if (saveGrids && !overwriteGrids){ // check if result already exists
i = sourceFilesList[nset][nfile].lastIndexOf('/');
if (i>0){
String grid_name = prefix+sourceFilesList[nset][nfile].substring(i+1);
String grid_path = gridSetPath + Prefs.getFileSeparator() + grid_name;
if ((new File(grid_path)).exists()){
if (DEBUG_LEVEL>0) System.out.println("-->>> Skipping existing "+grid_path+" (as requested in \"Configure Process Distortions\")");
continue;
}
}
}
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?
matchSimulatedPattern.invalidateFlatFieldForGrid(); //Reset Flat Field calibration - different image.
matchSimulatedPattern.invalidateFocusMask();
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
DISTORTION, //
PATTERN_DETECT,
PATTERN_DETECT.minGridPeriod/2,
PATTERN_DETECT.maxGridPeriod/2,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
null, // LASER_POINTERS, // LaserPointer laserPointer, // LaserPointer object or null
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, //
null, // double [][][] hintGrid, // predicted grid array (or null)
0, // double hintGridTolerance, // allowed mismatch (fraction of period) or 0 - orientation only
THREADS_MAX,
UPDATE_STATUS,
DEBUG_LEVEL,
DISTORTION.loop_debug_level, // debug level
noMessageBoxes);
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 "+
IJ.d2s(0.000000001*(System.nanoTime()-startFileTime),3)+" seconds )\n");
if (this.SYNC_COMMAND.stopRequested.get()>0) {
System.out.println("User requested stop");
break;
}
continue; // too few cells detected
}
if (DISTORTION_PROCESS_CONFIGURATION.useNoPonters || (numAbsolutePoints>0)){
//Calculate grid contrast and brightness for each color component
matchSimulatedPattern.calcGridIntensities (
DISTORTION, //final DistortionParameters distortionParameters, //
COMPONENTS.equalizeGreens,
imp_sel, // image to process
THREADS_MAX);
ImagePlus imp_calibrated=matchSimulatedPattern.getCalibratedPatternAsImage(imp_sel,prefix, numAbsolutePoints);
if (DISTORTION_PROCESS_CONFIGURATION.showGridImages) imp_calibrated.show();
if (saveGrids){
FileSaver fs=new FileSaver(imp_calibrated);
String srcDir=DISTORTION_PROCESS_CONFIGURATION.selectGridFileDirectory(true,DISTORTION_PROCESS_CONFIGURATION.gridDirectory,true);
if (srcDir==null){
saveGrids=false; // do not ask about the next ones too
} else {
String path=DISTORTION_PROCESS_CONFIGURATION.gridDirectory+Prefs.getFileSeparator()+imp_calibrated.getTitle();
if (UPDATE_STATUS) IJ.showStatus("Saving "+path);
if (DEBUG_LEVEL>0) System.out.println("-->>> Saving "+path+" - using "+numAbsolutePoints+" laser pointer references");
fs.saveAsTiffStack(path);
}
}
}
if (DEBUG_LEVEL>0) System.out.println("Grid "+(this_file+1)+" calculation done at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+" (in "+
IJ.d2s(0.000000001*(System.nanoTime()-startFileTime),3)+"s )\n");
//
if (this.SYNC_COMMAND.stopRequested.get()>0) {
System.out.println("User requested stop");
break;
}
this_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));
return;
}
/* ======================================================================== */
public void calculateGrids() {
long startTime=System.nanoTime();
boolean noMessageBoxes=true;
String prefix="grid-";
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
DISTORTION_PROCESS_CONFIGURATION.debugLevel=MASTER_DEBUG_LEVEL;
if (matchSimulatedPattern==null) matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
matchSimulatedPattern.debugLevel=MASTER_DEBUG_LEVEL;
String [] sourceFilesList=DISTORTION_PROCESS_CONFIGURATION.selectSourceFiles(); // select files - with/without dialog
boolean saveGrids=DISTORTION_PROCESS_CONFIGURATION.saveGridImages;
boolean overwriteGrids=DISTORTION_PROCESS_CONFIGURATION.overwriteResultFiles;
if (sourceFilesList==null) return;
showPatternMinMaxPeriodDialog(PATTERN_DETECT,false);
for (int numFile=0;numFile<sourceFilesList.length;numFile++){
long startFileTime=System.nanoTime();
if (DEBUG_LEVEL>0){
System.out.println(IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+"s: Processing file # "+(numFile+1)+ " (of "+ sourceFilesList.length+"): "+sourceFilesList[numFile]);
}
if (saveGrids && !overwriteGrids){ // check if result already exists
int i = sourceFilesList[numFile].lastIndexOf('/');
if (i>0){
String path=prefix+sourceFilesList[numFile].substring(i+1);
String srcDir=DISTORTION_PROCESS_CONFIGURATION.selectGridFileDirectory(true,DISTORTION_PROCESS_CONFIGURATION.gridDirectory,true);
if (srcDir==null){
saveGrids=false; // do not ask about the next ones too
} else {
path=DISTORTION_PROCESS_CONFIGURATION.gridDirectory+Prefs.getFileSeparator()+path;
// File rsltFile=new File(path);
if ((new File(path)).exists()){
if (DEBUG_LEVEL>0) System.out.println("-->>> Skipping existing "+path+" (as requested in \"Configure Process Distortions\")");
continue;
}
}
}
}
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?
if (!DISTORTION_PROCESS_CONFIGURATION.useNoPonters && (matchSimulatedPattern.getPointersXY(imp_sel,LASER_POINTERS.laserUVMap.length)==null)) {
if (this.SYNC_COMMAND.stopRequested.get()>0) {
System.out.println("User requested stop");
break;
}
continue; // no pointers in this image
}
// /getPointersXY(ImagePlus imp, int numPointers){ if
// calculate distortion grid for it
matchSimulatedPattern.invalidateFlatFieldForGrid(); //Reset Flat Field calibration - different image.
matchSimulatedPattern.invalidateFocusMask();
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
DISTORTION, //
PATTERN_DETECT,
PATTERN_DETECT.minGridPeriod/2,
PATTERN_DETECT.maxGridPeriod/2,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
LASER_POINTERS, // LaserPointer laserPointer, // LaserPointer object or null
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, //
null, // double [][][] hintGrid, // predicted grid array (or null)
0, // double hintGridTolerance, // allowed mismatch (fraction of period) or 0 - orientation only
THREADS_MAX,
UPDATE_STATUS,
DEBUG_LEVEL,
DISTORTION.loop_debug_level, // debug level
noMessageBoxes);
if (DEBUG_LEVEL>1) System.out.println("numAbsolutePoints="+numAbsolutePoints);
if ((numAbsolutePoints==DISTORTION.errPatternNotFound) || (numAbsolutePoints==DISTORTION.errTooFewCells)) {
if (DEBUG_LEVEL>0) System.out.println("Grid "+(numFile+1)+" 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");
break;
}
continue; // too few cells detected
}
if (DISTORTION_PROCESS_CONFIGURATION.useNoPonters || (numAbsolutePoints>0)){
//Calculate grid contrast and brightness for each color component
matchSimulatedPattern.calcGridIntensities (
DISTORTION, //final DistortionParameters distortionParameters, //
COMPONENTS.equalizeGreens,
imp_sel, // image to process
THREADS_MAX);
ImagePlus imp_calibrated=matchSimulatedPattern.getCalibratedPatternAsImage(imp_sel,prefix, numAbsolutePoints);
if (DISTORTION_PROCESS_CONFIGURATION.showGridImages) imp_calibrated.show();
if (saveGrids){
FileSaver fs=new FileSaver(imp_calibrated);
String srcDir=DISTORTION_PROCESS_CONFIGURATION.selectGridFileDirectory(true,DISTORTION_PROCESS_CONFIGURATION.gridDirectory,true);
if (srcDir==null){
saveGrids=false; // do not ask about the next ones too
} else {
String path=DISTORTION_PROCESS_CONFIGURATION.gridDirectory+Prefs.getFileSeparator()+imp_calibrated.getTitle();
if (UPDATE_STATUS) IJ.showStatus("Saving "+path);
if (DEBUG_LEVEL>0) System.out.println("-->>> Saving "+path+" - using "+numAbsolutePoints+" laser pointer references");
fs.saveAsTiffStack(path);
}
}
}
if (DEBUG_LEVEL>0) System.out.println("Grid "+(numFile+1)+" calculation done at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+" (in "+
IJ.d2s(0.000000001*(System.nanoTime()-startFileTime),3)+"s )\n");
//
if (this.SYNC_COMMAND.stopRequested.get()>0) {
System.out.println("User requested stop");
break;
}
}
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));
return;
}
/* ======================================================================== */
public void processCalibrationFiles() {
if (!showProcessCalibrationFilesDialog(PROCESS_PARAMETERS)) return;
......@@ -9570,6 +9733,8 @@ if (MORE_BUTTONS) {
matchSimulatedPattern.calculateDistortions(
DISTORTION, //
PATTERN_DETECT,
PATTERN_DETECT.minGridPeriod/2,
PATTERN_DETECT.maxGridPeriod/2,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
......@@ -12475,7 +12640,7 @@ if (MORE_BUTTONS) {
throw new IllegalArgumentException (msg);
}
matchSimulatedPattern.debugLevel=debugLevel;
/*
double sharpnessOld=matchSimulatedPattern.focusQualityOld(
imp,
focusMeasurementParameters.sampleSize, // will be twice the regualr FFT size
......@@ -12492,6 +12657,7 @@ if (MORE_BUTTONS) {
lensDistortionParameters.py0,
debugLevel);
if (debugLevel>0) System.out.println("Focus qualityOld1="+sharpnessOld1);
*/
double sharpness=matchSimulatedPattern.focusQuality(
imp,
focusMeasurementParameters.sampleSize, // will be twice the regualr FFT size
......@@ -17017,9 +17183,13 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
mapCell.x=nTileX*size;
pixels=splitBayer(imp, mapCell,COMPONENTS.equalizeGreens);
pixels[4]= normalizeAndWindow (pixels[4], hamming);
patternMap[nTileY][nTileX]=matchSimulatedPattern.findPattern(pixels[4],
patternMap[nTileY][nTileX]=matchSimulatedPattern.findPattern(
null,
pixels[4],
size,
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
patternDetectParameters.maxGridPeriod/2,
true,
title); // title - will not be used
/* Now verify by correlating with the actual pattern */
......@@ -17581,6 +17751,8 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
if (matchSimulatedPattern.PATTERN_GRID==null) {
double[][] distortedPattern= matchSimulatedPattern.findPatternDistorted(input_bayer, // pixel array to process (no windowing!)
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
patternDetectParameters.maxGridPeriod/2,
true, //(greensToProcess==4), // boolean greens, // this is a pattern for combined greens (diagonal), adjust results accordingly
title); // title prefix to use for debug images
......@@ -19833,7 +20005,7 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
return true;
}
/* ======================================================================== */
public boolean showPatternDetectParametersDialog(MatchSimulatedPattern.PatternDetectParameters patternDetectParameters) {
public boolean showPatternDetectParametersDialog(MatchSimulatedPattern.PatternDetectParameters patternDetectParameters, boolean use_lwir) {
///gaussWidth
GenericDialog gd = new GenericDialog("Parameters");
gd.addNumericField("Gaussian width for the window function (<=0 - use Hamming):", patternDetectParameters.gaussWidth, 3);
......@@ -19849,10 +20021,24 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
gd.addNumericField("Minimal pattern correlation contrast" , patternDetectParameters.minCorrContrast, 3); //5.0; // Discrimination threshold between good and bad pattern correleation
gd.addNumericField("Minimal pattern grid period (<=0.0 - do not check)" , patternDetectParameters.minGridPeriod, 2,5,"pix");
gd.addNumericField("Maximal pattern grid period (<=0.0 - do not check)" , patternDetectParameters.maxGridPeriod, 2,5,"pix");
if (use_lwir) {
gd.addNumericField("Minimal pattern grid period for LWIR sensors (<=0.0 - do not check)" , patternDetectParameters.minGridPeriodLwir, 2,5,"pix");
gd.addNumericField("Maximal pattern grid period for LWIR sensors (<=0.0 - do not check)" , patternDetectParameters.maxGridPeriodLwir, 2,5,"pix");
}
gd.addMessage("----- debug -----");
gd.addNumericField("Debug grid near pixel X" , patternDetectParameters.debugX, 1,6,"pix");
gd.addNumericField("Debug grid near pixel X" , patternDetectParameters.debugY, 1,6,"pix");
gd.addNumericField("Debug grid nodes at this distance of (x,Y) - <0 - no debug", patternDetectParameters.debugRadius, 1,5,"pix");
gd.addMessage("----- New method that should work with large cells (only half-period negative correlations fit in window) -----");
gd.addCheckbox ("Use large cell method (with phase correlation)", patternDetectParameters.use_large_cells); // true;
gd.addNumericField("\"phasiness\" of correlation" , patternDetectParameters.phaseCoeff, 2,5,"");
gd.addNumericField("Low-pass sigma for phase correlation - frequency fraction of maximal", patternDetectParameters.lowpass_sigma, 2,5,"");
gd.addNumericField("Minimal min/max amplitude fraction of the zero one" , patternDetectParameters.min_frac, 2,5,"");
gd.addNumericField("Minimal absolute value of sine of the patern vectors angle" , patternDetectParameters.min_sin, 2,5,"");
gd.addCheckbox ("Fail if quadratic approximation fails or returns outside of +/- 1.5", patternDetectParameters.no_crazy); // true;
gd.showDialog();
if (gd.wasCanceled()) return false;
......@@ -19869,21 +20055,42 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
patternDetectParameters.minCorrContrast= gd.getNextNumber();
patternDetectParameters.minGridPeriod= gd.getNextNumber();
patternDetectParameters.maxGridPeriod= gd.getNextNumber();
if (use_lwir) {
patternDetectParameters.minGridPeriodLwir= gd.getNextNumber();
patternDetectParameters.maxGridPeriodLwir= gd.getNextNumber();
}
patternDetectParameters.debugX= gd.getNextNumber();
patternDetectParameters.debugY= gd.getNextNumber();
patternDetectParameters.debugRadius= gd.getNextNumber();
patternDetectParameters.use_large_cells= gd.getNextBoolean();
patternDetectParameters.phaseCoeff= gd.getNextNumber();
patternDetectParameters.lowpass_sigma= gd.getNextNumber();
patternDetectParameters.min_frac= gd.getNextNumber();
patternDetectParameters.min_sin= gd.getNextNumber();
patternDetectParameters.no_crazy= gd.getNextBoolean();
return true;
}
public boolean showPatternMinMaxPeriodDialog(MatchSimulatedPattern.PatternDetectParameters patternDetectParameters) {
public boolean showPatternMinMaxPeriodDialog(MatchSimulatedPattern.PatternDetectParameters patternDetectParameters, boolean use_lwir) {
///gaussWidth
GenericDialog gd = new GenericDialog("Min/Max opattern grid period");
gd.addNumericField("Minimal pattern grid period (<=0.0 - do not check)" , patternDetectParameters.minGridPeriod, 2,5,"pix");
gd.addNumericField("Maximal pattern grid period (<=0.0 - do not check)" , patternDetectParameters.maxGridPeriod, 2,5,"pix");
gd.addMessage ("TODO: Calculate min/max from pattern data and distance");
if (use_lwir) {
gd.addNumericField("Minimal pattern grid period for LWIR sensors (<=0.0 - do not check)" , patternDetectParameters.minGridPeriodLwir, 2,5,"pix");
gd.addNumericField("Maximal pattern grid period for LWIR sensors (<=0.0 - do not check)" , patternDetectParameters.maxGridPeriodLwir, 2,5,"pix");
}
gd.showDialog();
if (gd.wasCanceled()) return false;
patternDetectParameters.minGridPeriod= gd.getNextNumber();
patternDetectParameters.maxGridPeriod= gd.getNextNumber();
if (use_lwir) {
patternDetectParameters.minGridPeriodLwir= gd.getNextNumber();
patternDetectParameters.maxGridPeriodLwir= gd.getNextNumber();
}
return true;
}
......@@ -23,15 +23,16 @@ package com.elphel.imagej.calibration;
**
*/
import ij.IJ;
import ij.Prefs;
import ij.gui.GenericDialog;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Properties;
import com.elphel.imagej.common.WindowTools;
import ij.IJ;
import ij.Prefs;
import ij.gui.GenericDialog;
public class DistortionProcessConfiguration{
public String sourceDirectory="";
......@@ -207,4 +208,25 @@ import com.elphel.imagej.common.WindowTools;
return sourceFiles;
}
public String[] selectSourceSets() {
File dir= new File (this.sourceDirectory);
if (this.debugLevel>1) System.out.println("selectSourceSets, dir="+this.sourceDirectory);
if (!dir.exists()) {
String error="Source directory "+this.sourceDirectory+" does not exist.";
IJ.showMessage("No files selected");
if (this.debugLevel>1) System.out.println("selectSourceFiles() ERROR:"+error);
return null;
}
File [] sourceFileSets = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
});
String [] sourceSets = new String[sourceFileSets.length];
for (int i=0;i<sourceSets.length;i++) sourceSets[i]=sourceFileSets[i].getPath();
return sourceSets;
}
}
package com.elphel.imagej.calibration;
import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.Prefs;
import ij.gui.GenericDialog;
import ij.io.FileSaver;
import ij.io.Opener;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import java.awt.Rectangle;
import java.io.File;
import java.util.ArrayList;
......@@ -19,14 +9,22 @@ import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.SwingUtilities;
import com.elphel.imagej.calibration.CalibrationFileManagement.MultipleExtensionsFileFilter;
import com.elphel.imagej.calibration.SimulationPattern.SimulParameters;
import com.elphel.imagej.common.DoubleFHT;
import com.elphel.imagej.common.DoubleGaussianBlur;
import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.common.WindowTools;
import com.elphel.imagej.jp4.JP46_Reader_camera;
import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.Prefs;
import ij.gui.GenericDialog;
import ij.io.FileSaver;
import ij.io.Opener;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
public class EyesisAberrations {
public double [][][][] pdfKernelMap=null;
JP46_Reader_camera JP4_INSTANCE= new JP46_Reader_camera(false);
......@@ -181,6 +179,7 @@ public class EyesisAberrations {
final int numberOfKernelsInChn=tilesY*tilesX;
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
float [] pixels=null;
double [] kernel= new double[inverseParameters.dSize*inverseParameters.dSize];
......@@ -555,7 +554,7 @@ public class EyesisAberrations {
iy=-iy;
}
ix= (ix+size) % size;
floatPixels[i]=(float) clusterMap[iy][ix];
floatPixels[i]=clusterMap[iy][ix];
}
ip.setPixels(floatPixels);
ip.resetMinAndMax();
......@@ -639,8 +638,8 @@ public class EyesisAberrations {
row2=(fftsize-row1) %fftsize;
for (col1=0;col1 < fftsize;col1++) {
col2=(fftsize-col1) %fftsize;
fht_pixels[row1*fftsize+col1]=(double) (fft[row1][col1][0]-fft[row1][col1][1]);
fht_pixels[row2*fftsize+col2]=(double) (fft[row1][col1][0]+fft[row1][col1][1]);
fht_pixels[row1*fftsize+col1]=fft[row1][col1][0]-fft[row1][col1][1];
fht_pixels[row2*fftsize+col2]=fft[row1][col1][0]+fft[row1][col1][1];
}
}
return fht_pixels;
......@@ -1281,6 +1280,8 @@ public class EyesisAberrations {
int rslt=matchSimulatedPattern.calculateDistortions(
distortionParameters, //
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
patternDetectParameters.maxGridPeriod/2,
simulParameters,
colorComponents.equalizeGreens,
imp,
......@@ -2313,6 +2314,7 @@ public class EyesisAberrations {
for (int ithread = 0; ithread < threads.length; ithread++) {
// Concurrently run in as many threads as CPUs
threads[ithread] = new Thread() {
@Override
public void run() {
// Each thread processes a few items in the total list
......@@ -2399,6 +2401,7 @@ public class EyesisAberrations {
}
final int numFinished=tilesFinishedAtomic.getAndIncrement();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
IJ.showProgress(numFinished,patternCells);
}
......@@ -2679,6 +2682,8 @@ public class EyesisAberrations {
if (matchSimulatedPattern.PATTERN_GRID==null) {
double[][] distortedPattern= matchSimulatedPattern.findPatternDistorted(input_bayer, // pixel array to process (no windowing!)
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
patternDetectParameters.maxGridPeriod/2,
true, //(greensToProcess==4), // boolean greens, // this is a pattern for combined greens (diagonal), adjust results accordingly
title); // title prefix to use for debug images
......@@ -4148,7 +4153,7 @@ if (globalDebugLevel>2)globalDebugLevel=0; //***********************************
ImageProcessor ip = new FloatProcessor(size,size);
float [] floatPixels = new float [size*size];
for (i=0;i<floatPixels.length;i++) {
floatPixels[i]=(float) clusterMap[i/size][i%size];
floatPixels[i]=clusterMap[i/size][i%size];
}
ip.setPixels(floatPixels);
ip.resetMinAndMax();
......@@ -4404,11 +4409,11 @@ if (globalDebugLevel>2)globalDebugLevel=0; //***********************************
if (debug) {
SDFA_INSTANCE.showArrays(debugPixels, title+"_mask_PSF");
double [] doublePixelsPSFCount=new double [pixelsPSF.length];
for (j=0;j<doublePixelsPSFCount.length;j++) doublePixelsPSFCount[j]=(double)pixelsPSFCount[j];
for (j=0;j<doublePixelsPSFCount.length;j++) doublePixelsPSFCount[j]=pixelsPSFCount[j];
SDFA_INSTANCE.showArrays(doublePixelsPSFCount, title+"_PSF_bin_count");
SDFA_INSTANCE.showArrays(pixelsPSFWeight, title+"_PSF_bin_weight");
double [] doubleContrastCache=new double [contrastCache.length];
for (j=0;j<doubleContrastCache.length;j++) doubleContrastCache[j]=(double)((contrastCache[j]>=0.0)?contrastCache[j]:-0.00001);
for (j=0;j<doubleContrastCache.length;j++) doubleContrastCache[j]=(contrastCache[j]>=0.0)?contrastCache[j]:-0.00001;
SDFA_INSTANCE.showArrays(doubleContrastCache, title+"_ContrastCache");
}
return pixelsPSF;
......@@ -4988,6 +4993,7 @@ if (globalDebugLevel>2)globalDebugLevel=0; //***********************************
this.thresholdHigh = thresholdHigh;
this.thresholdLow = thresholdLow;
}
@Override
public OTFFilterParameters clone() {
return new OTFFilterParameters(
this.deconvInvert,
......@@ -5076,6 +5082,7 @@ if (globalDebugLevel>2)globalDebugLevel=0; //***********************************
}
@Override
public PSFParameters clone(){
return new PSFParameters(
this.minContrast,
......
......@@ -668,6 +668,8 @@ horizontal axis:
// allow more of grid around pointers?
distortionParameters, //
this.patternDetectParameters,
this.patternDetectParameters.minGridPeriod/2,
this.patternDetectParameters.maxGridPeriod/2,
simulParameters,
equalizeGreens, imp_eq,
this.laserPointers, // null, //LASER_POINTERS, //
......@@ -841,6 +843,8 @@ horizontal axis:
// allow more of grid around pointers?
distortionParameters, //
this.patternDetectParameters,
this.patternDetectParameters.minGridPeriod/2,
this.patternDetectParameters.maxGridPeriod/2,
simulParameters,
equalizeGreens, imp_eq,
this.laserPointers, // null, //LASER_POINTERS, //
......
......@@ -25,7 +25,6 @@ package com.elphel.imagej.calibration;
import java.awt.Rectangle;
import java.util.Properties;
import com.elphel.imagej.calibration.SimulationPattern.SimulParameters;
import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.common.WindowTools;
......@@ -136,6 +135,8 @@ public class LensAdjustment {
null, // is not used in update mode
distortionParameters, //
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
patternDetectParameters.maxGridPeriod/2,
simulParameters,
equalizeGreens,
imp_eq, // image to process
......@@ -158,6 +159,8 @@ public class LensAdjustment {
numAbsolutePoints=matchSimulatedPattern.calculateDistortions( // allow more of grid around pointers?
distortionParameters, //
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
patternDetectParameters.maxGridPeriod/2,
simulParameters,
equalizeGreens,
imp_eq,
......@@ -806,6 +809,7 @@ public class LensAdjustment {
this.reportTemperature=reportTemperature;
this.showLegacy=showLegacy;
}
@Override
public FocusMeasurementParameters clone(){
return new FocusMeasurementParameters(
this.gridGeometryFile,
......
......@@ -36,7 +36,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.SwingUtilities;
import com.elphel.imagej.calibration.SimulationPattern.SimulParameters;
import com.elphel.imagej.common.DoubleFHT;
import com.elphel.imagej.common.DoubleGaussianBlur;
import com.elphel.imagej.common.PolynomialApproximation;
......@@ -112,6 +111,7 @@ public class MatchSimulatedPattern {
this.FFT_SIZE=fft_size;
}
// not real clone, just for threads - if there will be FFT - keep individual
@Override
public MatchSimulatedPattern clone(){ // used in createPSFMap when creating threads
MatchSimulatedPattern msp=new MatchSimulatedPattern (this.FFT_SIZE);
// cloning should be thread safe, when using DoubleFHT - use individual instances
......@@ -237,7 +237,7 @@ public class MatchSimulatedPattern {
UVShiftRot[2] = combinedRotations[UVShiftRotA[2]][UVShiftRotB[2]];
return UVShiftRot;
}
/*
public double focusQualityOld(
ImagePlus imp,
int fftSize,
......@@ -392,18 +392,6 @@ public class MatchSimulatedPattern {
pixels[c]=fht_instance.calculateAmplitude(pixels[c]);
}
if (debugLevel>2) SDFA_INSTANCE.showArrays(pixels, fftSize, fftSize, true,"amplitudes");
/*
DoubleGaussianBlur gb=new DoubleGaussianBlur();
for (int i=0;i<pixels.length;i++)
if (pixels[i]!=null) gb.blurDouble(
pixels[i],
fftSize,
fftSize,
2.0, // fixed sigma
2.0,
0.01);
if (debugLevel>1) SDFA_INSTANCE.showArrays(pixels, fftSize, fftSize, true,"amplitudes");
*/
int [][][] spectrumMaximums=new int [pixels.length][][];
double [] spectralContrast=new double [pixels.length];
......@@ -507,6 +495,7 @@ public class MatchSimulatedPattern {
return 0.25*(spectralContrast[0]+spectralContrast[1]+spectralContrast[2]+spectralContrast[3]);
}
*/
public double focusQualityR2(
ImagePlus imp,
int fftSize,
......@@ -999,8 +988,11 @@ public class MatchSimulatedPattern {
}
/* returns array of 3 arrays: first two are 3-element wave vectors (x,y,phase), last - 3-rd order correction coefficients */
public double[][] findPatternDistorted(double [][] bayer_pixels, // pixel array to process (no windowing!), two greens will be used
public double[][] findPatternDistorted(
double [][] bayer_pixels, // pixel array to process (no windowing!), two greens will be used
PatternDetectParameters patternDetectParameters,
double min_half_period,
double max_half_period,
boolean greens, // this is a pattern for combined greens (diagonal), adjust results accordingly
String title){ // title prefix to use for debug images
if (bayer_pixels==null) return null;
......@@ -1044,9 +1036,13 @@ public class MatchSimulatedPattern {
}
quarter_pixels[iq]= normalizeAndWindow (quarter_pixels[iq], quarterHamming);
if (this.debugLevel>2) SDFA_INSTANCE.showArrays(quarter_pixels[iq],hsize, hsize, title+"-new"+iq);
quarter_patterns[iq] =findPattern(quarter_pixels[iq],
quarter_patterns[iq] = findPattern(
null, // DoubleFHT doubleFHT,
quarter_pixels[iq],
hsize,
patternDetectParameters,
min_half_period,
max_half_period,
greens,
title+"Q_"+iq);
......@@ -1720,7 +1716,8 @@ public class MatchSimulatedPattern {
return rslt; // temporary
}
/* ======================================================================== */
public double[][] findPattern(double [] input_pixels, // pixel array to process
public double[][] findPatternUsedNow(
double [] input_pixels, // pixel array to process
int size, // FFT size
PatternDetectParameters patternDetectParameters,
boolean greens, // this is a pattern for combined greens (diagonal), adjust results accordingly
......@@ -1988,7 +1985,709 @@ public class MatchSimulatedPattern {
if (this.debugLevel>2) System.out.println();
return result;
}
// Above is currently used for years, below is for experiments
public double[][] findPattern(
DoubleFHT doubleFHT,
double [] input_pixels, // pixel array to process
int size, // FFT size
PatternDetectParameters patternDetectParameters,
double min_half_period,
double max_half_period,
boolean greens, // this is a pattern for combined greens (diagonal), adjust results accordingly
String title) { // title prefix to use for debug images
if (!patternDetectParameters.use_large_cells) {
return findPatternUsedNow(
input_pixels, // pixel array to process
size, // FFT size
patternDetectParameters,
greens, // this is a pattern for combined greens (diagonal), adjust results accordingly
title); // title prefix to use for debug images
}
int debug_threshold = 4;
// this.debugLevel = 11;
if (doubleFHT == null) doubleFHT = new DoubleFHT(); // pass from the caller to re-use
double [] cpixels=input_pixels.clone();
if (min_half_period < 2) {
min_half_period = 2;
}
double [] dfht = new double [input_pixels.length]; // will save FHT from phase auto correlation
double [][]rslt= new double [2][3];
cpixels = doubleFHT.phaseCorrelate (cpixels, patternDetectParameters.phaseCoeff, 0, patternDetectParameters.lowpass_sigma, dfht);
if (this.debugLevel > (debug_threshold+1)) {
double [][] src_corr = {input_pixels, cpixels};
String [] titles = {"source","corr"};
(new ShowDoubleFloatArrays()).showArrays(src_corr,size,size,true,"fft_corr-"+patternDetectParameters.phaseCoeff,titles);
}
int [][] half_periods = findFirst2MinOnCorrelation( cpixels, min_half_period, max_half_period);
if (half_periods != null) { // check vectors are not close to colinear
double sin = (half_periods[0][0]*half_periods[1][1]-half_periods[0][1]*half_periods[1][0])/
Math.sqrt((half_periods[0][0]*half_periods[0][0] + half_periods[0][1]*half_periods[0][1])*
(half_periods[1][0]*half_periods[1][0] + half_periods[1][1]*half_periods[1][1]));
if (Math.abs(sin) < patternDetectParameters.min_sin) {
if (this.debugLevel > debug_threshold) System.out.println("Half-period vectors on correlation are too close to colinear - sin="+sin);
return null;
}
}
if (this.debugLevel>7) {
if (half_periods == null) {
if (this.debugLevel > (debug_threshold+0)) System.out.println("Could not find half-periods on correlation");
return null;
} else {
if (this.debugLevel > (debug_threshold+1)) System.out.println("first half period (x/y) :"+half_periods[0][0]+"/"+half_periods[0][1]+
", second half period :"+half_periods[1][0]+"/"+half_periods[1][1]);
}
}
double [][] dhp = getPeriodsFromCorrelation(
cpixels,
half_periods, // a pair of half-periods
patternDetectParameters.min_frac,
patternDetectParameters.no_crazy) ;
if (dhp != null) {
if (this.debugLevel > (debug_threshold+1)) System.out.println(String.format("findPattern(): dhp= [[%.5f,%.5f],[%.5f,%.5f]]",dhp[0][0],dhp[0][1],dhp[1][0],dhp[1][1]));
} else {
if (this.debugLevel > (debug_threshold+0)) System.out.println("findPattern(): getPeriodsFromCorrelation() FAILED");
}
/* these are combined greens, convert vectors to original pixel space)! */
if (greens) {
double [][] rotMatrix= {{1.0,-1.0},{1.0,1.0}};
double [][] max2orig= matrix2x2_mul(dhp,rotMatrix);
for (int i=0; i<2; i++) for (int j=0; j<2; j++) rslt[i][j]=max2orig[i][j]; // result is [2][3], max2orig is [2][2]
if (this.debugLevel > (debug_threshold + 0)) {
System.out.println("Corrected to original pixels[0] x="+IJ.d2s(rslt[0][0],4)+" y="+IJ.d2s(rslt[0][1],4));
System.out.println("Corrected to original pixels[1] x="+IJ.d2s(rslt[1][0],4)+" y="+IJ.d2s(rslt[1][1],4));
}
} else {
for (int i=0;i<2;i++) for (int j=0;j<2;j++) rslt[i][j]=rslt[i][j]; // result is [2][3], max2 is [2][2]
}
// Calculate complex FFT - needed to determine pattern phases (autocorrelation does not provide this
// dfht array has FHT(input_pixels) save from calculation of the phase autocorrelation
double [][][] fft_cmplx = doubleFHT.FHT2FFTHalf(dfht,size);
if (this.debugLevel > (debug_threshold+2)) {
(new ShowDoubleFloatArrays()).showComplex(fft_cmplx,"fft_cmplx");
}
/* Calculate locations of the maximums on FFT (corresponding to the diagonals of the checkerboard pattern) */
double [][] max_on_FFT = {{2*size*(dhp[0][0]-dhp[1][0]),2*size*(dhp[0][1]-dhp[1][1])},
{2*size*(dhp[0][0]+dhp[1][0]),2*size*(dhp[0][1]+dhp[1][1])}};
/* We have only one half of the FFT data so rotate 180-degrees around the center if the point is in the bottom half*/
double [] max_phases = getPatternPhasesFromFFT(fft_cmplx, size, max_on_FFT);
double [] checker_phases= findCheckerPhases(dhp, max_phases); /* may be different for greens==true . No, the same */
for (int i=0;i<2;i++) rslt[i][2]=checker_phases[i];
if (this.debugLevel > (debug_threshold + 0)) System.out.println();
if (this.debugLevel < 1000) return rslt;
// below is dead (older) code
double [] pixels=input_pixels.clone();
double [][]result=new double [2][3];
//System.out.println("pixels.length="+pixels.length); //4096
ImageProcessor ip, ip1;
FHT fht, fht1;
double[][][] fft_complex,fft_corr;
double[][] fft_gamma;
int i,j;
double DCLevel=0.0;
double a;
float []floatPixels=new float[pixels.length];
for (i=0;i<pixels.length; i++) DCLevel+=pixels[i];
DCLevel/=(size*size);
for (i=0;i<pixels.length; i++) pixels[i]-=DCLevel;
// convert to float for image processor;
for (i=0;i<pixels.length; i++) floatPixels[i]=(float) pixels[i];
ip = new FloatProcessor(size,size);
ip.setPixels(floatPixels);
if (this.debugLevel>8) {
ip.resetMinAndMax();
ImagePlus imp_direct= new ImagePlus(title+"_Direct_"+patternDetectParameters.corrGamma, ip);
imp_direct.show();
}
fht = new FHT(ip);
// Swapping quadrants, so the center will be 0,0
fht.swapQuadrants();
// get to frequency domain
fht.transform();
if (this.debugLevel>5) {
floatPixels=(float []) fht.getPixels();
ImageProcessor ip_fht = new FloatProcessor(size,size);
ip_fht.setPixels(floatPixels);
ip_fht.resetMinAndMax();
ImagePlus imp_fht= new ImagePlus(title+"_FHT", ip_fht);
imp_fht.show();
}
// Convert from FHT to complex FFT
fft_complex= FHT2FFTHalf (fht,size);
if (this.debugLevel>7) {
(new ShowDoubleFloatArrays()).showComplex(fft_complex,"fft_complex");
}
// will need fft_complex again later for later phase pattern measurements, calculate fft_gamma for correlation (pattern 2 frequencies measurement)
fft_gamma=new double [size][size];
floatPixels=new float[pixels.length];
DCLevel=0.0;
for (i=0;i<fft_complex.length; i++) for (j=0;j<fft_complex[0].length;j++) {
fft_gamma[i][j]=Math.pow(fft_complex[i][j][0]*fft_complex[i][j][0]+fft_complex[i][j][1]*fft_complex[i][j][1],patternDetectParameters.corrGamma);
DCLevel+=fft_gamma[i][j];
floatPixels[i*size+j]=(float) fft_gamma[i][j];
}
DCLevel/=(fft_complex.length*fft_complex[0].length);
for (i=0;i<fft_complex.length; i++) for (j=0;j<fft_complex[0].length;j++) {
floatPixels[i*size+j]-=DCLevel;
if ((i>0)&& (i<(size/2))){
floatPixels[(size-i)*size+((size-j)%size)]=floatPixels[i*size+j];
}
}
/* TODO: maybe it is better to find the pattern frequencies just here, without converting back.
After rejecting low frequencies, there seem to be just 2 nice maximums - easy to extract*/
// now perform direct FFT of gamma(power spectrum)
ip1 = new FloatProcessor(size,size);
ip1.setPixels(floatPixels);
if (this.debugLevel>7) {
ip1.resetMinAndMax();
ImagePlus imp1= new ImagePlus(title+"_gamma(ps)_"+patternDetectParameters.corrGamma, ip1);
imp1.show();
}
fht1 = new FHT(ip1);
// Swapping quadrants, so the center will be 0,0
fht1.swapQuadrants();
fht1.transform();
fft_corr= FHT2FFTHalf (fht1,size);
if (this.debugLevel>7) {
(new ShowDoubleFloatArrays()).showComplex(fft_corr,"fft_corr");
}
double[] highPassFilter=new double[fft_complex[0].length];
double expK=(patternDetectParameters.corrSigma>0)?(1.0/(2*patternDetectParameters.corrSigma*patternDetectParameters.corrSigma)):0.0;
for (j=0;j<=fft_complex[0].length/2;j++) {
highPassFilter[j]=(expK>0.0)?(1.0-Math.exp(-(expK*j*j))):1.0;
if (j>0) highPassFilter[highPassFilter.length-j]=highPassFilter[j];
}
for (i=0;i<fft_complex.length; i++) for (j=0;j<fft_complex[0].length;j++) {
fft_corr[i][j][0]=highPassFilter[i]*highPassFilter[j]*(fft_corr[i][j][0]*fft_corr[i][j][0]+fft_corr[i][j][1]*fft_corr[i][j][1]);
fft_corr[i][j][1]=0.0;
}
if (this.debugLevel>7) {
(new ShowDoubleFloatArrays()).showComplex(fft_corr,"fft_corr-high_pass");
}
// Convert fft array back to fht array and
// set fht_target pixels with new values
fht1.setPixels (floatFFTHalf2FHT (fft_corr,size)); /* FIXME: - done, there is no difference as Im()==0 */
/// optionally show the result
if (this.debugLevel>7) {
ImageProcessor ip_fht2 = new FloatProcessor(size,size);
ip_fht2.setPixels(floatFFTHalf2FHT (fft_corr,size));
ip_fht2.resetMinAndMax();
ImagePlus imp_fht2= new ImagePlus(title+"_fht_corr_"+patternDetectParameters.corrGamma, ip_fht2);
imp_fht2.show();
}
/// transform to space
fht1.inverseTransform();
floatPixels=(float []) fht1.getPixels();
a=1/floatPixels[0];
for (i=0; i<floatPixels.length; i++){
floatPixels[i]*=a;
}
fht1.setPixels(floatPixels);
//System.out.println("2:y="+y+" x="+x+" base_b="+base_b+" base="+base);
fht1.swapQuadrants();
if (this.debugLevel>2) {
fht1.resetMinAndMax();
ImagePlus imp_corr= new ImagePlus(title+"_corr_"+patternDetectParameters.corrGamma, fht1);
imp_corr.show();
}
// return direct_target;
floatPixels =(float[])fht1.getPixels();
for (i=0;i<floatPixels.length;i++) pixels[i]=floatPixels[i];
int [][] max2OnSpectrum= findFirst2MaxOnSpectrum (fft_complex, // complex, top half, starting from 0,0
1, // skip +- from (0,0) and previous max - add parameter to dialog?
0.5); // 0.5 - 30deg. orthogonality of 2 vectors - 1.0 - perpendicular, 0.0 - parallel - add parameter to dialog?
/**TODO: get out on failure */
if (max2OnSpectrum==null) {
if (this.debugLevel>2){
System.out.println("findPattern() 1: Failed to find a pattern");
if (this.debugLevel>2){
SDFA_INSTANCE.showArrays(input_pixels, "failed-findPattern-1-");
}
}
return null;
}
/* Trying to filter out unreasonable maximums (if there is no pattern at all) */
double maxFrequency=0.25*fft_complex.length;
if ((Math.abs(max2OnSpectrum[0][0])>maxFrequency) ||
(Math.abs(max2OnSpectrum[0][1])>maxFrequency) ||
(Math.abs(max2OnSpectrum[1][0])>maxFrequency) ||
(Math.abs(max2OnSpectrum[1][1])>maxFrequency)) {
if (this.debugLevel>2) {
System.out.println("Failed to detect pattern, as frequecy is above limit="+IJ.d2s(maxFrequency,2));
System.out.println("Maximum 1 on spectrum: x="+IJ.d2s(max2OnSpectrum[0][0],4)+" y="+IJ.d2s(max2OnSpectrum[0][1],4));
System.out.println("Maximum 2 on spectrum: x="+IJ.d2s(max2OnSpectrum[1][0],4)+" y="+IJ.d2s(max2OnSpectrum[1][1],4));
}
return null;
}
if (this.debugLevel>6) {
System.out.println("Maximum 1 on spectrum: x="+IJ.d2s(max2OnSpectrum[0][0],4)+" y="+IJ.d2s(max2OnSpectrum[0][1],4));
System.out.println("Maximum 2 on spectrum: x="+IJ.d2s(max2OnSpectrum[1][0],4)+" y="+IJ.d2s(max2OnSpectrum[1][1],4));
}
int [][] startPoints={{max2OnSpectrum[0][0]+max2OnSpectrum[1][0],
max2OnSpectrum[0][1]+max2OnSpectrum[1][1]},
{max2OnSpectrum[0][0]-max2OnSpectrum[1][0],
max2OnSpectrum[0][1]-max2OnSpectrum[1][1]}};
if (startPoints[1][1] <0) { /* startPoints[1][1] > 0 anyway */
startPoints[1][0]= -startPoints[1][0];
startPoints[1][1]= -startPoints[1][1];
}
if (this.debugLevel>2) {
System.out.println("Predicted correlation maximum 1 from spectrum: x="+IJ.d2s(startPoints[0][0],4)+" y="+IJ.d2s(startPoints[0][1],4));
System.out.println("Predicted correlation maximum 2 from spectrum: x="+IJ.d2s(startPoints[1][0],4)+" y="+IJ.d2s(startPoints[1][1],4));
}
double[][] max2= findFirst2MaxOnCorrelation(
pixels,
startPoints,
patternDetectParameters
);
/**TODO: get out on failure */
if (max2==null) {
if (this.debugLevel>2){
System.out.println("findPattern() 2: Failed to find a pattern");
if (this.debugLevel>2){
SDFA_INSTANCE.showArrays(input_pixels, "failed-findPattern-2-");
}
}
return null;
}
/* these are combined greens, convert vectors to original pixel space)! */
if (greens) {
double [][] rotMatrix= {{1.0,-1.0},{1.0,1.0}};
double [][] max2orig= matrix2x2_mul(max2,rotMatrix);
for (i=0;i<2;i++) for (j=0;j<2;j++) result[i][j]=max2orig[i][j]; // result is [2][3], max2orig is [2][2]
if (this.debugLevel>2) {
System.out.println("Corrected to original pixels[0] x="+IJ.d2s(result[0][0],4)+" y="+IJ.d2s(result[0][1],4));
System.out.println("Corrected to original pixels[1] x="+IJ.d2s(result[1][0],4)+" y="+IJ.d2s(result[1][1],4));
}
} else {
for (i=0;i<2;i++) for (j=0;j<2;j++) result[i][j]=max2[i][j]; // result is [2][3], max2 is [2][2]
}
/* Calculate locations of the maximums on FFT (corresponding to the diagonals of the checkerboard pattern) */
double [][] maxOnFFT = {{2*size*(max2[0][0]-max2[1][0]),2*size*(max2[0][1]-max2[1][1])},
{2*size*(max2[0][0]+max2[1][0]),2*size*(max2[0][1]+max2[1][1])}};
/* We have only one half of the FFT data so rotate 180-degrees around the center if the point is in the bottom half*/
double [] maxPhases = getPatternPhasesFromFFT(fft_complex, size, maxOnFFT);
double [] checkerPhases= findCheckerPhases(max2, maxPhases); /* may be different for greens==true . No, the same */
for (i=0;i<2;i++) result[i][2]=checkerPhases[i];
if (this.debugLevel>2) System.out.println();
return result;
}
/* ======================================================================== */
// calculate pattern 3D phases by interpolating im/re for the found maximums
private double [] getPatternPhasesFromFFT(
double [][][] fft_complex,
int size,
double [][] maxOnFFT) {
double [] maxPhases=new double[2];
boolean [] invertPhaseSign={false,false};
int maxIndex; // iterate through the two maximums on FFT for phase measurement
int [][] interpolateXY= new int [2][2];
double [][] interpolateKxy=new double [2][2];
double [][][] interpolatePhases=new double [2][2][2];
double [][][] interpolateAmplitudes=new double [2][2][2];// Maybe use it? if the amplitudes are very different?
int ix,iy;
boolean phaseCorr; // phase shift before averaging, to prevent rollover
for (maxIndex=0;maxIndex<2;maxIndex++) {
if (maxOnFFT[maxIndex][1]<0) {
invertPhaseSign[maxIndex]=true;
maxOnFFT[maxIndex][0]=-maxOnFFT[maxIndex][0];
maxOnFFT[maxIndex][1]=-maxOnFFT[maxIndex][1];
}
interpolateXY [maxIndex][1] = (int) maxOnFFT[maxIndex][1];
interpolateKxy[maxIndex][1] = maxOnFFT[maxIndex][1] - interpolateXY [maxIndex][1];
if (maxOnFFT[maxIndex][0]<0) {
interpolateXY [maxIndex][0] = (int) (size+ maxOnFFT[maxIndex][0]);
interpolateKxy [maxIndex][0] = (size+ maxOnFFT[maxIndex][0]) - interpolateXY[maxIndex][0];
} else {
interpolateXY [maxIndex][0] = (int) maxOnFFT[maxIndex][0];
interpolateKxy [maxIndex][0] = maxOnFFT[maxIndex][0] - interpolateXY[maxIndex][0];
}
for (int j=0;j<2;j++) {
ix=(interpolateXY[maxIndex][0]+j) % size;
for (int i=0;i<2;i++) {
iy=interpolateXY[maxIndex][1]+i; // next: OOB 2147483647
interpolateAmplitudes[maxIndex][i][j]= Math.sqrt(fft_complex[iy][ix][0]*fft_complex[iy][ix][0]+fft_complex[iy][ix][1]*fft_complex[iy][ix][1]);
interpolatePhases[maxIndex][i][j]= Math.atan2((invertPhaseSign[maxIndex]?-1.0:1.0)*fft_complex[iy][ix][1], fft_complex[iy][ix][0]);
if (this.debugLevel>5) {
System.out.println("maxIndex="+maxIndex+" ix="+ix+" iy="+iy+" phase="+IJ.d2s(interpolatePhases[maxIndex][i][j],4)+" amplitude="+interpolateAmplitudes[maxIndex][i][j]);
}
}
}
phaseCorr=false;
if ((interpolatePhases[maxIndex][0][0]> Math.PI/2) ||
(interpolatePhases[maxIndex][0][1]> Math.PI/2) ||
(interpolatePhases[maxIndex][1][0]> Math.PI/2) ||
(interpolatePhases[maxIndex][1][1]> Math.PI/2) ||
(interpolatePhases[maxIndex][0][0]<-Math.PI/2) ||
(interpolatePhases[maxIndex][0][1]<-Math.PI/2) ||
(interpolatePhases[maxIndex][1][0]<-Math.PI/2) ||
(interpolatePhases[maxIndex][1][1]<-Math.PI/2)) {
phaseCorr=true;
interpolatePhases[maxIndex][0][0]+= (interpolatePhases[maxIndex][0][0]<0)?Math.PI:-Math.PI;
interpolatePhases[maxIndex][0][1]+= (interpolatePhases[maxIndex][0][1]<0)?Math.PI:-Math.PI;
interpolatePhases[maxIndex][1][0]+= (interpolatePhases[maxIndex][1][0]<0)?Math.PI:-Math.PI;
interpolatePhases[maxIndex][1][1]+= (interpolatePhases[maxIndex][1][1]<0)?Math.PI:-Math.PI;
if (this.debugLevel>5) {
System.out.println("Shifting phases by PI/2 before averaging (to avoid rollover)");
}
}
maxPhases[maxIndex]= interpolateKxy[maxIndex][1] *(interpolateKxy[maxIndex][0] * interpolatePhases[maxIndex][1][1] + (1.0-interpolateKxy[maxIndex][0])* interpolatePhases[maxIndex][1][0])+
(1.0 - interpolateKxy[maxIndex][1])*(interpolateKxy[maxIndex][0] * interpolatePhases[maxIndex][0][1] + (1.0-interpolateKxy[maxIndex][0])* interpolatePhases[maxIndex][0][0]);
if (phaseCorr) maxPhases[maxIndex]+=(maxPhases[maxIndex]<0)?Math.PI:-Math.PI;
if (this.debugLevel>5) {
System.out.println("kx="+IJ.d2s(interpolateKxy [maxIndex][0],4)+ " ky="+IJ.d2s(interpolateKxy [maxIndex][1],4));
}
if (this.debugLevel>2) {
System.out.println("maxIndex="+maxIndex+" phase="+IJ.d2s(maxPhases[maxIndex],4));
}
}
return maxPhases;
}
/* ======================================================================== */
// zero is in the center
private int [][] findFirst2MinOnCorrelation(
double [] pixels,
double min_half_period, // from white to black
double max_half_period) { // from white to black
double min_fract_period = 0.3; //second minimum should be not closer to the first than this fraction of the first
// distance from zero
int size = (int) Math.sqrt(pixels.length);
int size2 = size >>1;
if (max_half_period <= 0) max_half_period = size;
if (min_half_period < 1) min_half_period = 1;
double mn2 = min_half_period*min_half_period;
double mx2 = max_half_period*max_half_period;
int [][] mins={{0,0},{0,0}};
double mn = 0.0; // minimums are always negative
// find the first minimum
for (int row = 0; row <= size2; row++) {
double dy2 = (row-size2)*(row-size2);
for (int col = 0; col < size; col++) {
double d2 = (col-size2)*(col-size2) + dy2;
if ((d2 >= mn2) && (d2 < mx2) && (pixels[row * size + col] < mn)) {
mn = pixels[row * size + col];
mins[0][0] = col-size2;
mins[0][1] = row-size2; // always <=0
}
}
}
if (mn ==0.0) {
return null; // could not find a first minimum
}
// find the second minimum (not too close to the first
int x0 = mins[0][0]+size2;
int y0 = mins[0][1]+size2;
int x1 = size - x0;
int y1 = size - y0;
mn = 0.0;
double mn2a = Math.max(mn2, min_fract_period*( mins[0][0]* mins[0][0]+mins[0][1]*mins[0][1]));
for (int row = 0; row <= size2; row++) {
double dy2 = (row-size2)*(row-size2);
for (int col = 0; col < size; col++) {
double d2 = (col-size2)*(col-size2) + dy2;
if ((d2 >= mn2) && (d2 < mx2) && (pixels[row * size + col] < mn)) {
// verify it is far enough from the first minimum and it's mirror
d2 = (row - y0)*(row -y0)+(col - x0)*(col - x0);
if (d2 >= 2*mn2a) { // diagonal
// verify it is far enough from the mirrored first
d2 = (row - y1)*(row -y1)+(col - x1)*(col - x1);
if (d2 >= 2 * mn2a) { // diagonal
mn = pixels[row * size + col];
mins[1][0] = col-size2;
mins[1][1] = row-size2; // always <=0
}
}
}
}
}
if (mn ==0.0) {
return null; // could not find a second minimum
}
return mins;
}
private int rad_search(int [][] half_periods) {
int ahp;
int amx;
int dist = -1;
for (int n = 0; n < half_periods.length; n++) {
amx = 0;
for (int i = 0; i < half_periods[0].length; i++) {
ahp = half_periods[n][i];
if (ahp < 0) ahp=-ahp;
if (ahp > amx) amx = ahp;
}
if ((dist <0) || (dist > amx)) dist = amx;
}
if (dist < 3) return 1;
return (dist -1) >> 1;
}
private boolean isLocalMinMax(double [] pixels, int size, int indx, boolean need_min) {
int sizesize = size*size;
for (int dy = -size; dy<=size; dy +=size) {
for (int dx = -1; dx <=1; dx++) {
int indx1 = indx + dy +dx;
if ((indx1 >= 0) && (indx1 < sizesize)){
if (need_min) {
if (pixels[indx] > pixels[indx1]) return false;
} else {
if (pixels[indx] < pixels[indx1]) return false;
}
}
}
}
return true;
}
private double [][] getPeriodsFromCorrelation(
double [] pixels,
int [][] half_periods, // a pair of half-periods
double min_frac, // minimal fraction of the center maximum to consider
boolean no_crazy ){ // discard min/max with failed interpolation
// how far to look around expected maximum/minimum
double [][] rslt = null;
int dbg_threshold = 3;
int search_radius = rad_search (half_periods);
// below first >= second
int [][] search_order = {{1,0}, // just half periods, negative
{1,1}, // diagonals, positive
{2,0}, // full period, positive
{2,1}, // 8 (4) directions, negative
{2,2}}; // positive
int size = (int) Math.sqrt(pixels.length);
int size2 = size/2;
int [][] aper = new int [2][2];
double [][] dhalf_periods = new double [2][2]; // will refine half_periods;
for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) aper[i][j] = Math.abs(half_periods[i][j]);
for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) dhalf_periods[i][j] = half_periods[i][j];
double min_avalue = pixels[size2*(size+1)]*min_frac; // minimal absolute value of min/max
int max_dist = size2 - 2; //arbitrary ??
int nord = 0; // to preserve after loop
layers_iteration:
for (nord = 0; nord < search_order.length; nord++) {
int [] xy_ind= search_order[nord];
// 1 check if too far to fit
if ( ((xy_ind[0] * aper[0][0] + xy_ind[1] * aper[1][0]) > max_dist ) ||
((xy_ind[0] * aper[0][1] + xy_ind[1] * aper[1][1]) > max_dist ) ||
((xy_ind[1] * aper[0][0] + xy_ind[0] * aper[1][0]) > max_dist ) ||
((xy_ind[1] * aper[0][1] + xy_ind[0] * aper[1][1]) > max_dist )
) {
break layers_iteration;
}
boolean are_mins = ((xy_ind[0] + xy_ind[1]) % 2) != 0;
int nspots = ((xy_ind[1]==0) || (xy_ind[0]==xy_ind[1])) ? 2 : 4;
// double [][] predicted_centers = new double nsamples
int [][] lin_comb = new int [nspots][2]; // number of half periods (incl. negative) to combine
if (xy_ind[1]==0) {
lin_comb[0][0] = xy_ind[0]; // first spot, first vector
lin_comb[0][1] = 0; // first spot, second vector
lin_comb[1][0] = 0; // second spot, first vector
lin_comb[1][1] = xy_ind[0]; // second spot, second vector
} else if (xy_ind[0]==xy_ind[1]){
lin_comb[0][0] = xy_ind[0]; // first spot, first vector
lin_comb[0][1] = xy_ind[0]; // first spot, second vector
lin_comb[1][0] = xy_ind[0]; // second spot, first vector
lin_comb[1][1] = -xy_ind[0]; // second spot, second vector
} else {
lin_comb[0][0] = xy_ind[0]; // first spot, first vector
lin_comb[0][1] = xy_ind[1]; // first spot, second vector
lin_comb[1][0] = xy_ind[0]; // second spot, first vector
lin_comb[1][1] = -xy_ind[1]; // second spot, second vector
lin_comb[2][0] = xy_ind[1]; // third spot, first vector
lin_comb[2][1] = xy_ind[0]; // third spot, second vector
lin_comb[3][0] = -xy_ind[1]; // fourth spot, first vector
lin_comb[3][1] = xy_ind[0]; // fourth spot, second vector
}
double [][] spot_centers = new double[nspots][2];
// iterate through all min/max spots in a layer, break outer loop on any failure (and use previous layer data)
for (int nspot = 0; nspot < nspots; nspot++) {
double [] xyc = {
lin_comb[nspot][0]*dhalf_periods[0][0] + lin_comb[nspot][1]*dhalf_periods[1][0],
lin_comb[nspot][0]*dhalf_periods[0][1] + lin_comb[nspot][1]*dhalf_periods[1][1]};
int [] ixyc = {(int) Math.round(xyc[0]),(int) Math.round(xyc[1])};
int [] ixym = ixyc.clone();
for (int y = ixyc[1] - search_radius; y <= ixyc[1] + search_radius; y ++ ) if ((y >= -max_dist) && (y < max_dist)) {
for (int x = ixyc[0] - search_radius; x <= ixyc[0] + search_radius; x ++ ) if ((x >= -max_dist) && (x < max_dist)) {
double d = pixels[(y+size2)*size+(x+size2)] - pixels[(ixym[1]+size2)*size+(ixym[0]+size2)];
if (are_mins) d= -d;
if (d > 0) {
ixym[0] = x;
ixym[1] = y;
}
}
}
// verify it is local max/min
if (!isLocalMinMax(pixels, size, (ixym[1]+size2)*size+(ixym[0]+size2), are_mins)) {
if (this.debugLevel > dbg_threshold) {
System.out.println("getPeriodsFromCorrelation(): is not a local max/min");
}
break layers_iteration;
}
// verify it is strong enough
if (Math.abs(pixels[(ixym[1]+size2)*size+(ixym[0]+size2)]) < min_avalue) { // BUG: -8030
if (this.debugLevel > dbg_threshold) {
System.out.println("getPeriodsFromCorrelation(): min/max is too weak: "+
pixels[(ixym[1]+size2)*size+(ixym[0]+size2)]+ " < "+ min_avalue+
" (layer"+nord+")");
}
break layers_iteration;
}
//use quadratic interpolation to find min/max
double [][][] data =new double [9][3][];
int index=0;
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
data[index][0] = new double [2];
data[index][1]= new double[1];
data[index][2]= new double[1];
int pix_indx = (ixym[1] + dy + size2) * size + (ixym[0] + dx + size2);
if ((pix_indx >= 0) && (pix_indx < pixels.length)) {
data[index][0][0] = dx;
data[index][0][1] = dy;
data[index][1][0]= are_mins ? -pixels[pix_indx] : pixels[pix_indx];
data[index][2][0]= 1.0;
} else {
data[index][2][0]= 0.0;
}
index++;
}
}
double [] corrXY=(new PolynomialApproximation()).quadraticMax2d (data);
if (corrXY == null) {
if (no_crazy) {
if (this.debugLevel > dbg_threshold) {
System.out.println("getPeriodsFromCorrelation(): interpolation failed,"+
" (layer"+nord+")");
}
break layers_iteration;
}
corrXY=new double[2];
corrXY[0] = 0.0;
corrXY[1] = 0.0;
}
// verify that interpolation did not go crazy. If it did - reset to center
if ((corrXY[0] > 1.5) || (corrXY[1] > 1.5) || (corrXY[0] < -1.5) || (corrXY[1] < -1.5)) {
if (no_crazy) {
if (this.debugLevel > dbg_threshold) {
System.out.println("getPeriodsFromCorrelation(): interpolation failed, "+
"corrXY = ["+corrXY[0]+", "+corrXY[1]+"] (layer"+nord+")");
}
break layers_iteration;
}
corrXY[0] = 0.0;
corrXY[1] = 0.0;
}
spot_centers[nspot][0] = ixym[0] + corrXY[0];
spot_centers[nspot][1] = ixym[1] + corrXY[1];
}
// refine half-period values
if (xy_ind[1]==0) {
dhalf_periods[0][0] = spot_centers[0][0]/xy_ind[0];
dhalf_periods[0][1] = spot_centers[0][1]/xy_ind[0];
dhalf_periods[1][0] = spot_centers[1][0]/xy_ind[0];
dhalf_periods[1][1] = spot_centers[1][1]/xy_ind[0];
} else if (xy_ind[0]==xy_ind[1]){
dhalf_periods[0][0] = (spot_centers[0][0] + spot_centers[1][0])/2/xy_ind[0];
dhalf_periods[0][1] = (spot_centers[0][1] + spot_centers[1][1])/2/xy_ind[0];
dhalf_periods[1][0] = (spot_centers[0][0] - spot_centers[1][0])/2/xy_ind[0];
dhalf_periods[1][1] = (spot_centers[0][1] - spot_centers[1][1])/2/xy_ind[0];
} else {
dhalf_periods[0][0] = (spot_centers[0][0] + spot_centers[1][0] + spot_centers[2][0] - spot_centers[3][0]) / (xy_ind[0] + xy_ind[1])/2;
dhalf_periods[0][1] = (spot_centers[0][1] + spot_centers[1][1] + spot_centers[2][1] - spot_centers[3][1]) / (xy_ind[0] + xy_ind[1])/2;
dhalf_periods[1][0] = (spot_centers[0][0] - spot_centers[1][0] + spot_centers[2][0] + spot_centers[3][0]) / (xy_ind[0] + xy_ind[1])/2;
dhalf_periods[1][1] = (spot_centers[0][1] - spot_centers[1][1] + spot_centers[2][1] + spot_centers[3][1]) / (xy_ind[0] + xy_ind[1])/2;
}
} // for (int nord = 0; nord < search_order.length; nord++) {
// double [][] pattern_diagonals = {
// {dhalf_periods[0][0]+dhalf_periods[1][0], dhalf_periods[0][1]+dhalf_periods[1][1]},
// {dhalf_periods[0][0]-dhalf_periods[1][0], dhalf_periods[0][1]-dhalf_periods[1][1]}};
double [][] scaled_v = new double [2][2];
double k_scale = 4.0;
for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) {
scaled_v[i][j] = k_scale*dhalf_periods[i][j]; // not clear why 4 and not 2
}
// rslt = vectToWaveVect(pattern_diagonals);
// make vectors to have positive y:
for (int i = 0; i < 2; i++) {
if (scaled_v[i][1] <0) {
scaled_v[i][0] = - scaled_v[i][0];
scaled_v[i][1] = - scaled_v[i][1];
}
}
rslt = vectToWaveVect(scaled_v);
// rslt = dhalf_periods;
// sort so first vector to second vector will be clockwise (positive y is downwards)
{int j=0, k=1;
if ((rslt[j][0] * rslt[k][1] - rslt[k][0] * rslt[j][1]) < 0) {
double [] tmp = rslt[0];
rslt[0] = rslt[1];
rslt[1] = tmp;
}
}
for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) {
if (Double.isNaN(rslt[i][j]) || Double.isInfinite(rslt[i][j])) {
System.out.println("got NaN/Infinity, nord = "+nord);
return null;
}
}
return rslt;
}
//vect[0][] - 1-st vector connecting nodes, vect[1][] - second vector
// return [0][] - first wave vector, orthogonal to vecgt[0][], return [1][] - to the second vect[1][]
double [][] vectToWaveVect(double [][] vect){
double a = 1.0/(vect[0][0]*vect[1][1] -vect[0][1]*vect[1][0]);
// double [] rv0 = {-vect[0][1], vect[0][0]};
// double [] rv1 = { vect[1][1], -vect[1][0]};
// double [][] wv= {{a*rv0[0], a*rv0[1]},{a*rv1[0], a*rv1[1]}};
double [][] wv= {{-a*vect[0][1], a*vect[0][0]}, {a*vect[1][1], -a*vect[1][0]}};
return wv;
}
private int [][] findFirst2MaxOnSpectrum (double [][][] pixels, // complex, top half, starting from 0,0
/* May need to reduce the skip_around to be able to handle smaller number of pattern periods? Or re-try if failed? Guess somehow?*/
int skip_around, // skip +- from (0,0) and previous max
......@@ -2075,7 +2774,8 @@ public class MatchSimulatedPattern {
}
/* ======================================================================== */
/* Can it handle negative y if the refined maximum goes there? (maximal value on positive Y) */
private double[][] findFirst2MaxOnCorrelation(double [] pixels,
private double[][] findFirst2MaxOnCorrelation(
double [] pixels,
int [][] startPoints,
PatternDetectParameters patternDetectParameters
) {
......@@ -2083,7 +2783,7 @@ public class MatchSimulatedPattern {
int size =(int) Math.sqrt (pixels.length);
int [][] imax =startPoints.clone();
int [][] imax2 =new int [2*patternDetectParameters.multiplesToTry][2];
boolean []maxDefined=new boolean [2*patternDetectParameters.multiplesToTry];
boolean []maxDefined=new boolean [2*patternDetectParameters.multiplesToTry]; //.multiplesToTry = 4;
double [] maxValues =new double [startPoints.length];
double [] max2Values =new double [2];
......@@ -2105,7 +2805,7 @@ public class MatchSimulatedPattern {
/* Look for the maximal values around startPoints (+/-diff_spectr_corr )*/
for (nmax=0; nmax<startPoints.length; nmax++) {
ymn=imax[nmax][1]-patternDetectParameters.diffSpectrCorr;
ymn=imax[nmax][1]-patternDetectParameters.diffSpectrCorr; // .diffSpectrCorr=2
ymx=imax[nmax][1]+patternDetectParameters.diffSpectrCorr;
if (ymx>lim) ymx=lim;
xmn=imax[nmax][0]-patternDetectParameters.diffSpectrCorr;
......@@ -2166,7 +2866,7 @@ public class MatchSimulatedPattern {
isMax=false;
indx+=dirs[j];
imax[nmax][1]=(indx / size) - halfSize;
imax[nmax][1]=(indx % size) - halfSize;
imax[nmax][0]=(indx % size) - halfSize;
break;
}
}
......@@ -2348,7 +3048,7 @@ public class MatchSimulatedPattern {
/* Average (or just use farthest?) multiple maximums */
if (this.debugLevel>2){
float [] dbg_pixels=new float[clusterMap.length];
for (j=0;j<dbg_pixels.length;j++) dbg_pixels[j]=(float)clusterMap[j];
for (j=0;j<dbg_pixels.length;j++) dbg_pixels[j]=clusterMap[j];
dbg_pixels[(size+1)*size/2]=-1; // mark center
ImageProcessor ip=new FloatProcessor(size,size);
......@@ -2475,9 +3175,8 @@ public class MatchSimulatedPattern {
v[0][1]=-wv1[0]/vect_wv0_x_wv1;
v[1][0]=-wv0[1]/vect_wv0_x_wv1;
v[1][1]= wv0[0]/vect_wv0_x_wv1;
v[0][2]=wv0[2];
v[1][2]=wv1[2];
if (wv0.length>2) v[0][2]=wv0[2];
if (wv1.length>2) v[1][2]=wv1[2];
/* "white square" center had coordinates
-wv0[0]
*/
......@@ -2898,9 +3597,12 @@ public class MatchSimulatedPattern {
double [] greens=normalizeAndWindow (input_bayer[4], windowFunction);
double [][] pattern=matchSimulatedPattern.findPattern(
null, // DoubleFHT doubleFHT,
greens,
distortionParameters.FFTSize,
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
patternDetectParameters.maxGridPeriod/2,
true, // this is a pattern for combined greens (diagonal), adjust results accordingly
"Pattern"); // title - will not be used
if (pattern==null) {
......@@ -2992,9 +3694,12 @@ public class MatchSimulatedPattern {
* [2][2] - Wave vector 2 phase (not used here)
*/
public double[][] tryPattern (
DoubleFHT doubleFHT,
double [] point, // xy to try
final DistortionParameters distortionParameters, //
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
final double min_half_period,
final double max_half_period,
final SimulationPattern.SimulParameters thisSimulParameters,
final MatchSimulatedPattern matchSimulatedPattern,
final MatchSimulatedPattern matchSimulatedPatternCorr,
......@@ -3010,6 +3715,10 @@ public class MatchSimulatedPattern {
String dbgStr
){
this.debugLevel = 3;
int debug_threshold = 2;
if (imp==null) {
if (dbgStr!=null) System.out.println(dbgStr+" imp==null");
return null;
......@@ -3034,15 +3743,18 @@ public class MatchSimulatedPattern {
}
//create diagonal green selection around xc,yc
double [][] input_bayer=splitBayer (imp,initialPatternCell,equalizeGreens);
if (debugLevel>2) SDFA_INSTANCE.showArrays(input_bayer, true, "selection--bayer");
if (debugLevel > (debug_threshold + 0)) SDFA_INSTANCE.showArrays(input_bayer, true, "selection--bayer");
double [] greens=normalizeAndWindow (input_bayer[4], windowFunction);
double [][] pattern=matchSimulatedPattern.findPattern(
doubleFHT,
greens,
distortionParameters.FFTSize,
patternDetectParameters,
min_half_period,
max_half_period,
true, // this is a pattern for combined greens (diagonal), adjust results accordingly
"Pattern"); // title - will not be used
if (pattern==null) {
......@@ -3051,8 +3763,8 @@ public class MatchSimulatedPattern {
if (dbgStr!=null) System.out.println(dbgStr+" matchSimulatedPattern.findPattern->null");
return null;
}
if (debugLevel>2) System.out.println("FX1="+pattern[0][0]+" FY1="+pattern[0][1]+" phase1="+pattern[0][2]);
if (debugLevel>2) System.out.println("FX2="+pattern[1][0]+" FY2="+pattern[1][1]+" phase2="+pattern[1][2]);
if (debugLevel > (debug_threshold + 0)) System.out.println("FX1="+pattern[0][0]+" FY1="+pattern[0][1]+" phase1="+pattern[0][2]);
if (debugLevel > (debug_threshold + 0)) System.out.println("FX2="+pattern[1][0]+" FY2="+pattern[1][1]+" phase2="+pattern[1][2]);
double [] ll2=new double[2];
double [][] dxy=new double[2][2];
double [][] phases=new double[2][2];
......@@ -3061,27 +3773,27 @@ public class MatchSimulatedPattern {
ll2[i]=(pattern[i][0]*pattern[i][0]+pattern[i][1]*pattern[i][1])*2*Math.PI;
}
if (debugLevel>2) System.out.println("phase1/2pi="+(pattern[0][2]/2/Math.PI)+" phase2/2pi="+(pattern[1][2]/2/Math.PI));
if (debugLevel > (debug_threshold + 0)) System.out.println("phase1/2pi="+(pattern[0][2]/2/Math.PI)+" phase2/2pi="+(pattern[1][2]/2/Math.PI));
for (k=0;k<2;k++) {
for (j=0;j<2;j++) {
phases[k][j]= pattern[j][2]-Math.PI/2+((k>0)? Math.PI:0.0);
while (phases[k][j]<-Math.PI) phases[k][j]+=2*Math.PI;
while (phases[k][j]>Math.PI) phases[k][j]-=2*Math.PI;
}
if (debugLevel>2) System.out.println("phase1/2pi="+(phases[k][0]/2/Math.PI)+" phase2/2pi="+(phases[k][1]/2/Math.PI));
if (debugLevel > (debug_threshold + 0)) System.out.println("phase1/2pi="+(phases[k][0]/2/Math.PI)+" phase2/2pi="+(phases[k][1]/2/Math.PI));
for (i=0;i<2;i++) {
dxy[k][i]=0;
for (j=0;j<2;j++) {
dxy[k][i]+=(phases[k][j])*pattern[j][i]/ll2[j];
}
}
if (debugLevel>2) System.out.println("dX["+k+"]="+dxy[k][0]+" dY["+k+"]="+dxy[k][1]);
if (debugLevel > (debug_threshold + 0)) System.out.println("dX["+k+"]="+dxy[k][0]+" dY["+k+"]="+dxy[k][1]);
}
int phaseSel=((dxy[0][0]*dxy[0][0]+dxy[0][1]*dxy[0][1])<(dxy[1][0]*dxy[1][0]+dxy[1][1]*dxy[1][1]))?0:1;
if (debugLevel>2) System.out.println("xc="+xc+" yc="+yc);
if (debugLevel>2) System.out.println("dX="+dxy[phaseSel][0]+" dY="+dxy[phaseSel][1]);
if (debugLevel > (debug_threshold + 0)) System.out.println("xc="+xc+" yc="+yc);
if (debugLevel > (debug_threshold + 0)) System.out.println("dX="+dxy[phaseSel][0]+" dY="+dxy[phaseSel][1]);
double [] centerXY0={xc-dxy[phaseSel][0],yc-dxy[phaseSel][1]};
if (debugLevel>1) System.out.println("+++ Initial center x="+IJ.d2s(centerXY0[0],3)+" y="+ IJ.d2s(centerXY0[1],3));
if (debugLevel > (debug_threshold - 1)) System.out.println("+++ Initial center x="+IJ.d2s(centerXY0[0],3)+" y="+ IJ.d2s(centerXY0[1],3));
double [] centerXY=correctedPatternCrossLocation(
centerXY0, // initial coordinates of the pattern cross point
pattern[0][0],
......@@ -3105,7 +3817,7 @@ public class MatchSimulatedPattern {
locsNeib,
debugLevel,
dbgStr);
if (debugLevel>1) System.out.println("--- Initial center x="+IJ.d2s(centerXY0[0],3)+" y="+ IJ.d2s(centerXY0[1],3)+
if (debugLevel > (debug_threshold - 1)) System.out.println("--- Initial center x="+IJ.d2s(centerXY0[0],3)+" y="+ IJ.d2s(centerXY0[1],3)+
" -> "+((centerXY==null)?" NULL ":(IJ.d2s(centerXY[0],3)+" : "+ IJ.d2s(centerXY[1],3))));
double [][] node = {centerXY,pattern[0],pattern[1]};
if (dbgStr!=null) {
......@@ -3114,6 +3826,14 @@ public class MatchSimulatedPattern {
}
return node;
}
/* ================================================================*/
// Optionally remove the outer (possibly corrupted) layer of the detected pattern nodes, extrapolate new layers of the nodes
// without pattern matching
......@@ -3238,6 +3958,8 @@ public class MatchSimulatedPattern {
final boolean [] triedIndices,
final DistortionParameters distortionParameters, //
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
final double min_half_period,
final double max_half_period,
final SimulationPattern.SimulParameters simulParameters,
final boolean equalizeGreens,
final ImagePlus imp, // image to process
......@@ -3342,23 +4064,9 @@ public class MatchSimulatedPattern {
int nbv,nbh,nh,nv,nb;
if (debugLevel>1) System.out.println("selection.x="+selection.x+" selection.y="+selection.y+" selection.width="+selection.width+" selection.height="+selection.height);
if (debugLevel>1) System.out.println("numTries="+numTries+" tryHor="+tryHor+" tryVert="+tryVert);
// double [][] node=null;
// double [][][] nodes=null;
boolean oldMode=false; //true; // false;
/*
if (startScanIndex[0]==0) startScanIndex[0]=3;
if (startScanIndex[0]<0){
System.out.println("distortions(): BUG - startScanIndex[0]="+startScanIndex[0]+" <0");
this.PATTERN_GRID=null;
return 0;
}
*/
if (oldMode) { // old (single-threaded) mode
// for (int n=startScanIndex[0];n<numTries;n++) {
// final boolean [] triedIndices,
// nodes = new double [1][][];
// nodes[0]=null;
if (oldMode) { // old (single-threaded) mode
for (int startScanIndex=3;startScanIndex<=numTries;startScanIndex++) if (!triedIndices[startScanIndex]){
if (startScanIndex==numTries){
triedIndices[startScanIndex]=true; // all done
......@@ -3389,9 +4097,12 @@ public class MatchSimulatedPattern {
// System.out.println("### trying xc="+point[0]+", yc="+point[1]+"(nv="+nv+", nh="+nh+")");
if ((debugLevel>2) && (startScanIndex==3)) debugLevel=3; // show debug images for the first point only
double [][] node=tryPattern (
null,
point, // xy to try
thisDistortionParameters, //no control of the displacement
patternDetectParameters,
min_half_period,
max_half_period,
thisSimulParameters,
matchSimulatedPattern,
matchSimulatedPatternCorr,
......@@ -3429,6 +4140,8 @@ public class MatchSimulatedPattern {
selection,
thisDistortionParameters, //no control of the displacement
patternDetectParameters,
min_half_period,
max_half_period,
thisSimulParameters,
matchSimulatedPattern,
matchSimulatedPatternCorr,
......@@ -3627,6 +4340,7 @@ public class MatchSimulatedPattern {
cellNum.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
SimulationPattern simulationPattern= new SimulationPattern(bPattern);
MatchSimulatedPattern matchSimulatedPatternCorr=new MatchSimulatedPattern(distortionParameters.correlationSize);
......@@ -4051,6 +4765,8 @@ public class MatchSimulatedPattern {
final Rectangle selection,
final DistortionParameters distortionParameters, //
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
final double min_half_period,
final double max_half_period,
final SimulationPattern.SimulParameters thisSimulParameters,
final MatchSimulatedPattern matchSimulatedPattern,
final MatchSimulatedPattern matchSimulatedPatternCorr,
......@@ -4080,9 +4796,11 @@ public class MatchSimulatedPattern {
// System.out.println();
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
int nbh, nbv, nh, nv, nb;
double [] point = new double[2];
DoubleFHT doubleFHT = new DoubleFHT();
// for (int n=seqNumber.getAndIncrement(); n< numTries;n=seqNumber.getAndIncrement()){
for (int n=seqNumber.getAndIncrement(); n<(triedIndices.length-1); n=seqNumber.getAndIncrement()) if (!triedIndices[n]){
if (nodeSet.get()) break; // already set
......@@ -4110,9 +4828,12 @@ public class MatchSimulatedPattern {
if (debugLevel>2) System.out.println("trying xc="+point[0]+", yc="+point[1]+"(nv="+nv+", nh="+nh+")");
// if ((debugLevel>2) && (n==3)) debugLevel=3; // show debug images for the first point
double [][] node=tryPattern (
doubleFHT,
point, // xy to try
distortionParameters, //no control of the displacement
patternDetectParameters,
min_half_period,
max_half_period,
thisSimulParameters,
matchSimulatedPattern,
matchSimulatedPatternCorr,
......@@ -4164,18 +4885,17 @@ public class MatchSimulatedPattern {
}
}
// private double [][][] findPatternCandidates(
private Queue<GridNode> findPatternCandidates(
// final int [] startScanIndex, // [0] will be updated
final boolean [] triedIndices, // which indices are already tried
final int startScanIndex,
final int tryHor,
final int tryVert,
// final int numTries,
final Rectangle selection,
final DistortionParameters distortionParameters, //
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
final double min_half_period,
final double max_half_period,
final SimulationPattern.SimulParameters thisSimulParameters,
final MatchSimulatedPattern matchSimulatedPattern,
final MatchSimulatedPattern matchSimulatedPatternCorr,
......@@ -4192,7 +4912,7 @@ public class MatchSimulatedPattern {
final boolean updateStatus,
final int debugLevel
){
final int debugThreshold=1;
final int debugThreshold=-1; // 1; ** Restore 1
if ((debugLevel>debugThreshold) && ((debugLevel>1) || (startScanIndex>3))) {
int debugNumLeft=0;
for (boolean b:triedIndices) if (!b) debugNumLeft++;
......@@ -4201,19 +4921,17 @@ public class MatchSimulatedPattern {
final Thread[] threads = newThreadArray(threadsMax);
final AtomicInteger seqNumber = new AtomicInteger(startScanIndex);
// final AtomicBoolean nodeSet=new AtomicBoolean(false);
// final double [][][] nodeRef= new double[1][][];
// nodeRef[0]=null;
final AtomicInteger debugNumThreadAtomic= new AtomicInteger(0);
final Queue<GridNode> nodeQueue = new ConcurrentLinkedQueue<GridNode>();
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
int nbh, nbv, nh, nv, nb;
double [] point = new double[2];
// SimulationPattern simulationPatternClone=simulationPattern.clone();
DoubleFHT doubleFHT = new DoubleFHT();
int debugNumThread=debugNumThreadAtomic.getAndIncrement();
for (int n=seqNumber.getAndIncrement(); n<(triedIndices.length-1); n=seqNumber.getAndIncrement()) if (!triedIndices[n]){
if (!nodeQueue.isEmpty()) break; // already set at least one element - does it work?
......@@ -4239,12 +4957,14 @@ public class MatchSimulatedPattern {
point[0]=(selection.x+nh*selection.width/(1<<tryHor)) & ~1;
point[1]=(selection.y+nv*selection.height/(1<<tryVert)) & ~1;
if (debugLevel>2) System.out.println("trying xc="+point[0]+", yc="+point[1]+"(nv="+nv+", nh="+nh+")");
// if ((debugLevel>2) && (n==3)) debugLevel=3; // show debug images for the first point
if (debugLevel>2) System.out.println(debugNumThread+":"+n+" >> ");
double [][] node=tryPattern (
doubleFHT,
point, // xy to try
distortionParameters, //no control of the displacement
patternDetectParameters,
min_half_period,
max_half_period,
thisSimulParameters,
matchSimulatedPattern,
matchSimulatedPatternCorr,
......@@ -4259,10 +4979,8 @@ public class MatchSimulatedPattern {
locsNeib, // which neibors to try (here - just the center)
(debugLevel>debugThreshold)?(""+debugNumThread+":"+n+", nv="+nv+", nh="+nh+", nb="+nb+" "+point[0]+"/"+point[1]):null
);
// if (debugLevel>0) System.out.println(debugNumThread+":"+n+", nv="+nv+", nh="+nh+", nb="+nb+" "+point[0]+"/"+point[1]+" "+(node!=null));
if ((node!=null) && (node[0]!=null)) {
nodeQueue.add(new GridNode(node));
// if (debugLevel>1) System.out.println("adding candidate "+n+" x0="+point[0]+" y0="+point[1]+" -> "+ node[0][0]+"/"+node[0][1]);
if (debugLevel>debugThreshold) System.out.println("adding candidate "+n+" x0="+point[0]+" y0="+point[1]+" -> "+ node[0][0]+"/"+node[0][1]+" seqNumber.get()="+seqNumber.get()+" n="+n);
}
} else {
......@@ -4274,15 +4992,11 @@ public class MatchSimulatedPattern {
};
}
startAndJoin(threads);
// if (nodeQueue.isEmpty()) return null;
if (debugLevel>debugThreshold){
System.out.println("seqNumber after join is "+seqNumber.get());
}
if (seqNumber.get()>=(triedIndices.length-1) ) triedIndices[triedIndices.length-1]=true; // all tried
return nodeQueue; // never null, may be empty
// double [][][] nodes = new double [nodeQueue.size()][][];
// for (int i=0;i<nodes.length;i++) nodes[i]=nodeQueue.poll().getNode();
// return nodes;
}
/* ================================================================*/
......@@ -4396,6 +5110,7 @@ public class MatchSimulatedPattern {
// MinMaxSync minMaxSync=new MinMaxSync();
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
SimulationPattern simulationPattern= new SimulationPattern(bPattern);
MatchSimulatedPattern matchSimulatedPatternCorr=new MatchSimulatedPattern(distortionParameters.correlationSize);
......@@ -4513,6 +5228,7 @@ public class MatchSimulatedPattern {
}
final int numFinished=cellNumDoneAtomic.getAndIncrement();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Here, we can safely update the GUI
// because we'll be called from the
......@@ -4798,6 +5514,7 @@ public class MatchSimulatedPattern {
for (int v=0;v<height;v++) for (int u=0;u<width;u++) newGrid[v][u]=null;
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
int [] iUV= new int [2];
for (int ncell=cellNum.getAndIncrement(); ncell<(width*height);ncell=cellNum.getAndIncrement()){
......@@ -5312,6 +6029,7 @@ public class MatchSimulatedPattern {
pixInWaveNum.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
// for (int i =0;i<extList.size();i++){
......@@ -5818,6 +6536,8 @@ public class MatchSimulatedPattern {
public int calculateDistortions(
MatchSimulatedPattern.DistortionParameters distortionParameters, //
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
double min_half_period,
double max_half_period,
SimulationPattern.SimulParameters simulParameters,
boolean equalizeGreens,
ImagePlus imp, // image to process
......@@ -5854,7 +6574,6 @@ public class MatchSimulatedPattern {
// save initial distortionParameters.correlationMinInitialContrast
double savedCorrelationMinInitialContrast=distortionParameters.correlationMinInitialContrast;
int reTries= 10; // bail out after these attempts
// int [] startScanIndex={0}; // scan for pattern will update this index to continue next time (<0 - nothing left)
boolean foundGoodCluster=false;
int tryHor=0,tryVert=0;
......@@ -5870,9 +6589,6 @@ public class MatchSimulatedPattern {
int numTries=1<<(tryHor+tryVert);
boolean [] triedIndices=new boolean[numTries+1]; // last set - all used
for (int i=0;i<triedIndices.length;i++) triedIndices[i]=(i<3); // mark first 3 as if they are already used
// ========= Removing adjustment of contrast ==============
// boolean fromVeryBeginning=true;
while (reTries-->0) {
......@@ -5881,9 +6597,10 @@ public class MatchSimulatedPattern {
patternCells=distortions( // calculates matchSimulatedPattern.DIST_ARRAY // invalidates calibration, flatFieldForGrid, resets this.PATTERN_GRID
triedIndices,
// startScanIndex, // [0] will be updated
distortionParameters, //
patternDetectParameters,
min_half_period,
max_half_period,
simulParameters,
equalizeGreens,
imp,
......@@ -5898,79 +6615,6 @@ public class MatchSimulatedPattern {
break; // new distortions() code - returns non-zero only if passed other tests
}
// ========= Removing adjustment of contrast ==============
// if (fromVeryBeginning){
// if (global_debug_level>0) System.out.println("--- Nothing found at all --- at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
// break; // or maybe - still try to adjust threshold?
// }
/*
double averageGridPeriod=Double.NaN;
if (this.PATTERN_GRID!=null) averageGridPeriod=averageGridPeriod(this.PATTERN_GRID);
if (global_debug_level>0){
System.out.println("Pattern period="+averageGridPeriod+
" limits are set to :"+patternDetectParameters.minGridPeriod+","+patternDetectParameters.maxGridPeriod);
}
if (!Double.isNaN(averageGridPeriod)) {
if (!Double.isNaN(patternDetectParameters.minGridPeriod) &&
(patternDetectParameters.minGridPeriod>0.0) &&
(averageGridPeriod<patternDetectParameters.minGridPeriod)){
if (global_debug_level>0){
System.out.println("Pattern is too small, period="+averageGridPeriod+
" minimal="+patternDetectParameters.minGridPeriod);
}
continue; //?
}
if (!Double.isNaN(patternDetectParameters.maxGridPeriod) &&
(patternDetectParameters.maxGridPeriod>0.0) &&
(averageGridPeriod>patternDetectParameters.maxGridPeriod)){
if (global_debug_level>0){
System.out.println("Pattern is too large, period="+averageGridPeriod+
" maximal="+patternDetectParameters.maxGridPeriod);
}
continue; //?
}
}
if (
(distortionParameters.minimalPatternCluster<=0) || // minimal cluster size is disabled
(distortionParameters.scaleMinimalInitialContrast<=0) || // minimal cluster size is disabled
((patternCells==0) && fromVeryBeginning)|| // no cells detected at all, starting from the very beginning
(patternCells>=distortionParameters.minimalPatternCluster) // detected enough cells
){
foundGoodCluster=true;
break;
}
fromVeryBeginning=false;
if (roi!=null){ // 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 ("+patternCells+"), but ROI is set - no retries");
{
foundGoodCluster=true;
break;
}
} else {
// if (global_debug_level>0){
// if (startScanIndex[0]>=0) {
if (!triedIndices[triedIndices.length-1]) {
if (global_debug_level>0){
int startScanIndex=3;
for (;(startScanIndex<triedIndices.length) && triedIndices[startScanIndex];startScanIndex++); // skip tried indices
System.out.println("Initial pattern cluster is too small ("+patternCells+
"), continuing scanning from index "+startScanIndex);
}
} else {
// startScanIndex[0]=0;
System.out.println("Last pattern cluster was too small, adjusting the minimal contrast from "+
IJ.d2s(distortionParameters.correlationMinInitialContrast,3)+
" to "+IJ.d2s(distortionParameters.correlationMinInitialContrast*distortionParameters.scaleMinimalInitialContrast,3));
distortionParameters.correlationMinInitialContrast*=distortionParameters.scaleMinimalInitialContrast;
for (int i=0;i<triedIndices.length;i++) triedIndices[i]=(i<3); // mark first 3 as if they are already used
fromVeryBeginning=true;
}
}
// distortionParameters.correlationMinInitialContrast*=distortionParameters.scaleMinimalInitialContrast;
// }
*/
boolean someLeft=false;
int startScanIndex=0;
for (startScanIndex=3;startScanIndex<triedIndices.length;startScanIndex++) if (!triedIndices[startScanIndex]){
......@@ -5979,26 +6623,13 @@ public class MatchSimulatedPattern {
}
if (someLeft) {
// if (!triedIndices[triedIndices.length-1]) {
if (global_debug_level>0){
// int startScanIndex=3;
// for (;(startScanIndex<triedIndices.length) && triedIndices[startScanIndex];startScanIndex++); // skip tried indices
System.out.println("Initial pattern cluster is too small ("+patternCells+
"), continuing scanning from index "+startScanIndex);
}
} else {
if (global_debug_level>0) System.out.println("--- Tried all - nothing found --- at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
break;
// ========= Removing adjustment of contrast ==============
/*
// startScanIndex[0]=0;
System.out.println("Last pattern cluster was too small, adjusting the minimal contrast from "+
IJ.d2s(distortionParameters.correlationMinInitialContrast,3)+
" to "+IJ.d2s(distortionParameters.correlationMinInitialContrast*distortionParameters.scaleMinimalInitialContrast,3));
distortionParameters.correlationMinInitialContrast*=distortionParameters.scaleMinimalInitialContrast;
for (int i=0;i<triedIndices.length;i++) triedIndices[i]=(i<3); // mark first 3 as if they are already used
fromVeryBeginning=true;
*/
}
}
......@@ -7059,8 +7690,8 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
for (int i=0;i<4;i++) pixels[i]= (float[]) stack.getPixels(i+1); // pixel X : negative - no grid here
int minU=0,minV=0,maxU=0,maxV=0;
for (int i=0;i<pixels[0].length;i++) if (pixels[0][i]>=0) {
int u=(int) Math.round(pixels[2][i]);
int v=(int) Math.round(pixels[3][i]);
int u=Math.round(pixels[2][i]);
int v=Math.round(pixels[3][i]);
if (numCells==0){
minV=v;
maxV=v;
......@@ -7079,8 +7710,8 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
double [] xy=new double[2];
int [] uv=new int[2];
for (int i=0;i<pixels[0].length;i++) if (pixels[0][i]>=0) {
uv[0]=((int) Math.round(pixels[2][i]))-minU;
uv[1]=((int) Math.round(pixels[3][i]))-minV;
uv[0]=(Math.round(pixels[2][i]))-minU;
uv[1]=(Math.round(pixels[3][i]))-minV;
xy[0]=pixels[0][i];
xy[1]=pixels[1][i];
setPatternGridCell(
......@@ -7343,8 +7974,8 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
} else {
pixels [0][index]=(float) this.pXYUV[v][u][0];
pixels [1][index]=(float) this.pXYUV[v][u][1];
pixels [2][index]=(float) this.targetUV[v][u][0];
pixels [3][index]=(float) this.targetUV[v][u][1];
pixels [2][index]=this.targetUV[v][u][0];
pixels [3][index]=this.targetUV[v][u][1];
if (numSlices>4){
pixels [4][index]=(float) this.gridContrastBrightness[0][v][u]; // grid contrast
pixels [5][index]=(float) this.gridContrastBrightness[1][v][u]; // red
......@@ -8478,6 +9109,7 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
int debug_level,
String dbgStr
){
int debug_threshold = 2;
// next print - same for good and bad, correction==null
if (dbgStr!=null) System.out.println(dbgStr+ ": wv0x="+wv0x+" wv0y="+wv0y+ " wv1x="+wv1x+" wv1y="+wv1y+
" beforeXY[0]="+beforeXY[0]+", beforeXY[1]="+beforeXY[1]+" correction is "+((correction==null)?"null":"not null"));
......@@ -8486,6 +9118,7 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
boolean dbgThis=
(Math.abs(beforeXY[0]-patternDetectParameters.debugX)<patternDetectParameters.debugRadius) &&
(Math.abs(beforeXY[1]-patternDetectParameters.debugY)<patternDetectParameters.debugRadius);
dbgThis=true;
if (dbgThis) {
System.out.println("correctedPatternCrossLocationAverage4(), beforeXY[0]="+beforeXY[0]+", beforeXY[1]="+beforeXY[1]);
debug_level+=3;
......@@ -8513,7 +9146,7 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
double [][]wv={{wv0x, wv0y},
{wv1x, wv1y}};
double [][] WVgreens=matrix2x2_mul(wv,invConvMatrix);
if (debug_level>2) System.out.println("WVgreens[0][0]="+IJ.d2s(WVgreens[0][0],3)+
if (debug_level > debug_threshold) System.out.println("WVgreens[0][0]="+IJ.d2s(WVgreens[0][0],3)+
" WVgreens[0][1]="+IJ.d2s(WVgreens[0][1],3)+
" WVgreens[1][0]="+IJ.d2s(WVgreens[1][0],3)+
" WVgreens[1][1]="+IJ.d2s(WVgreens[1][1],3));
......@@ -8583,7 +9216,7 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
}
*/
setCorrelationSizesUsed(thisCorrelationSize);
if ((debug_level>0)&&(thisCorrelationSize>distortionParameters.correlationSize)) System.out.println("**** u/v span too small, increasing FFT size to "+thisCorrelationSize);
if ((debug_level > (debug_threshold - 2))&&(thisCorrelationSize>distortionParameters.correlationSize)) System.out.println("**** u/v span too small, increasing FFT size to "+thisCorrelationSize);
Rectangle centerCross=correlationSelection(
beforeXY, // initial coordinates of the pattern cross point
thisCorrelationSize);
......@@ -8593,14 +9226,14 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
double [] diffBeforeXY={beforeXY[0]-ixc, beforeXY[1]-iyc};
double[][] input_bayer=splitBayer (imp,centerCross,equalizeGreens);
if (debug_level>3) SDFA_INSTANCE.showArrays(input_bayer, true, "centered");
if (debug_level>2) SDFA_INSTANCE.showArrays(input_bayer[4], "greens");
if (debug_level>2) System.out.println("ixc="+ixc+" iyc="+iyc);
if (debug_level > (debug_threshold +1)) SDFA_INSTANCE.showArrays(input_bayer, true, "centered");
if (debug_level > (debug_threshold +0)) SDFA_INSTANCE.showArrays(input_bayer[4], "greens");
if (debug_level > (debug_threshold +0)) System.out.println("ixc="+ixc+" iyc="+iyc);
double [] greens=normalizeAndWindow (input_bayer[4], thisWindow);
if (debug_level>2) SDFA_INSTANCE.showArrays(greens, "greensWindowed");
if (debug_level > (debug_threshold +0)) SDFA_INSTANCE.showArrays(greens, "greensWindowed");
// average is not zero - probably
if (debug_level>2) {
if (debug_level > (debug_threshold + 0)) {
System.out.println(" wv0x="+IJ.d2s(wv0x,5)+" wv0y="+IJ.d2s(wv0y,5));
System.out.println(" wv1x="+IJ.d2s(wv1x,5)+" wv1y="+IJ.d2s(wv1y,5));
System.out.println(" u-span="+IJ.d2s(u_span,3)+" v-span="+IJ.d2s(v_span,3)+" threshold="+IJ.d2s(uv_threshold,3)+" ("+IJ.d2s(distortionParameters.minUVSpan,3)+")");
......@@ -8611,12 +9244,12 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
}
int [][] greenNeib={{0,0},{0,1},{1,0},{1,1}};
int numOfNeib=distortionParameters.correlationAverageOnRefine?greenNeib.length:1;
if (debug_level>2) {
if (debug_level > (debug_threshold + 0)) {
System.out.println(" numOfNeib="+numOfNeib+" (distortionParameters.correlationAverageOnRefine="+distortionParameters.correlationAverageOnRefine);
}
if (locsNeib.length==1) {
numOfNeib=1; // on the first pass, from legacy
if (debug_level>2) {
if (debug_level > (debug_threshold + 0)) {
System.out.println("Reduced numOfNeib to "+numOfNeib+" as locsNeib.length="+locsNeib.length);
}
}
......@@ -8692,12 +9325,12 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
}
if (debug_level>2){
if (debug_level > (debug_threshold + 0)){
System.out.println(">=========Showing simGreensCentered"+ixc+":"+iyc);
SDFA_INSTANCE.showArrays(debugGreens, true, "simGreensCentered"+ixc+":"+iyc);
}
if (debug_level>2){
if (debug_level > (debug_threshold + 0)){
System.out.println(">=========Showing modelCorrs, passNumber="+passNumber);
SDFA_INSTANCE.showArrays(modelCorrs, true, "modelCorrs:"+numOfNeib);
}
......@@ -8722,14 +9355,14 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
} else {
modelCorr=modelCorrs[0]; // also - different size
}
if (debug_level>2){
if (debug_level > (debug_threshold + 0)){
System.out.println(">==========Showing modelCorr");
SDFA_INSTANCE.showArrays(modelCorr, thisCorrelationSize,thisCorrelationSize, "modelCorr");
}
if (fast) centerXY= correlationMaximum( // maybe twice actual size if
modelCorr,
distortionParameters.correlationMaxOffset,
(debug_level>2) && (numNeib==0)); // low-pass filtering should already be done
(debug_level > (debug_threshold + 0)) && (numNeib==0)); // low-pass filtering should already be done
else centerXY= correlationMaximum(modelCorr,
distortionParameters.correlationRadius,
distortionParameters.correlationThreshold, //double threshold, // fraction of maximum (slightly less than 1.0) to limit the top part of the maximum for centroid
......@@ -8740,9 +9373,9 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
distortionParameters.correlationMaxOffset,
thisLowpass, //distortionParameters.correlationLowPassSigma
// (debug_level>2) && (passNumber>1));
(debug_level>2));
(debug_level > (debug_threshold + 0)));
if (centerXY==null) {
if (debug_level>1) System.out.println("Too far from the center01 ("+beforeXY[0]+"/"+beforeXY[1]+")");
if (debug_level > (debug_threshold - 1)) System.out.println("Too far from the center01 ("+beforeXY[0]+"/"+beforeXY[1]+")");
if (dbgStr!=null) System.out.println(dbgStr+ "- Too far from the center01 ("+beforeXY[0]+"/"+beforeXY[1]+")");
return null;
}
......@@ -8787,8 +9420,8 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
contrast=contrasts[0];
result[2]=contrast;
if (Double.isNaN(contrasts[0]) || ((distortionParameters.correlationMinContrast>0) && (contrasts[0]<distortionParameters.correlationMinContrast))) {
if (debug_level>1) System.out.println("Contrast too low - "+contrasts[0]+"<"+distortionParameters.correlationMinContrast);
if (debug_level>1) System.out.println("Contrast "+IJ.d2s(contrasts[0],3)+" ("+distortionParameters.correlationMinContrast+")"+
if ((debug_level > (debug_threshold - 1))) System.out.println("Contrast too low - "+contrasts[0]+"<"+distortionParameters.correlationMinContrast);
if (debug_level > (debug_threshold - 1)) System.out.println("Contrast "+IJ.d2s(contrasts[0],3)+" ("+distortionParameters.correlationMinContrast+")"+
" is TOO LOW ("+IJ.d2s(beforeXY[0],3)+"/"+IJ.d2s(beforeXY[1],3)+")->"+
IJ.d2s(centerXY[0],3)+"/"+IJ.d2s(centerXY[1],3));
if (dbgStr!=null) System.out.println(dbgStr+ " - Contrast "+IJ.d2s(contrasts[0],3)+" ("+distortionParameters.correlationMinContrast+")"+
......@@ -8797,7 +9430,7 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
return null;
} else {
if (debug_level>1) System.out.println("Contrast "+IJ.d2s(contrasts[0],3)+" ("+distortionParameters.correlationMinContrast+")"+
if (debug_level > (debug_threshold - 1)) System.out.println("Contrast "+IJ.d2s(contrasts[0],3)+" ("+distortionParameters.correlationMinContrast+")"+
" is GOOD ("+IJ.d2s(beforeXY[0],3)+"/"+IJ.d2s(beforeXY[1],3)+")->"+
IJ.d2s(centerXY[0],3)+"/"+IJ.d2s(centerXY[1],3));
if (dbgStr!=null) System.out.println(dbgStr+ " - Contrast "+IJ.d2s(contrasts[0],3)+" ("+distortionParameters.correlationMinContrast+")"+
......@@ -8807,8 +9440,8 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
if (Double.isNaN(contrasts[1]) || ((distortionParameters.correlationMinAbsoluteContrast>0) && (contrasts[1]<distortionParameters.correlationMinAbsoluteContrast))) {
if (debug_level>1) System.out.println("Absolute contrast too low - "+contrasts[1]+"<"+distortionParameters.correlationMinAbsoluteContrast);
if (debug_level>1) System.out.println("Absolute contrast "+IJ.d2s(contrasts[1],3)+" ("+distortionParameters.correlationMinAbsoluteContrast+")"+
if (debug_level > (debug_threshold - 1)) System.out.println("Absolute contrast too low - "+contrasts[1]+"<"+distortionParameters.correlationMinAbsoluteContrast);
if (debug_level > (debug_threshold - 1)) System.out.println("Absolute contrast "+IJ.d2s(contrasts[1],3)+" ("+distortionParameters.correlationMinAbsoluteContrast+")"+
" is too low ("+IJ.d2s(beforeXY[0],3)+"/"+IJ.d2s(beforeXY[1],3)+")->"+
IJ.d2s(centerXY[0],3)+"/"+IJ.d2s(centerXY[1],3));
if (dbgStr!=null) System.out.println(dbgStr+ " - Absolute contrast "+IJ.d2s(contrasts[1],3)+" ("+distortionParameters.correlationMinAbsoluteContrast+")"+
......@@ -8821,20 +9454,25 @@ y=xy0[1] + dU*deltaUV[0]*(xy1[1]-xy0[1])+dV*deltaUV[1]*(xy2[1]-xy0[1])
IJ.d2s(centerXY[0],3)+"/"+IJ.d2s(centerXY[1],3));
}
if (debug_level>1) System.out.println(">>>Contrast="+contrasts[0]+"/"+contrasts[1]+" ("+IJ.d2s(beforeXY[0],3)+":"+IJ.d2s(beforeXY[1],3)+")->"+IJ.d2s(result[0],3)+":"+IJ.d2s(result[1],3));
if (debug_level > (debug_threshold - 1))System.out.println(">>>Contrast="+contrasts[0]+"/"+contrasts[1]+" ("+IJ.d2s(beforeXY[0],3)+":"+IJ.d2s(beforeXY[1],3)+")->"+IJ.d2s(result[0],3)+":"+IJ.d2s(result[1],3));
result[0]=ixc-(-centerXY[0]-centerXY[1])+diffBeforeXY[0];
result[1]=iyc-( centerXY[0]-centerXY[1])+diffBeforeXY[1];
if (debug_level>2) System.out.println(">---correctedPatternCrossLocation: before x="+IJ.d2s(beforeXY[0],3)+" y="+IJ.d2s(beforeXY[1],3));
if (debug_level>2) System.out.println(">+++correctedPatternCrossLocation: after x="+IJ.d2s(result[0],3)+" y="+IJ.d2s(result[1],3));
// if (debug_level>0) System.out.println(">---correctedPatternCrossLocation: before x="+IJ.d2s(beforeXY[0],3)+" y="+IJ.d2s(beforeXY[1],3));
// if (debug_level>0) System.out.println(">+++correctedPatternCrossLocation: after x="+IJ.d2s(result[0],3)+" y="+IJ.d2s(result[1],3));
if (debug_level > (debug_threshold + 0)) System.out.println(">---correctedPatternCrossLocation: before x="+IJ.d2s(beforeXY[0],3)+" y="+IJ.d2s(beforeXY[1],3));
if (debug_level > (debug_threshold + 0)) System.out.println(">+++correctedPatternCrossLocation: after x="+IJ.d2s(result[0],3)+" y="+IJ.d2s(result[1],3));
return result;
}
/* ======= Debugging only - returns 2-d array of x,y as a function of initial estimation =================== */
public double [][][] scanPatternCrossLocation(
double range, // size of the scanning square
......@@ -10130,9 +10768,20 @@ error=Sum(W(x,y)*(F^2 + 2*F*(A*x^2+B*y^2+C*x*y+D*x+E*y-Z(x,y)) +(...) )
public double minCorrContrast;
public double minGridPeriod;
public double maxGridPeriod;
public double minGridPeriodLwir;
public double maxGridPeriodLwir;
public double debugX;
public double debugY;
public double debugRadius;
// added for large cell findPattern (based on phase correlation)
public boolean use_large_cells = false; // new method based on phase correlation should work with large cells,
// so only first negative correlation (1/2 period) fits in window
public double phaseCoeff = 0.5; // "phasiness" of correlation
public double lowpass_sigma = .3; // for phase correlation - frequency fraction of maximal
public double min_frac = 0.03; // do not use higher order autocorrelation if min/max
// is weaker than this fraction of the zero maximum
public double min_sin = 0.5; // minimal sine for the angle between two pattern vectors
public boolean no_crazy = true; // fail if quadratic approximation fails or returns outside of +/- 1.5
public PatternDetectParameters(
......@@ -10149,9 +10798,17 @@ error=Sum(W(x,y)*(F^2 + 2*F*(A*x^2+B*y^2+C*x*y+D*x+E*y-Z(x,y)) +(...) )
double minCorrContrast,
double minGridPeriod,
double maxGridPeriod,
double minGridPeriodLwir,
double maxGridPeriodLwir,
double debugX,
double debugY,
double debugRadius
double debugRadius,
boolean use_large_cells,
double phaseCoeff,
double lowpass_sigma,
double min_frac,
double min_sin,
boolean no_crazy
) {
this.gaussWidth=gaussWidth;
this.corrGamma = corrGamma;
......@@ -10166,9 +10823,17 @@ error=Sum(W(x,y)*(F^2 + 2*F*(A*x^2+B*y^2+C*x*y+D*x+E*y-Z(x,y)) +(...) )
this.minCorrContrast = minCorrContrast;
this.minGridPeriod=minGridPeriod;
this.maxGridPeriod=maxGridPeriod;
this.minGridPeriodLwir=minGridPeriodLwir;
this.maxGridPeriodLwir=maxGridPeriodLwir;
this.debugX=debugX;
this.debugY=debugY;
this.debugRadius=debugRadius;
this.use_large_cells = use_large_cells;
this.phaseCoeff = phaseCoeff;
this.lowpass_sigma = lowpass_sigma;
this.min_frac = min_frac;
this.min_sin = min_sin;
this.no_crazy = no_crazy;
}
public void setProperties(String prefix,Properties properties){
......@@ -10185,9 +10850,18 @@ error=Sum(W(x,y)*(F^2 + 2*F*(A*x^2+B*y^2+C*x*y+D*x+E*y-Z(x,y)) +(...) )
properties.setProperty(prefix+"minCorrContrast",this.minCorrContrast+"");
properties.setProperty(prefix+"minGridPeriod",this.minGridPeriod+"");
properties.setProperty(prefix+"maxGridPeriod",this.maxGridPeriod+"");
properties.setProperty(prefix+"minGridPeriodLwir",this.minGridPeriodLwir+"");
properties.setProperty(prefix+"maxGridPeriodLwir",this.maxGridPeriodLwir+"");
properties.setProperty(prefix+"debugX",this.debugX+"");
properties.setProperty(prefix+"debugY",this.debugY+"");
properties.setProperty(prefix+"debugRadius",this.debugRadius+"");
properties.setProperty(prefix+"use_large_cells",this.use_large_cells+"");
properties.setProperty(prefix+"phaseCoeff", this.phaseCoeff+"");
properties.setProperty(prefix+"lowpass_sigma", this.lowpass_sigma+"");
properties.setProperty(prefix+"min_frac", this.min_frac+"");
properties.setProperty(prefix+"min_sin", this.min_sin+"");
properties.setProperty(prefix+"no_crazy", this.no_crazy+"");
}
public void getProperties(String prefix,Properties properties){
......@@ -10208,14 +10882,29 @@ error=Sum(W(x,y)*(F^2 + 2*F*(A*x^2+B*y^2+C*x*y+D*x+E*y-Z(x,y)) +(...) )
if (properties.getProperty(prefix+"maxGridPeriod")!=null)
this.minGridPeriod=Double.parseDouble(properties.getProperty(prefix+"maxGridPeriod"));
else this.maxGridPeriod=0.0;
if (properties.getProperty(prefix+"minGridPeriodLwir")!=null)
this.minGridPeriodLwir=Double.parseDouble(properties.getProperty(prefix+"minGridPeriodLwir"));
else this.minGridPeriodLwir=0.0;
if (properties.getProperty(prefix+"maxGridPeriodLwir")!=null)
this.minGridPeriodLwir=Double.parseDouble(properties.getProperty(prefix+"maxGridPeriodLwir"));
else this.maxGridPeriodLwir=0.0;
if (properties.getProperty(prefix+"debugX")!=null)
this.debugX=Double.parseDouble(properties.getProperty(prefix+"debugX"));
if (properties.getProperty(prefix+"debugY")!=null)
this.debugY=Double.parseDouble(properties.getProperty(prefix+"debugY"));
if (properties.getProperty(prefix+"debugRadius")!=null)
this.debugRadius=Double.parseDouble(properties.getProperty(prefix+"debugRadius"));
}
if (properties.getProperty(prefix+"use_large_cells")!=null) this.use_large_cells=Boolean.parseBoolean(properties.getProperty(prefix+"use_large_cells"));
if (properties.getProperty(prefix+"phaseCoeff")!=null) this.phaseCoeff=Double.parseDouble(properties.getProperty(prefix+"phaseCoeff"));
if (properties.getProperty(prefix+"lowpass_sigma")!=null) this.lowpass_sigma=Double.parseDouble(properties.getProperty(prefix+"lowpass_sigma"));
if (properties.getProperty(prefix+"min_frac")!=null) this.min_frac=Double.parseDouble(properties.getProperty(prefix+"min_frac"));
if (properties.getProperty(prefix+"min_sin")!=null) this.min_sin=Double.parseDouble(properties.getProperty(prefix+"min_sin"));
if (properties.getProperty(prefix+"no_crazy")!=null) this.no_crazy=Boolean.parseBoolean(properties.getProperty(prefix+"no_crazy"));
}
}
/* ======================================================================== */
......@@ -10414,6 +11103,7 @@ error=Sum(W(x,y)*(F^2 + 2*F*(A*x^2+B*y^2+C*x*y+D*x+E*y-Z(x,y)) +(...) )
this.legacyMode=legacyMode;
}
@Override
public DistortionParameters clone() {
return new DistortionParameters(
this.correlationSize,
......@@ -11134,6 +11824,7 @@ error=Sum(W(x,y)*(F^2 + 2*F*(A*x^2+B*y^2+C*x*y+D*x+E*y-Z(x,y)) +(...) )
public int getNumberOfPointers(){
return this.laserUVMap.length;
}
@Override
public LaserPointer clone(){
return new LaserPointer(
this.headLasersTilt,// degrees, right laser lower than left laser
......
......@@ -124,15 +124,7 @@ public class DoubleFHT {
public boolean transform(double [] data, boolean inverse) {
//IJ.log("transform: "+maxN+" "+inverse);
updateMaxN(data);
// maxN = (int) Math.sqrt(data.length);
// if ((S==null) || (S.length!=(maxN/4))) {
// makeSinCosTables(maxN);
// makeBitReverseTable(maxN);
// tempArr = new double[maxN];
// }
// float[] fht = (float[])getPixels();
rc2DFHT(data, inverse, this.maxN);
// isFrequencyDomain = !inverse;
return true;
}
......@@ -141,13 +133,7 @@ public class DoubleFHT {
double lowPass){
return createFrequencyFilter(null,highPass,lowPass);
}
/* public double []createFrequencyFilter(
double [] data,
double highPass,
double lowPass){
return createFrequencyFilter(data.length,highPass,lowPass);
}
*/
public double [] createFrequencyFilter(
double [] data, //int n,
double highPass,
......@@ -155,7 +141,7 @@ public class DoubleFHT {
if (data !=null) updateMaxN(data);
// int n;
if ((this.freqMask!=null) && (this.freqPass[0]==highPass) && (this.freqPass[0]==lowPass)) return this.freqMask;
if ((this.freqMask!=null) && (this.freqPass[0]==highPass) && (this.freqPass[1]==lowPass)) return this.freqMask;
this.freqMask= new double [(this.maxN+1)*this.maxN/2+1];
double [] lo=new double[this.maxN];
double [] hi=new double[this.maxN];
......@@ -177,12 +163,9 @@ public class DoubleFHT {
if (j>this.maxN/2) j=this.maxN-j;
this.freqMask[index]=(1.0-hi[i]*hi[j])*lo[i]*lo[j];
}
// this.freqMaskN=n;
this.freqPass=new double[2];
this.freqPass[0]=highPass;
this.freqPass[1]=lowPass;
// this.freqMask_cache[this.ln2]=this.freqMask;
// this.freqPass_cache[this.ln2]=this.freqPass;
return this.freqMask;
}
/**
......@@ -195,49 +178,6 @@ public class DoubleFHT {
*/
public double [] shift(double [] data, double dx, double dy){
return shift(data, 1, dx, dy);
/*
updateMaxN(data);
double sX=2*Math.PI*dx/this.maxN;
double sY=2*Math.PI*dy/this.maxN;
int halfN=this.maxN/2;
double [] cosDX = new double[this.maxN];
double [] sinDX = new double[this.maxN];
double [] cosDY = new double[halfN+1];
double [] sinDY = new double[halfN+1];
for (int i=0;i<=halfN;i++){ // need less?
cosDX[i]=Math.cos(sX*i);
sinDX[i]=Math.sin(sX*i);
cosDY[i]=Math.cos(sY*i);
sinDY[i]=Math.sin(sY*i);
}
for (int i=1;i<halfN;i++){ // need less?
cosDX[this.maxN-i]= cosDX[i];
sinDX[this.maxN-i]=-sinDX[i];
}
swapQuadrants(data);
if (!transform(data,false)) return null; // direct FHT
for (int row =0; row<=halfN; row++) {
int rowMod = (this.maxN - row) % this.maxN;
int maxCol=(row<halfN)?(this.maxN-1):halfN;
for (int col=0; col<=maxCol; col++) {
int colMod = (this.maxN - col) % this.maxN;
int index= row * this.maxN + col;
int indexMod=rowMod * this.maxN + colMod;
double re=0.5*(data[index]+data[indexMod]);
double im=0.5*(data[index]-data[indexMod]);
if ((col==halfN) || (row==halfN)) im=0;
double cosDelta= cosDX[col]*cosDY[row] - sinDX[col]*sinDY[row]; // cos(deltaX)*cos(deltaY)-sin(deltaX)*sin(deltaY)
double sinDelta= sinDX[col]*cosDY[row] + cosDX[col]*sinDY[row]; // sin(deltaX)*cos(deltaY)+cos(deltaX)*sin(deltaY)
double reMod=re*cosDelta-im*sinDelta;
double imMod=re*sinDelta+im*cosDelta;
data[index]= reMod+imMod;
data[indexMod]=reMod-imMod;
}
}
if (!transform(data,true)) return null; // inverse FHT
swapQuadrants(data);
return data;
*/
}
/**
* Upsample input array by padding in the frequency domain
......@@ -247,30 +187,6 @@ public class DoubleFHT {
*/
public double [] upsample( double [] first, int scale){
return shift (first, scale, 0.0, 0.0);
/*
if (scale <=1) return first.clone();
updateMaxN(first);
swapQuadrants(first);
if (!transform(first,false)) return null; // direct FHT
int halfN=this.maxN/2;
int shift=this.maxN*(scale-1);
int scaledN=this.maxN*scale;
double [] result =new double [first.length*scale*scale];
for (int i=0;i<result.length;i++) result [i]=0.0;
double scale2=scale*scale;
for (int i=0;i<first.length;i++){
int iy=i/this.maxN;
int ix=i%this.maxN;
if (ix>halfN) ix+=shift;
if (iy>halfN) iy+=shift;
result[scaledN*iy+ix]=scale2*first[i];
}
updateMaxN(result);
if (!transform(result,true)) return null; // inverse FHT
swapQuadrants(result);
return result;
*/
}
/**
......@@ -408,6 +324,54 @@ public class DoubleFHT {
swapQuadrants(first);
return first;
}
public double [] phaseCorrelate (
double [] first,
double phaseCoeff,
double high_pass,
double low_pass) { // high/low pass filtering
return phaseCorrelate(first, phaseCoeff, high_pass, low_pass, null);
}
public double [] phaseCorrelate (
double [] first,
double phaseCoeff,
double high_pass,
double low_pass, // high/low pass filtering
double [] fht_save){ //null-OK
updateMaxN(first);
double [] filter = null;
if ((high_pass >0) || (low_pass > 0)) {
filter = createFrequencyFilter(high_pass, low_pass);
}
return phaseCorrelate(first, phaseCoeff, filter,fht_save);
}
public double [] phaseCorrelate (
double [] first,
double phaseCoeff,
double [] filter) { // high/low pass filtering
return phaseCorrelate(first, phaseCoeff, filter, null);
}
public double [] phaseCorrelate (
double [] first,
double phaseCoeff,
double [] filter, // high/low pass filtering
double [] fht_save){ //null-OK
updateMaxN(first);
swapQuadrants(first);
if (!transform(first,false)) return null; // direct FHT
if (fht_save != null) {
System.arraycopy(first, 0, fht_save, 0, first.length);
}
first= phaseMultiplyNorm(first, first, phaseCoeff); // correlation, not convolution
if (filter!=null) multiplyByReal(first, filter);
transform(first,true) ; // inverse transform
swapQuadrants(first);
return first;
}
//
public double [] applyFreqFilter(
double [] first,
double [] filter
......@@ -2024,6 +1988,7 @@ public class DoubleFHT {
return product;
}
public double [] phaseMultiply(double [] h1, double [] h2, double phaseCoeff) {
int rowMod, colMod;
double h2e, h2o,d;
......@@ -2041,6 +2006,54 @@ public class DoubleFHT {
return product;
}
public double [] phaseMultiplyNorm(double [] h1, double [] h2, double phaseCoeff) {
int size = maxN;
int size2 = size >> 1;
int size21 = size*size2;
int rowMod, colMod, base, baseMod;
double h2e, h2o;
double[] product = new double[size*size];
for (int r =0; r<size; r++) {
rowMod = (size - r) % size;
for (int c=0; c<size; c++) {
colMod = (size - c) % size;
h2e = (h2[r * size + c] + h2[rowMod * size + colMod]) / 2;
h2o = (h2[r * size + c] - h2[rowMod * size + colMod]) / 2;
product[r * size + c] = (h1[r * size + c] * h2e - h1[rowMod * size + colMod] * h2o);
}
}
double [] amplitude = calculateAmplitudeHalf(product);
double avg_ampl = 0.0;
for (int row = 1; row < size2; row++) {
base = row*size;
for (int col = 0; col < size; col++) {
avg_ampl += amplitude[col+base];
}
}
avg_ampl *= 2;
for (int col = 0; col < size; col++) {
avg_ampl += amplitude[col] + amplitude[col + size21];
}
avg_ampl /= size*size;
double aoffs = (1.0 - phaseCoeff) * avg_ampl;
double ampl;
for (int row = 0; row <= size2; row++) {
base = row*size;
rowMod = (size - row) % size;
baseMod = rowMod * size;
for (int col = 0; col < size; col++) {
ampl = phaseCoeff * amplitude[col+base] + aoffs;
product[col+base] /= ampl;
if ((row > 0) && (row < size2)) {
colMod = (size - col) % size;
product[colMod + baseMod] /= ampl;
}
}
}
return product;
}
// Multiply by real array (i.e. filtering in frequency domain). Array m length should be at least maxN*maxN/2+1
public void multiplyByReal(double [] h, double [] m) {
......@@ -2094,6 +2107,17 @@ public class DoubleFHT {
swapQuadrants(amp);
return amp;
}
public double [] calculateAmplitudeHalf(double [] fht) {
int size=(int) Math.sqrt(fht.length);
int size2 = (size >>1) +1;
double[] amp = new double[size* size2];
for (int row=0; row<size2; row++) {
amplitude(row, size, fht, amp);
}
return amp;
}
public double [] calculateAmplitude2(double [] fht) {
int size=(int) Math.sqrt(fht.length);
double[] amp = new double[size*size];
......@@ -2133,8 +2157,6 @@ public class DoubleFHT {
row2=(fftsize-row1) %fftsize;
for (col1=0;col1<fftsize;col1++) {
col2=(fftsize-col1) %fftsize;
// fftHalf[row1][col1]= complex( 0.5*(fht_pixels[row1*fftsize+col1] + fht_pixels[row2*fftsize+col2]),
// 0.5*(fht_pixels[row2*fftsize+col2] - fht_pixels[row1*fftsize+col1]));
fftHalf[row1][col1][0]= 0.5*(fht_pixels[row1*fftsize+col1] + fht_pixels[row2*fftsize+col2]);
fftHalf[row1][col1][1]= 0.5*(fht_pixels[row2*fftsize+col2] - fht_pixels[row1*fftsize+col1]);
}
......
......@@ -112,6 +112,30 @@ import ij.process.ImageProcessor;
return;
} else showArrays(pixels, width, height, titles);
}
public void showComplex(double[][][] cpixels, String title) {
int height = cpixels.length;
int width = cpixels[0].length;
double [][]pixels = new double [height*width][];
int indx = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
pixels[indx++] = cpixels[y][x];
}
}
showComplex(pixels, width, title);
}
public void showComplex(double[][] cpixels, int width, String title) {
int height = cpixels.length/width;
double [][]pixels = new double [2][cpixels.length];
for (int i = 0; i< cpixels.length; i++) {
pixels[0][i]= cpixels[i][0];
pixels[1][i]= cpixels[i][1];
}
String [] titles = {"Re", "Im"};
showArrays(pixels, width, height, true, title, titles);
}
public void showArrays(float[][] pixels, int width, int height, boolean asStack, String title, String [] titles) {
int i,j;
......
......@@ -1407,7 +1407,12 @@ Exception in thread "Thread-3564" java.lang.ArrayIndexOutOfBoundsException: 8970
NodeList allNodes=doc.getDocumentElement().getElementsByTagName("*");
for (int i=0;i<allNodes.getLength();i++) {
String name= allNodes.item(i).getNodeName();
String value=allNodes.item(i).getFirstChild().getNodeValue();
String value="";
try {
value=allNodes.item(i).getFirstChild().getNodeValue();
} catch(Exception e) {
}
imp.setProperty(name, value);
}
......
......@@ -26,10 +26,14 @@
*/
package com.elphel.imagej.lwir;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Properties;
import com.elphel.imagej.common.GenericJTabbedDialog;
import ij.Prefs;
public class LwirReaderParameters {
private boolean parameters_updated = false;
protected int avg_number = 4; // number of measurements to average
......@@ -49,6 +53,7 @@ public class LwirReaderParameters {
protected double vnir_gain_g = 2.0;
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 double [] vnir_exp_corr = {1.0, 1.0, 1.0, 1.0};
......@@ -106,6 +111,7 @@ public class LwirReaderParameters {
properties.setProperty(prefix+"max_mismatch_ms", this.max_mismatch_ms+"");
properties.setProperty(prefix+"max_frame_diff", this.max_frame_diff+"");
properties.setProperty(prefix+"debug_level", this.debug_level+"");
properties.setProperty(prefix+"selected_channels", arr_to_str(this.selected_channels));
}
......@@ -134,6 +140,7 @@ public class LwirReaderParameters {
if (properties.getProperty(prefix+"max_mismatch_ms")!=null) this.max_mismatch_ms=Double.parseDouble(properties.getProperty(prefix+"max_mismatch_ms"));
if (properties.getProperty(prefix+"max_frame_diff")!=null) this.max_frame_diff=Integer.parseInt(properties.getProperty(prefix+"max_frame_diff"));
if (properties.getProperty(prefix+"debug_level")!=null) this.debug_level=Integer.parseInt(properties.getProperty(prefix+"debug_level"));
if (properties.getProperty(prefix+"selected_channels")!=null) this.selected_channels=str_to_barr(properties.getProperty(prefix+"selected_channels"));
parameters_updated = true;
}
@Override
......@@ -163,6 +170,7 @@ public class LwirReaderParameters {
lrp.max_mismatch_ms= this.max_mismatch_ms;
lrp.max_frame_diff= this.max_frame_diff;
lrp.debug_level= this.debug_level;
lrp.selected_channels = this.selected_channels.clone();
return lrp;
}
......@@ -198,7 +206,8 @@ public class LwirReaderParameters {
(lrp.vnir_lag == this.vnir_lag) &&
(lrp.max_mismatch_ms == this.max_mismatch_ms) &&
(lrp.max_frame_diff == this.max_frame_diff) &&
(lrp.debug_level == this.debug_level);
(lrp.debug_level == this.debug_level) &&
(java.util.Arrays.equals(lrp.selected_channels, this.selected_channels));
}
@Override
......@@ -225,6 +234,7 @@ public class LwirReaderParameters {
result = prime * result + arr_to_str(vnir_exp_corr).hashCode();
result = prime * result + arr_to_str(vnir_gcorr_rbgb).hashCode();
result = prime * result + (new Integer(lwir_trig_dly)).hashCode();
result = prime * result + arr_to_str(selected_channels).hashCode();
// next are not needed to be programmed to the cameras
// result = prime * result + (new Integer(vnir_lag)).hashCode();
// result = prime * result + (new Double(max_mismatch_ms)).hashCode();
......@@ -241,7 +251,7 @@ public class LwirReaderParameters {
gd.addStringField ("LWIR channels", arr_to_str(this.lwir_channels), 20, "Space-separated list of used LWIR camera channels, such as '0 1 2 3'");
gd.addStringField ("VNIR channels", arr_to_str(this.vnir_channels), 20, "Space-separated list of used visible range camera channels, such as '0 1 2 3'");
gd.addCheckbox ("LWIR telemetry", this.lwir_telemetry, "Set LWIR sesnors to provide telemetry data in the last 2 lines (may become mandatory later)");
gd.addNumericField("VNIR quality", this.vnir_quality, 3,6,"ms", "Visible range camera JPEG compression quality (all channels)");
gd.addNumericField("VNIR quality", this.vnir_quality, 3,6,"%", "Visible range camera JPEG compression quality (all channels)");
gd.addCheckbox ("VNIR undo white balance", this.vnir_scale, "Undo in-camera white balancing");
gd.addCheckbox ("VNIR autoexposure", this.vnir_autoexp, "Enable autoexposure for the visible range camera");
gd.addNumericField("VNIR vnir_max_autoexp_ms", this.vnir_max_autoexp_ms, 3,6,"ms", "Visible range camera maximal exposure in autoexposure mode");
......@@ -257,6 +267,7 @@ public class LwirReaderParameters {
gd.addNumericField("Max mismatch", this.max_mismatch_ms, 3,6,"ms","Maximal mismatch between image timestamps. Larger mismatch requires LWIR sinsor reinitialization");
gd.addNumericField("Max frame diff",this.max_frame_diff, 0,3,"","Maximal difference in frames between simultaneously acquired channels as calculated from the timestamps");
gd.addNumericField("Debug level", this.debug_level, 0,3,"","Image acquisition log level: -3: OFF, -2:FATAL, -1:ERROR, 0:WARN, 1:INFO, 2:DEBUG");
gd.addStringField ("Selected channels", arr_to_str(this.selected_channels), 20, "Space-separated channel selection (1 - selected, 0 - unselected)");
}
public void dialogAnswers(GenericJTabbedDialog gd) {
......@@ -284,6 +295,7 @@ public class LwirReaderParameters {
this.max_mismatch_ms = gd.getNextNumber();
this.max_frame_diff = (int) gd.getNextNumber();
this.debug_level = (int) gd.getNextNumber();
this.selected_channels = str_to_barr(gd.getNextString());
parameters_updated = true;
}
......@@ -307,6 +319,80 @@ public class LwirReaderParameters {
parameters_updated = false;
}
public boolean [] getSelected(){
return selected_channels;
}
public boolean [] getSelectedLwir(){
boolean [] sel = selected_channels.clone();
for (int i = lwir_channels.length; i < sel.length; i++ ) {
sel[i] = false;
}
return sel;
}
public boolean [] getSelectedVnir(){
boolean [] sel = selected_channels.clone();
for (int i = 0; i < lwir_channels.length; i++ ) {
sel[i] = false;
}
return sel;
}
public String [] getSourceFilesFlat(String [] sets, boolean[] channels) {
int num_sel = 0;
for (boolean s: channels) if (s) num_sel++;
String [] files = new String [sets.length * num_sel];
int indx = 0;
for (String set:sets) {
for (int i = 0; i < channels.length; i++) if (channels[i]) {
String file_base = set;
if (set.indexOf(Prefs.getFileSeparator()) >=0) {
file_base = set.substring(set.lastIndexOf(Prefs.getFileSeparator())+1);
}
files[indx++] =set + Prefs.getFileSeparator()+ file_base+"_"+i+".tiff";
}
}
return files;
}
// Image set may have different timestamps, only lwir0 matches
public String [][] getSourceFiles(String [] sets, boolean[] channels) {
String [][] files = new String [sets.length][channels.length];
for (int nset= 0; nset < sets.length; nset++) {
// read all files in the directory
File set_dir = new File(sets[nset]);
File [] channel_files = set_dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File current, String name) {
if (!(new File(current, name).isFile()) || !name.endsWith(".tiff")) return false;
String base = name.substring(0, name.lastIndexOf(".tiff"));
int undr = base.lastIndexOf("_");
if (undr < 0) return false;
int chn = -1;
try {
chn = Integer.parseInt(base.substring(undr + 1));
} catch (Exception e) {
}
return chn >= 0;
}
});
for (File f: channel_files) {
String base = f.getName().substring(0, f.getName().lastIndexOf(".tiff"));
int undr = base.lastIndexOf("_");
int chn = Integer.parseInt(base.substring(undr + 1));
if ((chn >= 0) && (chn < channels.length) && channels[chn]) {
files[nset][chn] = f.getPath();
}
}
}
return files;
}
// --- internal methods
private String arr_to_str(int [] arr) {
......@@ -321,6 +407,23 @@ public class LwirReaderParameters {
return s.trim();
}
private String arr_to_str(boolean [] arr) {
String s = "";
for (boolean c:arr) s+= (c?1:0)+" ";
return s.trim();
}
private boolean [] str_to_barr(String s) {
int [] iarr = str_to_iarr(s);
if (iarr == null) return null;
boolean [] barr = new boolean [iarr.length];
for (int i = 0; i < barr.length; i++) {
barr[i] = iarr[i] != 0;
}
return barr;
}
private int [] str_to_iarr(String s) {
String [] sa;
if (s.indexOf(",") >= 0) {
......@@ -349,4 +452,22 @@ public class LwirReaderParameters {
return darr;
}
public boolean [] selectSourceChannels(){
return selectSourceChannels(selected_channels);
}
public boolean [] selectSourceChannels(boolean [] sel) {
GenericJTabbedDialog gd = new GenericJTabbedDialog("Set CLT parameters",300,500);
for (int i = 0; i < sel.length; i++) {
gd.addCheckbox ("Channel "+i, sel[i], "Enable processing camera channel "+i);
}
gd.showDialog();
if (gd.wasCanceled()) return null;
for (int i = 0; i < sel.length; i++) {
sel[i] = gd.getNextBoolean();
}
return sel;
}
}
......@@ -640,7 +640,7 @@ the type of pixel data in this file getPixelType()
}
// copied from JP46_Reader_camera.java
public ImagePlus encodeProperiesToInfo(ImagePlus imp){
public static ImagePlus encodeProperiesToInfo(ImagePlus imp){
String info="<?xml version=\"1.0\" encoding=\"UTF-8\"?><properties>";
Set<Object> jp4_set;
Properties jp4_prop;
......@@ -661,7 +661,7 @@ the type of pixel data in this file getPixelType()
return imp;
}
public boolean decodeProperiesFromInfo(ImagePlus imp){
public static boolean decodeProperiesFromInfo(ImagePlus imp){
if (imp.getProperty("Info")==null) return false;
String xml= (String) imp.getProperty("Info");
......@@ -684,11 +684,15 @@ the type of pixel data in this file getPixelType()
NodeList allNodes=doc.getDocumentElement().getElementsByTagName("*");
for (int i=0;i<allNodes.getLength();i++) {
String name= allNodes.item(i).getNodeName();
String value=allNodes.item(i).getFirstChild().getNodeValue();
// System.out.print(name+" -> ");
String value = "";
try {
value=allNodes.item(i).getFirstChild().getNodeValue();
} catch (Exception e) {
}
// System.out.println(value);
imp.setProperty(name, value);
}
return true;
}
......
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