Commit 3f9c52b0 authored by Andrey Filippov's avatar Andrey Filippov

merged with lwir

parents 13959a97 047fdb5e
......@@ -55,6 +55,8 @@ import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.elphel.imagej.readers.ImagejJp4Tiff;
import ij.IJ;
import ij.ImageJ;
import ij.ImagePlus;
......@@ -69,6 +71,7 @@ import ij.plugin.frame.PlugInFrame;
import ij.process.ImageConverter;
import ij.process.ImageProcessor;
import ij.text.TextWindow;
import loci.formats.FormatException;
......@@ -87,6 +90,8 @@ public class JP46_Reader_camera0 extends PlugInFrame implements ActionListener {
static File dir;
ImagejJp4Tiff imagejJp4Tiff = new ImagejJp4Tiff();
public String camera_url = "http://192.168.0.236:8081/";
public String camera_img = "bimg";
public String camera_img_new = "towp/wait/bimg"; // will always wait for the next image (repetitive acquisitions get new images)
......@@ -109,8 +114,9 @@ public class JP46_Reader_camera0 extends PlugInFrame implements ActionListener {
panel1 = new Panel();
panel1.setLayout(new GridLayout(6, 1, 50, 5));
panel1.setLayout(new GridLayout(8, 1, 50, 5));
addButton("Open JP4/Tiff...",panel1);
addButton("Open JP4/JP46...",panel1);
addButton("Open JP4/JP46 from camera",panel1);
addButton("Configure...",panel1);
......@@ -137,8 +143,8 @@ public class JP46_Reader_camera0 extends PlugInFrame implements ActionListener {
panel1 = new Panel();
panel1.setLayout(new GridLayout(6, 1, 50, 5));
panel1.setLayout(new GridLayout(8, 1, 50, 5));
addButton("Open JP4/Tiff...",panel1);
addButton("Open JP4/JP46...",panel1);
addButton("Open JP4/JP46 from camera",panel1);
addButton("Configure...",panel1);
......@@ -169,7 +175,11 @@ public class JP46_Reader_camera0 extends PlugInFrame implements ActionListener {
if (label==null) return;
/* button */
if (label.equals("Open JP4/JP46...")) {
if (label.equals("Open JP4/Tiff...")) {
read_jp4Tiff(arg,true);
}else if (label.equals("Open JP4/Tiff (no scale)...")) {
read_jp4Tiff(arg,false);
}else if (label.equals("Open JP4/JP46...")) {
read_jp46(arg,true);
}else if (label.equals("Open JP4/JP46 (no scale)...")) {
read_jp46(arg,false);
......@@ -227,7 +237,54 @@ public class JP46_Reader_camera0 extends PlugInFrame implements ActionListener {
imp_stack.getProcessor().resetMinAndMax();
imp_stack.show();
}
public void read_jp4Tiff(String arg, // not used?
boolean scale) {
String LOG_LEVEL = ABSOLUTELY_SILENT? "OFF" : (IS_SILENT?"ERROR":"INFO");
boolean LOG_LEVEL_SET = loci.common.DebugTools.enableLogging(LOG_LEVEL);
if (!LOG_LEVEL_SET) { // only first time true
loci.common.DebugTools.setRootLevel(LOG_LEVEL);
}
JFileChooser fc=null;
//try {fc = new JFileChooser();}
fc = new JFileChooser();
//catch (Throwable e) {IJ.error("This plugin requires Java 2 or Swing."); return;}
fc.setMultiSelectionEnabled(true);
if (dir==null) {
String sdir = OpenDialog.getDefaultDirectory();
if (sdir!=null)
dir = new File(sdir);
}
if (dir!=null)
fc.setCurrentDirectory(dir);
int returnVal = fc.showOpenDialog(IJ.getInstance());
if (returnVal!=JFileChooser.APPROVE_OPTION)
return;
File[] files = fc.getSelectedFiles();
if (files.length==0) { // getSelectedFiles does not work on some JVMs
files = new File[1];
files[0] = fc.getSelectedFile();
}
String path = fc.getCurrentDirectory().getPath()+Prefs.getFileSeparator();
dir = fc.getCurrentDirectory();
for (int i=0; i<files.length; i++) {
try {
ImagePlus imp = imagejJp4Tiff.readTiffJp4(path + files[i].getName(), scale);
// imp.updateAndDraw();
imp.show();
} catch (IOException | FormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // throws IOException, FormatException { // std - include non-elphel properties with prefix std
// open(path, files[i].getName(), arg, scale);
}
}
public void read_jp46(String arg, boolean scale) {
JFileChooser fc=null;
//try {fc = new JFileChooser();}
......@@ -274,6 +331,7 @@ public class JP46_Reader_camera0 extends PlugInFrame implements ActionListener {
confpanel = new Panel();
gd.addPanel(confpanel);
addButton("Open JP4/Tiff (no scale)...", confpanel);
addButton("Open JP4/JP46 (no scale)...", confpanel);
addButton("Open JP4/JP46 from camera (no scale)", confpanel);
......@@ -1413,9 +1471,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
);
......@@ -350,12 +361,15 @@ public class Aberration_Calibration extends PlugInFrame implements ActionListene
public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSimulatedPattern.DistortionParameters(
64, //32, // use 64 for less artifacts, // correlationSize
64, // Maximal correlation size
16, // int correlationSizeLwir,
128, // 64, // Maximal correlation size
16, // int maximalCorrelationSizeLwir,
0.75,// reduce to 0.5 when correlationSize==64 // correlationGaussWidth
false, // boolean absoluteCorrelationGaussWidth=false; // do not scale correlationGaussWidth when the FFT size is increased
0, //zeros - // leave this number of zeros on the margins of the window (toatal from both sides). If correlationGaussWidth>0 will
// additionally multiply by Hamming
128, // FFT size
256, // FFTSize (was 128)
32, // FFTSize_lwir
0.5, //fftGaussWidth
0.0, //phaseCorrelationFraction
1.5, // 2.5, //6.0, // 2.0, // 0.0, // correlationHighPassSigma, - pixels in frequency domain
......@@ -364,15 +378,18 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
8.0, // 3.0, // correlationMaxOffset, // maximal distance between predicted and actual pattern node
3.0, // 2.0, // increase back to .5? was needed with fisheye. 5.0, // double correlationMinContrast, // minimal contrast for the pattern to pass
3.5, // 2.5, // correlationMinInitialContrast, // minimal contrast for the pattern of the center (initial point)
1.0, //this.correlationMinAbsoluteContrast, // minimal contrast for the pattern to pass, does not compensate for low ligt
// Absolute contrast is broken (05.29.2019), disabling it
0.0, // 1.0, //this.correlationMinAbsoluteContrast, // minimal contrast for the pattern to pass, does not compensate for low ligt
// TODO: adjust to a reasonable number
1.0, //this.correlationMinAbsoluteInitialContrast, // minimal contrast for the pattern of the center (initial point)
0.0, // 1.0, //this.correlationMinAbsoluteInitialContrast, // minimal contrast for the pattern of the center (initial point)
0.8, // scaleFirstPassContrast, // Decrease contrast of cells that are too close to the border to be processed in refinement pass
2.0, // public double contrastSelectSigmaCenter; // Gaussian sigma to select correlation centers (fraction of UV period), 0.02 (center spot)
0.1, // contrastSelectSigma, // Gaussian sigma to select correlation centers (fraction of UV period), 0.1
0.5, //contrastAverageSigma, // Gaussian sigma to average correlation variations (as contrast reference) 0.5
150, // minimalPatternCluster minimal pattern cluster size (0 - disable retries)
40, // 150, // minimalPatternCluster minimal pattern cluster size (0 - disable retries)
10, // 150, // minimalPatternClusterLwir minimal pattern cluster size (0 - disable retries)
2.0, // scaleMinimalInitialContrast increase/decrease minimal contrast if initial cluster is >0 but less than minimalPatternCluster
0.5, // when searching for grid, step this amount of the FFTSize
4, // public int patternSubdiv;
......@@ -674,11 +691,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 +1011,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 +1160,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")) {
......@@ -1402,6 +1421,7 @@ if (MORE_BUTTONS) {
// matchSimulatedPattern.invalidateFlatFieldForGrid(); //It is already reset, no need to do it again
// matchSimulatedPattern.invalidateFocusMask();
matchSimulatedPattern.calculateDistortions(
null, // LwirReaderParameters lwirReaderParameters,
DISTORTION, //
PATTERN_DETECT,
SIMUL,
......@@ -1798,6 +1818,7 @@ if (MORE_BUTTONS) {
// matchSimulatedPattern.invalidateFlatFieldForGrid(); //It is already reset, no need to do it again
// matchSimulatedPattern.invalidateFocusMask();
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
null, // LwirReaderParameters lwirReaderParameters,
DISTORTION, //
PATTERN_DETECT,
SIMUL,
......@@ -2567,113 +2588,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;
}
/* ======================================================================== */
......@@ -9501,6 +9416,11 @@ if (MORE_BUTTONS) {
/// POWER_CONTROL.lightsOff();
return;
}
/* ======================================================================== */
if (label.equals("LWIR grids")) {
calculateLwirGrids();
return;
}
......@@ -9517,7 +9437,254 @@ 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
boolean [] sel_chn = LWIR_PARAMETERS.getSelected();
int numFiles = LWIR_PARAMETERS.getSourceFilesFlat(sourceSetList, sel_chn).length; // just the number
String [][] sourceFilesList=LWIR_PARAMETERS.getSourceFiles(sourceSetList, sel_chn);
boolean saveGrids=DISTORTION_PROCESS_CONFIGURATION.saveGridImages;
boolean overwriteGrids=DISTORTION_PROCESS_CONFIGURATION.overwriteResultFiles;
if (sourceSetList==null) return;
showPatternMinMaxPeriodDialog(PATTERN_DETECT, true);
int saved_file = 0;
int in_file = 0;
String gridDir=DISTORTION_PROCESS_CONFIGURATION.selectGridFileDirectory(
true,DISTORTION_PROCESS_CONFIGURATION.gridDirectory,true);
if (gridDir == null) saveGrids=false; // do not ask about the next ones too
for (int nset = 0; nset < sourceFilesList.length; nset++){
String set_name = sourceSetList[nset];
int i = set_name.lastIndexOf(Prefs.getFileSeparator());
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){
in_file++;
long startFileTime=System.nanoTime();
if (DEBUG_LEVEL>0){
System.out.println(IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+"s: Processing set "+(nset+1) +" (of "+
sourceFilesList.length+"), channel # "+(nfile + 1)+
" (of "+ sourceFilesList[nset].length+"), file "+in_file+" (of "+ numFiles+ ") success in "+saved_file+" - "+sourceFilesList[nset][nfile]);
}
String grid_path = null;
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);
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();
boolean is_lwir = LWIR_PARAMETERS.is_LWIR(imp_sel);
int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
LWIR_PARAMETERS, // LwirReaderParameters lwirReaderParameters,
DISTORTION, //
PATTERN_DETECT,
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 "+(in_file)+" not found or too small ("+numAbsolutePoints+"), wasted "+
IJ.d2s(0.000000001*(System.nanoTime()-startFileTime),3)+" seconds )\n");
if (this.SYNC_COMMAND.stopRequested.get()>0) {
System.out.println("User requested stop");
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 (imp_calibrated == null) {
if (DEBUG_LEVEL> -1) System.out.println("Grid is empty !");
continue;
}
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();
// String path = gridDir + Prefs.getFileSeparator() + set_name+Prefs.getFileSeparator()+imp_calibrated.getTitle();
if (UPDATE_STATUS) IJ.showStatus("Saving "+grid_path);
if (DEBUG_LEVEL>0) System.out.println("-->>> Saving "+grid_path+" - using "+numAbsolutePoints+" laser pointer references");
fs.saveAsTiffStack(grid_path);
}
}
}
if (DEBUG_LEVEL>0) System.out.println("Grid "+(saved_file+1)+" calculation done at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+" (in "+
IJ.d2s(0.000000001*(System.nanoTime()-startFileTime),3)+"s )\n");
//
if (this.SYNC_COMMAND.stopRequested.get()>0) {
System.out.println("User requested stop");
break;
}
saved_file++;
}
}
if (DEBUG_LEVEL>0) System.out.println(((this.SYNC_COMMAND.stopRequested.get()>0)?"Partial (interrupted by user) set of grids":"All")+ " grids calculation done at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
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(
LWIR_PARAMETERS, // LwirReaderParameters lwirReaderParameters,,
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));
return;
}
/* ======================================================================== */
public void processCalibrationFiles() {
if (!showProcessCalibrationFilesDialog(PROCESS_PARAMETERS)) return;
......@@ -9561,8 +9728,8 @@ if (MORE_BUTTONS) {
imp_sel); // reuse the same image window
//Remove for old method?
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
matchSimulatedPattern.calculateDistortions(
LWIR_PARAMETERS,
DISTORTION, //
PATTERN_DETECT,
SIMUL,
......@@ -12470,7 +12637,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
......@@ -12487,6 +12654,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
......@@ -17012,9 +17180,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 */
......@@ -17029,7 +17201,8 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
null, // no mesh distortion here
thisSimulParameters.subdiv,// SIMUL.subdiv, - do not need high quality here
size,
true); // center for greens
true, // center for greens
false);//boolean mono
sim_pix= simulationPattern.extractSimulPatterns (
thisSimulParameters,
1,
......@@ -17049,8 +17222,10 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
pixels[4],
WVgreens, // wave vectors (same units as the pixels array)
// patternDetectParameters.corrRingWidth, // ring (around r=0.5 dist to opposite corr) width
0.1, // contrastSelectSigma
0.5, // contrastAverageSigma
2.0, // distortionParameters.contrastSelectSigmaCenter, // Gaussian sigma to select correlation centers (fraction of UV period), 0.1
0.1, // distortionParameters.contrastSelectSigma, // Gaussian sigma to select correlation centers (fraction of UV period), 0.1
// 0.1, // contrastSelectSigma
// 0.5, // contrastAverageSigma
0.0, // x0, // center coordinates
0.0, //y0,
title)[0]; // title base for optional plots names
......@@ -17576,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
......@@ -17600,7 +17777,8 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
distortedPattern[2], //
simulParameters.subdiv,
fft_size,
simulParameters.center_for_g2);
simulParameters.center_for_g2,
false);//boolean mono
wVectors[0][0]=2.0*distortedPattern[0][0]/subpixel;
wVectors[0][1]=2.0*distortedPattern[0][1]/subpixel;
wVectors[1][0]=2.0*distortedPattern[1][0]/subpixel;
......@@ -17652,7 +17830,8 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
simCorr, //
simulParameters.subdiv,
fft_size,
simulParameters.center_for_g2);
simulParameters.center_for_g2,
false);//boolean mono
}
simul_pixels= simulationPattern.extractSimulPatterns (
simulParameters,
......@@ -19828,7 +20007,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);
......@@ -19844,10 +20023,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;
......@@ -19864,21 +20057,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;
}
......@@ -20084,10 +20298,13 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
public boolean showDistortionDialog(MatchSimulatedPattern.DistortionParameters distortionParameters) {
int i;
GenericDialog gd = new GenericDialog("Distrortion parameters");
gd.addNumericField("FFTSize (Initial pattern detection only):", distortionParameters.FFTSize, 0); // 128
gd.addNumericField("FFTSize (Initial pattern detection only):", distortionParameters.FFTSize, 0); // 256
gd.addNumericField("FFTSize for LWIR sensors):", distortionParameters.FFTSize_lwir, 0); // 32
gd.addNumericField("FFT Gaussian width (relative):", distortionParameters.fftGaussWidth, 3);
gd.addNumericField("Correlation size:", distortionParameters.correlationSize, 0); // 64
gd.addNumericField("Maximal correlation size:", distortionParameters.maximalCorrelationSize, 0); // 64
gd.addNumericField("Correlation size LWIR:", distortionParameters.correlationSizeLwir, 0); // 16
gd.addNumericField("Maximal correlation size:", distortionParameters.maximalCorrelationSize, 0); // 128
gd.addNumericField("Maximal correlation size LWIR:", distortionParameters.maximalCorrelationSizeLwir, 0); // 16
gd.addNumericField("Correlation Gauss width (relative):", distortionParameters.correlationGaussWidth, 3);
gd.addCheckbox("Keep Gaussian width absolute when increasing FFT size",distortionParameters.absoluteCorrelationGaussWidth);
......@@ -20108,23 +20325,25 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
gd.addNumericField("Correlation minimal contrast for initial search (absolute)", distortionParameters.correlationMinAbsoluteInitialContrast, 3);
gd.addNumericField("Decrease contrast of cells that are too close to the border to be processed in refinement pass", distortionParameters.scaleFirstPassContrast, 3);
gd.addNumericField("Gaussian sigma to select correlation centers (fraction of UV period), 0.1", distortionParameters.contrastSelectSigma, 3);
gd.addNumericField("Gaussian sigma to select correlation center in pixels, 2.0", distortionParameters.contrastSelectSigmaCenter, 3);
gd.addNumericField("Gaussian sigma to select correlation off-centers (fraction of UV period), 0.1", distortionParameters.contrastSelectSigma, 3);
gd.addNumericField("Gaussian sigma to average correlation variations (as contrast reference), 0.5", distortionParameters.contrastAverageSigma, 3);
gd.addNumericField("Minimal initial pattern cluster size (0 - disable retries)", distortionParameters.minimalPatternCluster, 0);
gd.addNumericField("Minimal initial pattern cluster size (0 - disable retries)", distortionParameters.minimalPatternCluster, 0); // 40
gd.addNumericField("Minimal initial LWIR pattern cluster size (0 - disable retries)", distortionParameters.minimalPatternClusterLwir, 0); // 10
gd.addNumericField("Scale minimal contrast if the initial cluster is nonzero but smaller", distortionParameters.scaleMinimalInitialContrast, 3);
gd.addNumericField("Overlap of FFT areas when searching for pattern", distortionParameters.searchOverlap, 3);
gd.addNumericField("Pattern subdivision:", distortionParameters.patternSubdiv, 0);
gd.addNumericField("Blur pattern bitmap (sigma): ", distortionParameters.bPatternSigma, 3,5,"pattern cell");
gd.addNumericField("Blur pattern (sigma): ", distortionParameters.barraySigma, 3,5,"sensor pix");
gd.addNumericField("Correlation weights (around maximum):", distortionParameters.correlationWeightSigma, 3,5,"nodes");
gd.addNumericField("Correlation radius scale (0 - sharp sigma)", distortionParameters.correlationRadiusScale, 1,3,"sigmas");
gd.addNumericField("Pattern subdivision:", distortionParameters.patternSubdiv, 0); // 4
gd.addNumericField("Blur pattern bitmap (sigma): ", distortionParameters.bPatternSigma, 3,5,"pattern cell"); // 0.02
gd.addNumericField("Blur pattern (sigma): ", distortionParameters.barraySigma, 3,5,"sensor pix"); // 0.5
gd.addNumericField("Correlation weights (around maximum):", distortionParameters.correlationWeightSigma, 3,5,"nodes"); // 2.5
gd.addNumericField("Correlation radius scale (0 - sharp sigma)", distortionParameters.correlationRadiusScale, 1,3,"sigmas"); //2.0
gd.addNumericField("Correlation maximal radius to use", distortionParameters.correlationRadius, 0,1,"pix");
gd.addNumericField("Correlation maximum calculation threshold", distortionParameters.correlationThreshold*100, 2,5,"%");
gd.addNumericField("Interpolate correlation (FFT*linear)", distortionParameters.correlationSubdiv, 0,1,"x");
gd.addNumericField("Interpolate correlation with FFT", distortionParameters.correlationFFTSubdiv, 0,1,"x");
gd.addNumericField("Correlation maximal radius to use", distortionParameters.correlationRadius, 0,1,"pix"); // 2.0
gd.addNumericField("Correlation maximum calculation threshold", distortionParameters.correlationThreshold*100, 2,5,"%"); // .8
gd.addNumericField("Interpolate correlation (FFT*linear)", distortionParameters.correlationSubdiv, 0,3,"x"); // 16
gd.addNumericField("Interpolate correlation with FFT", distortionParameters.correlationFFTSubdiv, 0,3,"x"); // 4
gd.addNumericField("Correlation dx (debug)", distortionParameters.correlationDx, 3);
gd.addNumericField("Correlation dy (debug)", distortionParameters.correlationDy, 3);
......@@ -20167,19 +20386,18 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
distortionParameters.FFTSize=1;
for (i=(int) gd.getNextNumber(); i >1; i>>=1) distortionParameters.FFTSize <<=1; /* make it to be power of 2 */
distortionParameters.FFTSize = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.FFTSize_lwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.fftGaussWidth= gd.getNextNumber();
distortionParameters.correlationSize=1;
for (i=(int) gd.getNextNumber(); i >1; i>>=1) distortionParameters.correlationSize <<=1; /* make it to be power of 2 */
distortionParameters.maximalCorrelationSize=1;
for (i=(int) gd.getNextNumber(); i >1; i>>=1) distortionParameters.maximalCorrelationSize <<=1; /* make it to be power of 2 */
distortionParameters.correlationSize = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.correlationSizeLwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.maximalCorrelationSize = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.maximalCorrelationSizeLwir = makePowerOfTwo((int) gd.getNextNumber());
distortionParameters.correlationGaussWidth= gd.getNextNumber();
distortionParameters.absoluteCorrelationGaussWidth=gd.getNextBoolean();
distortionParameters.zeros= (int) gd.getNextNumber();
distortionParameters.phaseCorrelationFraction=gd.getNextNumber();
distortionParameters.correlationHighPassSigma=gd.getNextNumber();
distortionParameters.phaseCorrelationFraction= gd.getNextNumber();
distortionParameters.correlationHighPassSigma= gd.getNextNumber();
distortionParameters.correlationLowPassSigma= gd.getNextNumber();
distortionParameters.correlationMaxOffset= gd.getNextNumber();
distortionParameters.correlationRingWidth= gd.getNextNumber();
......@@ -20190,10 +20408,13 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
distortionParameters.correlationMinAbsoluteInitialContrast= gd.getNextNumber();
distortionParameters.scaleFirstPassContrast= gd.getNextNumber();
distortionParameters.contrastSelectSigmaCenter= gd.getNextNumber();
distortionParameters.contrastSelectSigma= gd.getNextNumber();
distortionParameters.contrastAverageSigma= gd.getNextNumber();
distortionParameters.minimalPatternCluster=(int) gd.getNextNumber();
distortionParameters.minimalPatternClusterLwir=(int) gd.getNextNumber();
distortionParameters.scaleMinimalInitialContrast=gd.getNextNumber();
distortionParameters.searchOverlap= gd.getNextNumber();
......@@ -20240,6 +20461,12 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
MASTER_DEBUG_LEVEL= (int) gd.getNextNumber();
return true;
}
private int makePowerOfTwo(int v) {
int v2 = 1;
for (int i=v; i > 1; i>>=1 ) v2 <<=1; /* make it to be power of 2 */
return v2;
}
/* ======================================================================== */
/* ======================================================================== */
public boolean showGaussianStackDialog(EyesisAberrations.InverseParameters inverseParameters) {
......@@ -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;
......@@ -1279,8 +1278,11 @@ public class EyesisAberrations {
}
int rslt=matchSimulatedPattern.calculateDistortions(
null, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters,
// patternDetectParameters.minGridPeriod/2,
// patternDetectParameters.maxGridPeriod/2,
simulParameters,
colorComponents.equalizeGreens,
imp,
......@@ -2313,6 +2315,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 +2402,7 @@ public class EyesisAberrations {
}
final int numFinished=tilesFinishedAtomic.getAndIncrement();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
IJ.showProgress(numFinished,patternCells);
}
......@@ -2679,6 +2683,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
......@@ -2704,7 +2710,8 @@ public class EyesisAberrations {
distortedPattern[2], //
simulParameters.subdiv,
fft_size,
simulParameters.center_for_g2);
simulParameters.center_for_g2,
false);//boolean mono
wVectors[0][0]=2.0*distortedPattern[0][0]/subpixel;
wVectors[0][1]=2.0*distortedPattern[0][1]/subpixel;
wVectors[1][0]=2.0*distortedPattern[1][0]/subpixel;
......@@ -2747,7 +2754,8 @@ public class EyesisAberrations {
simCorr, //
simulParameters.subdiv,
fft_size,
simulParameters.center_for_g2);
simulParameters.center_for_g2,
false);//boolean mono
}
// simul_pixels= simulationPattern.extractSimulPatterns (
simul_pixels= simulationPattern.extractSimulPatterns (
......@@ -4148,7 +4156,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 +4412,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 +4996,7 @@ if (globalDebugLevel>2)globalDebugLevel=0; //***********************************
this.thresholdHigh = thresholdHigh;
this.thresholdLow = thresholdLow;
}
@Override
public OTFFilterParameters clone() {
return new OTFFilterParameters(
this.deconvInvert,
......@@ -5076,6 +5085,7 @@ if (globalDebugLevel>2)globalDebugLevel=0; //***********************************
}
@Override
public PSFParameters clone(){
return new PSFParameters(
this.minContrast,
......
......@@ -665,9 +665,12 @@ horizontal axis:
boolean noMessageBoxes=true;
int numAbsolutePoints = matchSimulatedPattern.calculateDistortions(
null, // LwirReaderParameters lwirReaderParameters, // null is OK
// allow more of grid around pointers?
distortionParameters, //
this.patternDetectParameters,
// this.patternDetectParameters.minGridPeriod/2,
// this.patternDetectParameters.maxGridPeriod/2,
simulParameters,
equalizeGreens, imp_eq,
this.laserPointers, // null, //LASER_POINTERS, //
......@@ -838,9 +841,12 @@ horizontal axis:
// matchSimulatedPatterns[numSensor].getChannel(images[numSensor])+" ");
int numAbsolutePoints = this.matchSimulatedPatterns[numSensor].calculateDistortions(
null, // LwirReaderParameters lwirReaderParameters, // null is OK
// allow more of grid around pointers?
distortionParameters, //
this.patternDetectParameters,
// this.patternDetectParameters.minGridPeriod/2,
// this.patternDetectParameters.maxGridPeriod/2,
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;
......@@ -100,6 +99,7 @@ public class LensAdjustment {
ImagePlus imp_eq=matchSimulatedPattern.applyFlatField (imp); // will throw if image size mismatch
if (updating) {
double maxActualCorr= matchSimulatedPattern.refineDistortionCorrelation (
null, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters,
simulParameters,
......@@ -133,9 +133,12 @@ public class LensAdjustment {
System.out.println("updateFocusGrid(), number of already defined grid cells (before distortions()) = "+matchSimulatedPattern.numDefinedCells());
}
matchSimulatedPattern.distortions(
null, // is not used in update mode
null, //LwirReaderParameters lwirReaderParameters, // null is OK
null, // final boolean [] triedIndices, // is not used in update mode
distortionParameters, //
patternDetectParameters,
patternDetectParameters.minGridPeriod/2,
patternDetectParameters.maxGridPeriod/2,
simulParameters,
equalizeGreens,
imp_eq, // image to process
......@@ -156,8 +159,11 @@ public class LensAdjustment {
// matchSimulatedPattern.invalidateFlatFieldForGrid(); //Keep these!
// matchSimulatedPattern.invalidateFocusMask();
numAbsolutePoints=matchSimulatedPattern.calculateDistortions( // allow more of grid around pointers?
null, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters,
// patternDetectParameters.minGridPeriod/2,
// patternDetectParameters.maxGridPeriod/2,
simulParameters,
equalizeGreens,
imp_eq,
......@@ -806,6 +812,7 @@ public class LensAdjustment {
this.reportTemperature=reportTemperature;
this.showLegacy=showLegacy;
}
@Override
public FocusMeasurementParameters clone(){
return new FocusMeasurementParameters(
this.gridGeometryFile,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -35,11 +35,11 @@ import ij.IJ;
*/
public class SimulationPattern {
// private double [] bPattern; // pattern bitmap (does not change)
// private double[][] barray; // high resolution boolean pattern array (specific to distortions in each area)
// private double [] bPattern; // pattern bitmap (does not change)
// private double[][] barray; // high resolution boolean pattern array (specific to distortions in each area)
public double [] bPattern=null; // pattern bitmap (does not change)
public int bPatternSize=0;
/// public double[][] barray; // high resolution boolean pattern array (specific to distortions in each area)
/// public double[][] barray; // high resolution boolean pattern array (specific to distortions in each area)
public double[] barray; // high resolution boolean pattern array (specific to distortions in each area)
public double bPatternSigma=0.0;
public double barraySigma=0.0;
......@@ -116,10 +116,10 @@ public class SimulationPattern {
break;
default: for (index=0;index<this.bPattern.length;index++) this.bPattern[index]=1.0;
}
// blur pattern
// blur pattern
if (this.bPatternSigma>0) {
if (this.bPatternSigma>0.25) this.bPatternSigma=0.25;
// 1 - add margins around the pattern
// 1 - add margins around the pattern
int i1,j1;
int margin= (int) Math.ceil(3*size*this.bPatternSigma);
int sizeM=size+2*margin;
......@@ -134,11 +134,11 @@ public class SimulationPattern {
bPatternM[i*sizeM+j]= (invertX ^ invertY)?(1.0-this.bPattern[i1*size+j1]):this.bPattern[i1*size+j1];
}
}
// apply blur
// apply blur
if (this.debugLevel>3) SDFA_INSTANCE.showArrays(bPatternM,sizeM,sizeM, "bPatternM");
this.gb.blurDouble(bPatternM,sizeM,sizeM,size*this.bPatternSigma,size*this.bPatternSigma, 0.01);
if (this.debugLevel>3) SDFA_INSTANCE.showArrays(bPatternM,sizeM,sizeM, "bPatternM-blured");
// remove margins
// remove margins
for (i=0;i<size;i++) for (j=0;j<size;j++) {
this.bPattern[i*size+j]= bPatternM[(i+margin)*sizeM+(j+margin)];
}
......@@ -146,7 +146,7 @@ public class SimulationPattern {
return this.bPattern;
}
/* ======================================================================== */
/* ======================================================================== */
public void simulatePatternFullPattern(
double freqX1,
double freqY1,
......@@ -157,7 +157,8 @@ public class SimulationPattern {
double [] corr,
int subdiv,
int size,
boolean center_for_g2) {
boolean center_for_g2,
boolean mono) {// takes precedence over center_for_g2, makes symmetrical around center of array (between pixels)
this.barray=simulatePatternFullPatternSafe(
freqX1,
freqY1,
......@@ -168,7 +169,9 @@ public class SimulationPattern {
corr,
subdiv,
size,
center_for_g2);
center_for_g2,
mono);
}
......@@ -182,7 +185,8 @@ public class SimulationPattern {
double [] corr,
int subdiv,
int size,
boolean center_for_g2) {
boolean center_for_g2,
boolean mono) {// takes precedence over center_for_g2, makes symmetrical around center of array (between pixels)
int patternSize= (this.bPattern!=null)?((int) Math.sqrt(this.bPattern.length)):0;
double twicePatternSize=2*patternSize;
int i,j;
......@@ -211,12 +215,16 @@ public class SimulationPattern {
double [] phases={phase1/(Math.PI*2)+0.25,phase2/(Math.PI*2)+0.25}; // period=1.0;
int iu,iv;
boolean invert;
for (i=0;i<fullSize;i++) {
yl=(i-0.5*fullSize)/subdiv-(center_for_g2?0.5:1.0); // center in the middle of Bayer
for (j=0;j<fullSize;j++) {
xl=(j-0.5*fullSize)/subdiv-(center_for_g2?0.5:1.0); // center in the middle of Bayer
/* apply second order polynomial correction to x,y
double offset = mono? 0.0: ((center_for_g2?0.5:1.0));
double center = 0.5*fullSize; // +(mono?-0.5: 0.0); // see if it is needed!
// in mono mode result barray is symmetrical around [fullSize/2,fullSize/2], but
// after extractSimulMono result will be symmetrical around [size/2-0.5, size/2 - 0.5]
for (i=0; i<fullSize; i++) {
yl=(i - center) / subdiv - offset; // center in the middle of Bayer
for (j=0; j<fullSize; j++) {
xl=(j - center) / subdiv - offset; // center in the middle of Bayer
/* apply second order polynomial correction to x,y
x=xl+Ax*xl^2+Bx*yl^2+2*Cx*xl*yl;
y=xl+Ay*xl^2+By*yl^2+2*Cy*xl*yl; */
if (corr==null) {
......@@ -256,7 +264,7 @@ public class SimulationPattern {
}
}
}
// Blur barray pattern if sigma >0
// Blur barray pattern if sigma >0
if (this.barraySigma>0) {
double sigma=this.barraySigma*subdiv; //*/ 2?
if (this.debugLevel>3) SDFA_INSTANCE.showArrays(localBarray, "localBarray");
......@@ -265,7 +273,7 @@ public class SimulationPattern {
}
return localBarray;
}
/* ======================================================================== */
/* ======================================================================== */
public double [] recursiveFillPixels ( // invert pattern in the caller, return signed value (-1..1 - pattern is 0..1)
SimulParameters simulParameters,
double [] xy, // top-left corner
......@@ -273,7 +281,7 @@ public class SimulationPattern {
double [][][] cornersXY, // xy pairs for the 4 corners of the square in UV (pattern) coordinates (u0v0,u1v0,u0v1,u1v1)
double [] uv, // UV value for the top-left corner (matching cornersXY[0][0])
double [] duv, // distances to the opposite corner in UV
// final boolean maskOnly, // just mark defined cells
// final boolean maskOnly, // just mark defined cells
int debug
){ //use this.bPattern, this.bPatternSize (side of the square)
......@@ -289,7 +297,7 @@ public class SimulationPattern {
}
if (debug>21){
String dbgStr="";
// IJ.d2s(quarter_patterns[iq][0][0],4)
// IJ.d2s(quarter_patterns[iq][0][0],4)
dbgStr+="xy={"+IJ.d2s(xy[0],2)+","+IJ.d2s(xy[1],2)+"} ";
dbgStr+=" dxy={"+IJ.d2s(dxy[0],2)+","+IJ.d2s(dxy[1],2)+"} ";
dbgStr+=" uv={"+IJ.d2s(uv[0],2)+","+IJ.d2s(uv[1],2)+"} ";
......@@ -307,25 +315,25 @@ public class SimulationPattern {
}
if (numInside==0) return result; // all corners outside of the (sub)pattern cell
// if (maskOnly) {
// if (maskOnly) {
if (simulParameters==null) {
result[1]=dxy[0]*dxy[1];
result[0]=result[1];
return result;
}
// recalculate to the full uv
// recalculate to the full uv
boolean cornersInvert;
double [][] cornerValue=new double [2][2];
int [] iPat=new int [2];
double min=1.0,max=-1.0;
for (int i=0;i<2;i++) for (int j=0;j<2;j++) {
// cornersUV[i][j][0]=uv[0]+j*cornersUV[i][j][0]*duv[0];
// cornersUV[i][j][1]=uv[1]+i*cornersUV[i][j][1]*duv[1];
// cornersUV[i][j][0]=uv[0]+j*cornersUV[i][j][0]*duv[0];
// cornersUV[i][j][1]=uv[1]+i*cornersUV[i][j][1]*duv[1];
cornersUV[i][j][0]=uv[0]+cornersUV[i][j][0]*duv[0];
cornersUV[i][j][1]=uv[1]+cornersUV[i][j][1]*duv[1];
cornersInvert=false;
for (int k=0;k<2;k++) {
// iPat[k] = (int) Math.floor(cornersUV[i][j][k]*this.bPatternSize*2.0); // 0.5 ->bPatternSize
// iPat[k] = (int) Math.floor(cornersUV[i][j][k]*this.bPatternSize*2.0); // 0.5 ->bPatternSize
iPat[k] = (int) Math.floor(cornersUV[i][j][k]*this.bPatternSize); // 1.0 ->bPatternSize
if (iPat[k]<0){
iPat[k]+=this.bPatternSize;
......@@ -347,7 +355,7 @@ public class SimulationPattern {
(dxy[0]>simulParameters.smallestSubPix) &&
(dxy[1]>simulParameters.smallestSubPix)) {
// divide this square into 4 quadrants, return sum of the recursively called method on them
// divide this square into 4 quadrants, return sum of the recursively called method on them
double [][] quadrants={{0.0,0.0},{0.5,0.0},{0.0,0.5},{0.5,0.5}};
double [] subResult;
double [] subxy=new double [2];
......@@ -375,7 +383,7 @@ public class SimulationPattern {
cornersXY, // xy pairs for the 4 corners of the square in UV (pattern) coordinates (u0v0,u1v0,u0v1,u1v1)
uv, // UV value for the top-left corner (matching cornersXY[0][0])
duv, // distances to the opposite corner in UV
// maskOnly, // just mark defined cells //always false - will never get here
// maskOnly, // just mark defined cells //always false - will never get here
debug
);
result[0]+=subResult[0];
......@@ -402,7 +410,7 @@ public class SimulationPattern {
}
return result;
}
/* ======================================================================== */
/* ======================================================================== */
/**
* @param cornersXY first index V, second index U, third index:0 - x, 1-y
* @param xy 0-x,1-y of the point, for which UV should be generated
......@@ -431,7 +439,7 @@ public class SimulationPattern {
double quadThreshold, // if abs(4*a*c)/b^2 is less than this, use linear, not quadratic equations
int debug
) {
/*
/*
x,y -> u,v
(1) x= v*u*Ax + v*Bx + u*Cx + Dx
......@@ -479,26 +487,26 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
double Av=(By*Ax-Bx*Ay);
double Bv=((-Bx*Cy-Ay*Dx+By*Cx+Ax*Dy)+Ay*xy[0]-Ax*xy[1]);
double Cv=(Cy*xy[0]-Cx*xy[1])+(-Cy*Dx+Cx*Dy);
// double [] UV={-Cv/Bv,-Cu/Bu}; // linear solution - use for linear grid
// double [] UV={-Cv/Bv,-Cu/Bu}; // linear solution - use for linear grid
double [] UV={-Cu/Bu,-Cv/Bv}; // linear solution - use for linear grid
double au=0.0,bu=0.0,av=0.0,bv=0.0;
if (Math.abs(Au*Cu)/(Bu*Bu)>quadThreshold) { // use quadratic equation for U
au=-Bu/(2*Au);
bu=Math.sqrt(Bu*Bu-4*Au*Cu)/Math.abs(2*Au);
// Use solution that is closer to linear one
// Use solution that is closer to linear one
if (UV[0]>au) UV[0]=au+bu;
else UV[0]=au-bu;
}
if (Math.abs(Av*Cv)/(Bv*Bv)>quadThreshold) { // use quadratic equation for V
av=-Bv/(2*Av);
bv=Math.sqrt(Bv*Bv-4*Av*Cv)/Math.abs(2*Av);
// Use solution that is closer to linear one
// Use solution that is closer to linear one
if (UV[1]>av) UV[1]=av+bv;
else UV[1]=av-bv;
}
if (debug>2){
String dbgStr="";
// IJ.d2s(quarter_patterns[iq][0][0],4)
// IJ.d2s(quarter_patterns[iq][0][0],4)
dbgStr+=" Ax="+IJ.d2s(Ax,5)+", Bx="+IJ.d2s(Bx,5)+", Cx="+IJ.d2s(Cx,5)+", Dx="+IJ.d2s(Dx,5);
dbgStr+=" Ay="+IJ.d2s(Ay,5)+", By="+IJ.d2s(By,5)+", Cy="+IJ.d2s(Cy,5)+", Dy="+IJ.d2s(Dy,5);
dbgStr+=" Au="+IJ.d2s(Au,5)+", Bu="+IJ.d2s(Bu,5)+", Cu="+IJ.d2s(Cu,5);
......@@ -511,7 +519,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
return UV;
}
/* ======================================================================== */
/* ======================================================================== */
private boolean isCellValid(
double [][][][] grid,
int [] uv){
......@@ -521,14 +529,14 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
}
return false;
}
/*
/*
private boolean isCellDefined(
double [][][][] grid,
int [] uv){
return ((uv[1]>=0) && (uv[0]>=0) && (uv[1]<grid.length) && (uv[0]<grid[uv[1]].length) &&
(grid[uv[1]][uv[0]]!=null) && (grid[uv[1]][uv[0]][0]!=null));
}
*/
*/
public float [] combineWithCanvas(
double canvasFill,
int width,
......@@ -588,25 +596,25 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
}
return canvas;
}
//===================== Moved from Aberration_Calibration
//===================== Moved from Aberration_Calibration
public float[][] simulateGridAll (
int width, // extend to full image, width, height - original (not scaled) image size
int height,
MatchSimulatedPattern matchSimulatedPattern,
// double [][][][] patternGrid, // should be aligned to gridFrac
// double [][][][] patternGrid, // should be aligned to gridFrac
int gridFrac, // number of grid steps per pattern full period
SimulParameters simulParameters,
int threadsMax,
boolean updateStatus,
int globalDebugLevel,
int debug_level){// debug level used inside loops
// SimulationPattern simulationPattern=new SimulationPattern(simulParameters);
// SimulationPattern simulationPattern=new SimulationPattern(simulParameters);
float [][] simArray0=simulateGridAll (
matchSimulatedPattern,
// patternGrid, // should be aligned to gridFrac
// patternGrid, // should be aligned to gridFrac
gridFrac, // number of grid steps per pattern full period
simulParameters,
// simulationPattern,
// simulationPattern,
threadsMax,
updateStatus,
globalDebugLevel,
......@@ -624,17 +632,17 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
public float[][] simulateGridAll (
MatchSimulatedPattern matchSimulatedPattern,
// double [][][][] patternGrid, // should be aligned to gridFrac
// double [][][][] patternGrid, // should be aligned to gridFrac
int gridFrac, // number of grid steps per pattern full period
SimulationPattern.SimulParameters simulParameters,
// SimulationPattern simulationPattern, // or null
// SimulationPattern simulationPattern, // or null
int threadsMax,
boolean updateStatus,
int globalDebugLevel,
int debug_level){// debug level used inside loops
long startTime=System.nanoTime();
double [][] xy0={{simulParameters.offsetX,simulParameters.offsetY},{simulParameters.offsetX-0.5,simulParameters.offsetY-0.5}} ;
// if (simulationPattern==null) simulationPattern=new SimulationPattern(simulParameters);
// if (simulationPattern==null) simulationPattern=new SimulationPattern(simulParameters);
float[][] simArray=new float[2][];
simArray[0]= simulateGrid (
matchSimulatedPattern.getDArray(),
......@@ -661,7 +669,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
return simArray;
}
//========================
//========================
public float [] simulateGrid (
final double [][][][] patternGrid, // should be aligned to gridFrac
final int gridFrac, // number of grid steps per pattern full period: black+white
......@@ -669,7 +677,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
final Rectangle woi,
final int subdiv, // subdivide output array from woi (normally 2)
double[] shift_xy, // add to patterGrid xy, null OK
// final boolean maskOnly, // just mark defined cells
// final boolean maskOnly, // just mark defined cells
final int threadsMax,
final boolean updateStatus,
final int debug_level){// debug level used inside loops
......@@ -705,8 +713,9 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
cellNum.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
// String dbgStr="";
// String dbgStr="";
int [][][] iUV=new int [2][2][2];
double [][][] dUV=new double [2][2][2];
double [][][] xy=new double [2][2][2];
......@@ -764,7 +773,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
for (int iy=rcell.y;iy<(rcell.y+rcell.height);iy++) for (int ix=rcell.x;ix<(rcell.x+rcell.width);ix++)
if (woiOut.contains (ix,iy))
{
double [] pixXY={(double) ix,(double) iy};
double [] pixXY={ix,iy};
double [] pixData=recursiveFillPixels ( // invert pattern in the caller, return signed value (-1..1 - pattern is 0..1)
simulParameters,
pixXY, // top-left corner
......@@ -811,6 +820,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
}
final int numFinished=finishedAtomic.getAndIncrement();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
IJ.showProgress(numFinished,cellsToProcess);
}
......@@ -823,8 +833,8 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
startAndJoin(threads);
}
for (int i=0;i<pixels.length;i++ ) {
// /(simulParameters!=null)
// if (maskOnly) {
// /(simulParameters!=null)
// if (maskOnly) {
if (simulParameters==null) {
if (pixelsDenom[i]==0.0F) pixels[i]=-1;
} else {
......@@ -868,9 +878,9 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
}
}
/* ======================================================================== */
/* make it faster when outSubdiv =2*n (usually so) */
/* TODO: cleanup shifts - they seem now to work correctly */
/* ======================================================================== */
/* make it faster when outSubdiv =2*n (usually so) */
/* TODO: cleanup shifts - they seem now to work correctly */
public double [][] extractSimulPatterns (
SimulParameters simulParameters,
int outSubdiv, // subdivide output pixels
......@@ -949,7 +959,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
}
} else { // just reuse available greens
if (this.debugLevel>2)System.out.println("Generating combined greens pattern from individual greens");
/* now combine greens - same as in splitBayer() */
/* now combine greens - same as in splitBayer() */
int base, base_b;
base_b=0;
......@@ -984,6 +994,69 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
return simul_pixels;
}
public double [] extractSimulMono (
SimulParameters simulParameters,
int outSubdiv, // subdivide output pixels
int size, // number of Bayer cells in width of the square selection (half number of pixels)
double x0, // selection center, X (in pixels)
double y0) {
return extractSimulMono (
this.barray,
simulParameters,
outSubdiv, // subdivide output pixels
size, // number of Bayer cells in width of the square selection (half number of pixels)
x0, // selection center, X (in pixels)
y0);
}
public double [] extractSimulMono ( // TODO: can use twice smaller barray
double [] localbArray,
SimulParameters simulParameters,
int outSubdiv, // subdivide output pixels - now 4
int size, // number of Bayer cells in width of the square selection (half number of pixels)
double x0, // selection center, X (in pixels)
double y0) {
int sampleWidth=(int) (Math.sqrt(simulParameters.fill)*simulParameters.subdiv);
int sampleN=sampleWidth*sampleWidth;
if (sampleWidth<1) sampleWidth=1;
else if (sampleWidth>simulParameters.subdiv)sampleWidth=simulParameters.subdiv;
double sampleAverage=0.5*sampleN;
int fullSize=(int) Math.sqrt(localbArray.length);
double [] simul_pixels=new double [size*size];
int ix,iy, iy0,ix0,px,py;
double s;
double span=((double) size)/outSubdiv;
int sampLow=-sampleWidth/2;
int sampHigh=sampLow+sampleWidth;
for (iy=0;iy<size;iy++) {
iy0=(fullSize/2) + (int) (( -span/2 + y0 + 0.5 + 1.0 * iy / outSubdiv)*simulParameters.subdiv);
for (ix=0;ix<size;ix++) {
ix0=(fullSize/2) + (int) ((-span/2 + x0 + 0.5 + 1.0 * ix / outSubdiv)*simulParameters.subdiv);
s=0.0;
for (py=iy0+sampLow;py<iy0+sampHigh;py++) for (px=ix0+sampLow;px<ix0+sampHigh;px++) {
try {
s+=localbArray[py*fullSize+px];
} catch (Exception e){
System.out.println("Bug in extractSimulMono(): px="+px+" py="+py+" fullSize="+fullSize+" size="+size+" x0="+x0+" y0="+y0);
e.printStackTrace();
return null;
}
}
simul_pixels[iy*size+ix]= (s-sampleAverage)/sampleAverage;
}
}
if (this.debugLevel>2) {
System.out.println("extractSimulMono, x0="+x0+" y0="+y0+" fullSize="+fullSize+" size="+size+" subdiv="+simulParameters.subdiv+" outSubdiv="+outSubdiv);
System.out.println(" sampLow="+sampLow+" sampHigh="+sampHigh+" span="+span+" size="+size);
s=0.0;
for (int i=0;i<simul_pixels.length;i++) s+=simul_pixels[i];
System.out.println("sum of pixels="+s);
}
if (this.debugLevel>2) SDFA_INSTANCE.showArrays(simul_pixels,size,size, "SIMUL");
return simul_pixels;
}
private double [] matrix2x2_mul(double [][] a, double [] b ){
double [] rslt={a[0][0]*b[0]+a[0][1]*b[1],
a[1][0]*b[0]+a[1][1]*b[1]};
......@@ -1019,8 +1092,8 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
if (colorComp==4) { // checkerboard greens
r.y+=r.width/2; // now it is the "top left" corner of the diagonal greens
for (index=0;index<result.length;index++){
// int iy=r.y+(index / r.width);
// int ix=r.x+(index % r.width);
// int iy=r.y+(index / r.width);
// int ix=r.x+(index % r.width);
int iyi=index / r.width;
int ixi=index % r.width;
int iy=r.y+(iyi+ixi)/2 -ixi;
......@@ -1052,7 +1125,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
return result;
}
//=====================
//=====================
public static class SimulParameters {
public int patternSize;
public int pattern_type;
......@@ -1115,6 +1188,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
this.offsetY= offsetY;
}
@Override
public SimulParameters clone() {
return new SimulParameters(
this.patternSize,
......
......@@ -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;
*/
}
/**
......@@ -387,7 +303,7 @@ public class DoubleFHT {
else return phaseCorrelate (first, second, phaseCoeff,filter);
}
//asymmetrical - will divide by squared second amplitude (pattern to match)
public double [] phaseCorrelate (
public double [] phaseCorrelate ( // old
double [] first,
double [] second,
double phaseCoeff,
......@@ -408,6 +324,104 @@ 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 [] phaseCorrelate (
double [] first,
double [] second,
double phaseCoeff,
double highPassSigma,
double lowPassSigma,
double [] first_save,
double [] second_save ){ //null-OK
updateMaxN(first);
double [] filter = null;
if ((highPassSigma >0) || (lowPassSigma > 0)) {
filter = createFrequencyFilter(highPassSigma, lowPassSigma);
}
return phaseCorrelate (
first,
second,
phaseCoeff,
filter, // high/low pass filtering
first_save,
second_save );
}
public double [] phaseCorrelate ( // new
double [] first,
double [] second,
double phaseCoeff,
double [] filter, // high/low pass filtering
double [] first_save,
double [] second_save ){ //null-OK
if (first.length!=second.length) {
IJ.showMessage("Error","Correlation arrays should be the same size");
return null;
}
updateMaxN(first);
swapQuadrants(first);
swapQuadrants(second);
if (!transform(first,false)) return null; // direct FHT
if (!transform(second,false)) return null; // direct FHT
if (first_save != null) System.arraycopy(first, 0, first_save, 0, first.length);
if (second_save != null) System.arraycopy(second, 0, second_save, 0, second.length);
first= phaseMultiplyNorm(first, second, 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 +2038,7 @@ public class DoubleFHT {
return product;
}
public double [] phaseMultiply(double [] h1, double [] h2, double phaseCoeff) {
int rowMod, colMod;
double h2e, h2o,d;
......@@ -2041,6 +2056,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 +2157,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 +2207,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;
......
......@@ -1358,7 +1358,11 @@ Exception in thread "Thread-3564" java.lang.ArrayIndexOutOfBoundsException: 8970
itr=set.iterator();
while(itr.hasNext()) {
str = (String) itr.next();
try {
imp_dst.setProperty(str,prop.getProperty(str));
} catch (Exception e) {
imp_dst.setProperty(str,"");
}
}
}
}
......@@ -1407,7 +1411,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,15 @@
*/
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.ImagePlus;
import ij.Prefs;
public class LwirReaderParameters {
private boolean parameters_updated = false;
protected int avg_number = 4; // number of measurements to average
......@@ -49,6 +54,8 @@ 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 int max_lwir_width = 1024; //
/*
protected double [] vnir_exp_corr = {1.0, 1.0, 1.0, 1.0};
......@@ -73,11 +80,19 @@ public class LwirReaderParameters {
protected int debug_level = 0;//-3: OFF, -2:Fatal, -1:ERROR, 0:WARN, 1:INFO,2:DEBUG
protected boolean show_images = false;
// --- interface methods
public boolean is_LWIR(int width) {
return width <= max_lwir_width;
}
public boolean is_LWIR(ImagePlus imp){
return is_LWIR(imp.getWidth());
}
public int getDebugLevel() {
return this.debug_level;
}
public void setDebugLevel(int level) {
this.debug_level = level;
}
......@@ -110,9 +125,9 @@ 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));
properties.setProperty(prefix+"show_images", this.show_images+"");
}
public void getProperties(String prefix,Properties properties){
......@@ -140,8 +155,8 @@ 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"));
if (properties.getProperty(prefix+"show_images")!=null) this.show_images= Boolean.parseBoolean(properties.getProperty(prefix+"show_images"));
parameters_updated = true;
}
@Override
......@@ -171,6 +186,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();
lrp.show_images = this.show_images;
return lrp;
}
......@@ -208,6 +224,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) &&
(java.util.Arrays.equals(lrp.selected_channels, this.selected_channels)) &&
(lrp.show_images == this.show_images);
}
......@@ -235,6 +252,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();
......@@ -251,7 +269,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");
......@@ -267,6 +285,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)");
gd.addCheckbox ("Show images", this.show_images, "Show acquired images after averaging)");
}
......@@ -295,8 +314,8 @@ 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());
this.show_images = gd.getNextBoolean();
parameters_updated = true;
}
......@@ -320,6 +339,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) {
......@@ -334,6 +427,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) {
......@@ -362,4 +472,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