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

generating range-balanced PNG files for preview videos

parent 3735bd46
...@@ -1192,7 +1192,7 @@ public class JP46_Reader_camera0 extends PlugInFrame implements ActionListener { ...@@ -1192,7 +1192,7 @@ public class JP46_Reader_camera0 extends PlugInFrame implements ActionListener {
try { try {
url = new URL(cameraurl); url = new URL(cameraurl);
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
System.out.println("Bad URL: " + cameraurl); System.out.println("Bad URL5: " + cameraurl);
return null; return null;
} }
......
...@@ -1072,6 +1072,9 @@ if (MORE_BUTTONS) { ...@@ -1072,6 +1072,9 @@ if (MORE_BUTTONS) {
addButton("Illustrations Configure", panelIllustrations,color_configure); addButton("Illustrations Configure", panelIllustrations,color_configure);
addButton("Remove bad grids", panelIllustrations,color_stop); addButton("Remove bad grids", panelIllustrations,color_stop);
addButton("Illustrations", panelIllustrations,color_bundle); addButton("Illustrations", panelIllustrations,color_bundle);
addButton("Illustrate Kernels", panelIllustrations,color_process);
addButton("Illustrate Footage", panelIllustrations,color_process);
add(panelIllustrations); add(panelIllustrations);
...@@ -8867,6 +8870,10 @@ if (MORE_BUTTONS) { ...@@ -8867,6 +8870,10 @@ if (MORE_BUTTONS) {
/* ======================================================================== */ /* ======================================================================== */
if (label.equals("Select Channels")) { if (label.equals("Select Channels")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL; DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
if (LENS_DISTORTIONS == null) {
LENS_DISTORTIONS=new Distortions(LENS_DISTORTION_PARAMETERS,PATTERN_PARAMETERS,REFINE_PARAMETERS,this.SYNC_COMMAND.stopRequested);
}
ABERRATIONS_PARAMETERS.selectChannelsToProcess("Select channels to process",LENS_DISTORTIONS); //LENS_DISTORTIONS==null OK ABERRATIONS_PARAMETERS.selectChannelsToProcess("Select channels to process",LENS_DISTORTIONS); //LENS_DISTORTIONS==null OK
return; return;
} }
...@@ -9432,6 +9439,7 @@ if (MORE_BUTTONS) { ...@@ -9432,6 +9439,7 @@ if (MORE_BUTTONS) {
if (CALIBRATION_ILLUSTRATION == null) { if (CALIBRATION_ILLUSTRATION == null) {
CALIBRATION_ILLUSTRATION = new CalibrationIllustration( CALIBRATION_ILLUSTRATION = new CalibrationIllustration(
LWIR_PARAMETERS, // LwirReaderParameters lwirReaderParameters,
CALIBRATION_ILLUSTRATION_PARAMETERS, // CalibrationIllustrationParameters illustrationParameters, CALIBRATION_ILLUSTRATION_PARAMETERS, // CalibrationIllustrationParameters illustrationParameters,
EYESIS_ABERRATIONS, // EyesisAberrations eyesisAberrations, EYESIS_ABERRATIONS, // EyesisAberrations eyesisAberrations,
LENS_DISTORTIONS, // Distortions distortions, LENS_DISTORTIONS, // Distortions distortions,
...@@ -9442,6 +9450,114 @@ if (MORE_BUTTONS) { ...@@ -9442,6 +9450,114 @@ if (MORE_BUTTONS) {
return; return;
} }
/* ======================================================================== */ /* ======================================================================== */
if (label.equals("Illustrate Footage")) {
// if (LENS_DISTORTIONS==null) {
// IJ.showMessage("LENS_DISTORTION is not set"); // to use all grids imported
// return;
// }
// EYESIS_ABERRATIONS.setDistortions(LENS_DISTORTIONS);
if (EYESIS_ABERRATIONS.aberrationParameters.illustrationsDirectory.length()>0){
File dFile=new File(EYESIS_ABERRATIONS.aberrationParameters.illustrationsDirectory);
if (!dFile.isDirectory() && !dFile.mkdirs()) {
String msg="Failed to create directory "+EYESIS_ABERRATIONS.aberrationParameters.illustrationsDirectory;
IJ.showMessage("Warning",msg);
System.out.println("Warning: "+msg);
EYESIS_ABERRATIONS.aberrationParameters.illustrationsDirectory=""; // start over with selecting directory
}
}
String configPath=EYESIS_ABERRATIONS.aberrationParameters.selectIllustrationsDirectory(
true,
EYESIS_ABERRATIONS.aberrationParameters.illustrationsDirectory,
true);
if (configPath==null){
String msg="No illustrations directory selected, command aborted";
System.out.println("Warning: "+msg);
IJ.showMessage("Warning",msg);
return;
}
configPath+=Prefs.getFileSeparator()+"config-illustrations";
try {
saveTimestampedProperties(
configPath, // full path or null
null, // use as default directory if path==null
true,
PROPERTIES);
} catch (Exception e){
String msg="Failed to save configuration to "+configPath+", command aborted";
System.out.println("Error: "+msg);
IJ.showMessage("Error",msg);
return;
}
if (CALIBRATION_ILLUSTRATION == null) { //LWIR_PARAMETERS
CALIBRATION_ILLUSTRATION = new CalibrationIllustration(
LWIR_PARAMETERS, // LwirReaderParameters lwirReaderParameters,
CALIBRATION_ILLUSTRATION_PARAMETERS, // CalibrationIllustrationParameters illustrationParameters,
EYESIS_ABERRATIONS, // EyesisAberrations eyesisAberrations,
LENS_DISTORTIONS, // Distortions distortions,
SYNC_COMMAND.stopRequested, // AtomicInteger stopRequested,
MASTER_DEBUG_LEVEL); // int debug_level);
}
CALIBRATION_ILLUSTRATION.convertCapturedFiles();
return;
}
//
/* ======================================================================== */
if (label.equals("Illustrate Kernels")) {
if (EYESIS_ABERRATIONS.aberrationParameters.illustrationsDirectory.length()>0){
File dFile=new File(EYESIS_ABERRATIONS.aberrationParameters.illustrationsDirectory);
if (!dFile.isDirectory() && !dFile.mkdirs()) {
String msg="Failed to create directory "+EYESIS_ABERRATIONS.aberrationParameters.illustrationsDirectory;
IJ.showMessage("Warning",msg);
System.out.println("Warning: "+msg);
EYESIS_ABERRATIONS.aberrationParameters.illustrationsDirectory=""; // start over with selecting directory
}
}
String configPath=EYESIS_ABERRATIONS.aberrationParameters.selectIllustrationsDirectory(
true,
EYESIS_ABERRATIONS.aberrationParameters.illustrationsDirectory,
true);
if (configPath==null){
String msg="No illustrations directory selected, command aborted";
System.out.println("Warning: "+msg);
IJ.showMessage("Warning",msg);
return;
}
configPath+=Prefs.getFileSeparator()+"config-illustrations";
try {
saveTimestampedProperties(
configPath, // full path or null
null, // use as default directory if path==null
true,
PROPERTIES);
} catch (Exception e){
String msg="Failed to save configuration to "+configPath+", command aborted";
System.out.println("Error: "+msg);
IJ.showMessage("Error",msg);
return;
}
if (CALIBRATION_ILLUSTRATION == null) {
CALIBRATION_ILLUSTRATION = new CalibrationIllustration(
LWIR_PARAMETERS, // LwirReaderParameters lwirReaderParameters,
CALIBRATION_ILLUSTRATION_PARAMETERS, // CalibrationIllustrationParameters illustrationParameters,
EYESIS_ABERRATIONS, // EyesisAberrations eyesisAberrations,
LENS_DISTORTIONS, // Distortions distortions,
SYNC_COMMAND.stopRequested, // AtomicInteger stopRequested,
MASTER_DEBUG_LEVEL); // int debug_level);
}
CALIBRATION_ILLUSTRATION.convertKernels(
INVERSE.dSize, // int dsize, // direct kernel size
INVERSE.rSize // int rsize // inverse kernel size
);
return;
}
/* ======================================================================== */
if (label.equals("Remove bad grids")) { if (label.equals("Remove bad grids")) {
if (LENS_DISTORTIONS==null) { if (LENS_DISTORTIONS==null) {
IJ.showMessage("LENS_DISTORTION is not set"); // to use all grids imported IJ.showMessage("LENS_DISTORTION is not set"); // to use all grids imported
...@@ -9451,6 +9567,7 @@ if (MORE_BUTTONS) { ...@@ -9451,6 +9567,7 @@ if (MORE_BUTTONS) {
if (CALIBRATION_ILLUSTRATION == null) { if (CALIBRATION_ILLUSTRATION == null) {
CALIBRATION_ILLUSTRATION = new CalibrationIllustration( CALIBRATION_ILLUSTRATION = new CalibrationIllustration(
LWIR_PARAMETERS, // LwirReaderParameters lwirReaderParameters,
CALIBRATION_ILLUSTRATION_PARAMETERS, // CalibrationIllustrationParameters illustrationParameters, CALIBRATION_ILLUSTRATION_PARAMETERS, // CalibrationIllustrationParameters illustrationParameters,
EYESIS_ABERRATIONS, // EyesisAberrations eyesisAberrations, EYESIS_ABERRATIONS, // EyesisAberrations eyesisAberrations,
LENS_DISTORTIONS, // Distortions distortions, LENS_DISTORTIONS, // Distortions distortions,
...@@ -10401,8 +10518,8 @@ if (MORE_BUTTONS) { ...@@ -10401,8 +10518,8 @@ if (MORE_BUTTONS) {
some_type[0] = false; some_type[0] = false;
some_type[1] = false; some_type[1] = false;
} }
if (allornone_eo) some_type[0] = all_type[0]; if (allornone_eo) some_type[0] &= all_type[0];
if (allornone_lwir) some_type[1] = all_type[1]; if (allornone_lwir) some_type[1] &= all_type[1];
if (some_type[0] || some_type[1]) { if (some_type[0] || some_type[1]) {
for (int i = 0; i < avail_chn.length; i++) { for (int i = 0; i < avail_chn.length; i++) {
...@@ -2,8 +2,11 @@ package com.elphel.imagej.calibration; ...@@ -2,8 +2,11 @@ package com.elphel.imagej.calibration;
import java.awt.BasicStroke; import java.awt.BasicStroke;
import java.awt.Color; import java.awt.Color;
import java.awt.Font;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
...@@ -12,6 +15,7 @@ import com.elphel.imagej.cameras.ThermalColor; ...@@ -12,6 +15,7 @@ import com.elphel.imagej.cameras.ThermalColor;
import com.elphel.imagej.common.ShowDoubleFloatArrays; import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.correction.EyesisCorrections; import com.elphel.imagej.correction.EyesisCorrections;
import com.elphel.imagej.lwir.LwirReaderParameters; import com.elphel.imagej.lwir.LwirReaderParameters;
import com.elphel.imagej.readers.ImagejJp4Tiff;
import ij.IJ; import ij.IJ;
import ij.ImagePlus; import ij.ImagePlus;
...@@ -19,10 +23,12 @@ import ij.ImageStack; ...@@ -19,10 +23,12 @@ import ij.ImageStack;
import ij.Prefs; import ij.Prefs;
import ij.gui.Line; import ij.gui.Line;
import ij.process.ImageProcessor; import ij.process.ImageProcessor;
import loci.formats.FormatException;
public class CalibrationIllustration { public class CalibrationIllustration {
public static final int MAX_THREADS = 100; // combine from all classes? public static final int MAX_THREADS = 100; // combine from all classes?
public static final int CONTRAST_INDEX = 2; public static final int CONTRAST_INDEX = 2;
public static final String FOOTAGE_DIR = "footage";
EyesisAberrations eyesisAberrations; EyesisAberrations eyesisAberrations;
Distortions distortions; Distortions distortions;
...@@ -37,18 +43,27 @@ public class CalibrationIllustration { ...@@ -37,18 +43,27 @@ public class CalibrationIllustration {
String [] sourceStationDirs; // = new String [numStations]; // directories of the source files per station String [] sourceStationDirs; // = new String [numStations]; // directories of the source files per station
String [] grid_extensions={".tiff"}; String [] grid_extensions={".tiff"};
String [] src_extensions={".tiff"}; String [] src_extensions={".tiff"};
double [][] offs_scale;// [chn][0] - offset to subtract to normalize, [chn][1] - scale to divide by to normalize
public CalibrationIllustration ( public CalibrationIllustration (
LwirReaderParameters lwirReaderParameters,
CalibrationIllustrationParameters illustrationParameters, CalibrationIllustrationParameters illustrationParameters,
EyesisAberrations eyesisAberrations, EyesisAberrations eyesisAberrations,
Distortions distortions, Distortions distortions,
AtomicInteger stopRequested, AtomicInteger stopRequested,
int debug_level) { int debug_level) {
this.lwirReaderParameters = lwirReaderParameters;
this.illustrationParameters = illustrationParameters; this.illustrationParameters = illustrationParameters;
this.eyesisAberrations = eyesisAberrations; this.eyesisAberrations = eyesisAberrations;
this.distortions = distortions; this.distortions = distortions;
this.stopRequested = stopRequested; this.stopRequested = stopRequested;
this.debug_level = debug_level; this.debug_level = debug_level;
offs_scale = new double[lwirReaderParameters.getTypeMap().length][2];
for (int i = 0; i < offs_scale.length; i++) {
offs_scale[i][0] = 0.0;
offs_scale[i][1] = 1.0;
}
} }
public void plotGrid( public void plotGrid(
...@@ -60,6 +75,10 @@ public class CalibrationIllustration { ...@@ -60,6 +75,10 @@ public class CalibrationIllustration {
Color color_grid_extra, // at least one end points to extra (unreliable) nodes (may be null) Color color_grid_extra, // at least one end points to extra (unreliable) nodes (may be null)
double weak_threshold double weak_threshold
) { ) {
if (numImg == 2276) {
System.out.println(">>>numImg="+numImg);
}
// int line_width = 3; //https://imagej.nih.gov/ij/developer/api/ij/ij/gui/Line.html#drawPixels(ij.process.ImageProcessor) // int line_width = 3; //https://imagej.nih.gov/ij/developer/api/ij/ij/gui/Line.html#drawPixels(ij.process.ImageProcessor)
DistortionCalibrationData dcd = distortions.fittingStrategy.distortionCalibrationData; DistortionCalibrationData dcd = distortions.fittingStrategy.distortionCalibrationData;
GridImageParameters gip = dcd.gIP[numImg]; GridImageParameters gip = dcd.gIP[numImg];
...@@ -118,6 +137,9 @@ public class CalibrationIllustration { ...@@ -118,6 +137,9 @@ public class CalibrationIllustration {
for (int indx = dimsUV.width + 1; indx < upper; indx++) if (grid[indx] >= 0){ for (int indx = dimsUV.width + 1; indx < upper; indx++) if (grid[indx] >= 0){
// try to the right and down // try to the right and down
int g0 = grid[indx]; int g0 = grid[indx];
if ((numImg == 2276) && (g0 == 78)) {
System.out.println(">>>g0="+g0);
}
for (int dir = 0; dir <2; dir++) { // 90 - right, 1 - down for (int dir = 0; dir <2; dir++) { // 90 - right, 1 - down
int indx1 = indx + ((dir > 0) ? dimsUV.width : 1); int indx1 = indx + ((dir > 0) ? dimsUV.width : 1);
if (indx1 < grid.length) { if (indx1 < grid.length) {
...@@ -136,8 +158,15 @@ public class CalibrationIllustration { ...@@ -136,8 +158,15 @@ public class CalibrationIllustration {
if (color_grid_weak == null) { if (color_grid_weak == null) {
continue; continue;
} }
if ((pXY0[CONTRAST_INDEX] == 0.0) && (pXY1[CONTRAST_INDEX] == 0.0)) { // treat strength==0 as extra
if (color_grid_extra == null) {
continue;
}
ip.setColor(color_grid_extra); // should not get here with color_grid_extra==null
} else {
ip.setColor(color_grid_weak); ip.setColor(color_grid_weak);
} }
}
} else { } else {
if (color_grid_extra == null) { if (color_grid_extra == null) {
continue; continue;
...@@ -175,9 +204,1463 @@ public class CalibrationIllustration { ...@@ -175,9 +204,1463 @@ public class CalibrationIllustration {
} }
} }
public boolean convertKernels(
int dsize, // direct kernel size
int rsize // inverse kernel size
) {
long startTime=System.nanoTime(); // restart timer after possible interactive dialogs
boolean same_size_inv = true;
// final boolean [] selectedChannels = eyesisAberrations.aberrationParameters.getChannelSelection(distortions);
final boolean [] selectedChannels = illustrationParameters.getSelectedChannels();
// final DistortionCalibrationData dcd = distortions.fittingStrategy.distortionCalibrationData;
// final MultipleExtensionsFileFilter sourceFilter =
// new MultipleExtensionsFileFilter("",src_extensions,"Source calibration images");
// final int lwir0 = illustrationParameters.getLwirReaderParameters().getLwirChn0();
// final int eo0 = illustrationParameters.getLwirReaderParameters().getEoChn0();
int [][] whall = new int [selectedChannels.length][2];
String illustrations_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory;
String partial_dir = eyesisAberrations.aberrationParameters.partialKernelDirectory;
String direct_dir = eyesisAberrations.aberrationParameters.psfKernelDirectory;
String inverted_dir = eyesisAberrations.aberrationParameters.aberrationsKernelDirectory;
String partial_dest = illustrations_dir+ (illustrations_dir.endsWith(Prefs.getFileSeparator())?"":Prefs.getFileSeparator())+"partial";
String direct_dest = illustrations_dir+ (illustrations_dir.endsWith(Prefs.getFileSeparator())?"":Prefs.getFileSeparator())+"direct";
String inverted_dest = illustrations_dir+ (illustrations_dir.endsWith(Prefs.getFileSeparator())?"":Prefs.getFileSeparator())+"inverted";
if (illustrationParameters.kernel_process_partial) {
convertPartial(
selectedChannels,
dsize,
partial_dir, // String source_dir,
partial_dest);
}
if (illustrationParameters.kernel_process_direct) {
convertDirect(
selectedChannels,
dsize,
direct_dir, // String source_dir,
direct_dest,
whall);
}
if (illustrationParameters.kernel_process_inverse) {
if (!same_size_inv) {
whall = null;
}
convertInverted(
selectedChannels,
rsize,
inverted_dir, // String source_dir,
inverted_dest,
whall);
}
System.out.println("All done in "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+" sec.");
return true;
}
public boolean convertPartial(
final boolean [] selectedChannels,
int src_step,
String source_dir,
String dest_dir) {
String partialSuffix= eyesisAberrations.aberrationParameters.partialSuffix; // .".ppsf-tiff";
File destDir= new File (dest_dir);
if (!destDir.exists()){
if (!destDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+dest_dir);
return false;
}
}
String [][] src_files = new String [selectedChannels.length][];
for (int nChn = 0; nChn < src_files.length; nChn++) if (selectedChannels[nChn]) {
MultipleExtensionsFileFilter sourceFilter =
new MultipleExtensionsFileFilter("",new String[] {String.format("%02d", nChn)+partialSuffix},"partial kernels");
src_files[nChn] = (new File(source_dir)).list(sourceFilter); // are these full files?
}
// create list of partial kernel files
// partial-1623732618_112155-00.ppsf-tiff
final Thread[] threads = newThreadArray(MAX_THREADS);
final AtomicInteger indxAtomic = new AtomicInteger(0);
for (int iChn = 0; iChn < src_files.length; iChn++) if (src_files[iChn]!=null) {
final int nChn=iChn;
indxAtomic.set(0);
int sensor_type = distortions.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.getSensorType(nChn);
int decimate = (sensor_type==1) ? illustrationParameters.kernel_decimate_direct_lwir : illustrationParameters.kernel_decimate_direct_eo;
int kernel_widh = (sensor_type==1) ? illustrationParameters.kernel_dia_direct_lwir : illustrationParameters.kernel_dia_direct_eo;
// String illustrations_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory;
final String chn_ill_dir = dest_dir+Prefs.getFileSeparator()+ illustrationParameters.getChannelPrefix()+String.format("%02d", nChn);
// create directory if it does not exist
final File destChnDir= new File (chn_ill_dir);
if (!destChnDir.exists()){
if (!destChnDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+chn_ill_dir);
continue;
}
}
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
// for (int nChn = indxAtomic.getAndIncrement(); nChn < selectedChannels.length; nChn = indxAtomic.getAndIncrement()) if (selectedChannels[nChn]) {
// iterate through all image set (some grids may be missing)
for (int nImg = indxAtomic.getAndIncrement(); nImg < src_files[nChn].length; nImg = indxAtomic.getAndIncrement()) {
// for (int nImg=0; nImg < src_files[nChn].length; nImg++) {
ImagePlus imp = new ImagePlus(source_dir+Prefs.getFileSeparator()+src_files[nChn][nImg]);
String title = imp.getTitle();
if (title.endsWith(partialSuffix)) {
title = title.substring(0, title.lastIndexOf("."));
}
int [] wh = new int [2];
double [][] dpixels = getDecimatedStack(
imp, // ImagePlus imp,
wh, // int [] wh, // will return width, height
src_step, // int src_step, // margins == src_step/2
decimate, // 1 - no decimation
kernel_widh,
0.0001); // if none kernel pixel above - return null
if (dpixels == null) {
continue; // no kernels
}
ImagePlus imp_ill;
if (sensor_type==1) {
imp_ill = normalizeColorizeLWIRKernels(
title+"-ill", // String title,
dpixels[0], // double [] dpixels,
wh[0], // int width,
illustrationParameters.kernel_direct_lwir_min, // double mn,
illustrationParameters.kernel_direct_lwir_max, // double mx,
illustrationParameters.kernel_lwir_palette); // int palette);
} else {
imp_ill = normalizeColorizeEOKernels(
title+"-ill", // String title,
dpixels, // double [] dpixels,
wh[0], // int width,
illustrationParameters.kernel_direct_red_min, // double mnR,
illustrationParameters.kernel_direct_red_max, // double mxR,
illustrationParameters.kernel_direct_green_min, // double mnG,
illustrationParameters.kernel_direct_green_max, // double mxG,
illustrationParameters.kernel_direct_blue_min, // double mnB,
illustrationParameters.kernel_direct_blue_max); // double mnB,
}
// save result
EyesisCorrections.saveAndShow(
imp_ill,
chn_ill_dir,
illustrationParameters.save_png,
false, // show
illustrationParameters.JPEG_quality, // <0 - keep current, 0 - force Tiff, >0 use for JPEG
0); // debug_level);
// return true; // temporarily
}
}
};
}
startAndJoin(threads);
}
///imp_psf.getStack()
//int sensor_type = dcd.eyesisCameraParameters.getSensorType(nChn);
return true;
}
public boolean convertDirect(
final boolean [] selectedChannels,
final int src_step,
final String source_dir,
final String dest_dir,
final int [][] whall) { // null or per-channel
String directSuffix= eyesisAberrations.aberrationParameters.psfSuffix; // .".psf-tiff";
File destDir= new File (dest_dir);
if (!destDir.exists()){
if (!destDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+dest_dir);
return false;
}
}
String [][] src_files = new String [selectedChannels.length][]; // should be one file per channel
for (int nChn = 0; nChn < src_files.length; nChn++) if (selectedChannels[nChn]) {
MultipleExtensionsFileFilter sourceFilter =
new MultipleExtensionsFileFilter("",new String[] {String.format("%02d", nChn)+directSuffix},"direct kernels");
src_files[nChn] = (new File(source_dir)).list(sourceFilter); // are these full files?
}
// create list of partial kernel files
// partial-1623732618_112155-00.ppsf-tiff
for (int iChn = 0; iChn < src_files.length; iChn++) if (src_files[iChn]!=null) {
final int nChn=iChn;
int sensor_type = distortions.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.getSensorType(nChn);
int decimate = (sensor_type==1) ? illustrationParameters.kernel_decimate_direct_lwir : illustrationParameters.kernel_decimate_direct_eo;
int kernel_widh = (sensor_type==1) ? illustrationParameters.kernel_dia_direct_lwir : illustrationParameters.kernel_dia_direct_eo;
/*
// String illustrations_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory;
final String chn_ill_dir = dest_dir+Prefs.getFileSeparator()+ illustrationParameters.getChannelPrefix()+String.format("%02d", nChn);
// create directory if it does not exist
final File destChnDir= new File (chn_ill_dir);
if (!destChnDir.exists()){
if (!destChnDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+chn_ill_dir);
continue;
}
}
*/
// for (int nImg=0; nImg < src_files[nChn].length; nImg++) {
ImagePlus imp = new ImagePlus(source_dir+Prefs.getFileSeparator()+src_files[nChn][0]);
String title = imp.getTitle();
if (title.endsWith(directSuffix)) {
title = title.substring(0, title.lastIndexOf("."));
}
int [] wh = (whall == null) ? new int [2]: whall[nChn];
double [][] dpixels = getDecimatedStack(
imp, // ImagePlus imp,
wh, // int [] wh, // will return width, height
src_step, // int src_step, // margins == src_step/2
decimate, // 1 - no decimation
kernel_widh,
0.0); // if none kernel pixel above - return null (here it is not needed)
ImagePlus imp_ill;
if (sensor_type==1) {
imp_ill = normalizeColorizeLWIRKernels(
title+"-ill", // String title,
dpixels[0], // double [] dpixels,
wh[0], // int width,
illustrationParameters.kernel_direct_lwir_min, // double mn,
illustrationParameters.kernel_direct_lwir_max, // double mx,
illustrationParameters.kernel_lwir_palette); // int palette);
} else {
imp_ill = normalizeColorizeEOKernels(
title+"-ill", // String title,
dpixels, // double [] dpixels,
wh[0], // int width,
illustrationParameters.kernel_direct_red_min, // double mnR,
illustrationParameters.kernel_direct_red_max, // double mxR,
illustrationParameters.kernel_direct_green_min, // double mnG,
illustrationParameters.kernel_direct_green_max, // double mxG,
illustrationParameters.kernel_direct_blue_min, // double mnB,
illustrationParameters.kernel_direct_blue_max); // double mnB,
}
// save result
EyesisCorrections.saveAndShow(
imp_ill,
dest_dir, // chn_ill_dir,
illustrationParameters.save_png,
false, // show
illustrationParameters.JPEG_quality, // <0 - keep current, 0 - force Tiff, >0 use for JPEG
0); // debug_level);
// return true; // temporarily
}
//int sensor_type = dcd.eyesisCameraParameters.getSensorType(nChn);
return true;
}
public boolean convertInverted(
final boolean [] selectedChannels,
final int src_step,
final String source_dir,
final String dest_dir,
final int [][] whall) { // null or per-channel
String invertedSuffix= eyesisAberrations.aberrationParameters.aberrationsSuffix; // .".psf-tiff";
File destDir= new File (dest_dir);
if (!destDir.exists()){
if (!destDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+dest_dir);
return false;
}
}
String [][] src_files = new String [selectedChannels.length][]; // should be one file per channel
for (int nChn = 0; nChn < src_files.length; nChn++) if (selectedChannels[nChn]) {
MultipleExtensionsFileFilter sourceFilter =
new MultipleExtensionsFileFilter("",new String[] {String.format("%02d", nChn)+invertedSuffix},"inverted kernels");
src_files[nChn] = (new File(source_dir)).list(sourceFilter); // are these full files?
}
// create list of partial kernel files
// partial-1623732618_112155-00.ppsf-tiff
for (int iChn = 0; iChn < src_files.length; iChn++) if (src_files[iChn]!=null) {
final int nChn=iChn;
int sensor_type = distortions.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.getSensorType(nChn);
int decimate = (sensor_type==1) ? illustrationParameters.kernel_decimate_inverse_lwir : illustrationParameters.kernel_decimate_inverse_eo;
int kernel_widh = (sensor_type==1) ? illustrationParameters.kernel_dia_inverse_lwir : illustrationParameters.kernel_dia_inverse_eo;
ImagePlus imp = new ImagePlus(source_dir+Prefs.getFileSeparator()+src_files[nChn][0]);
String title = imp.getTitle();
if (title.endsWith(invertedSuffix)) {
title = title.substring(0, title.lastIndexOf("."));
}
// int [] wh = new int [2];
int [] wh = (whall == null) ? new int [2]: whall[nChn];
double [][] dpixels = getDecimatedStack(
imp, // ImagePlus imp,
wh, // int [] wh, // will return width, height
src_step, // int src_step, // margins == src_step/2
decimate, // 1 - no decimation
kernel_widh,
0.0); // if none kernel pixel above - return null (here it is not needed)
ImagePlus imp_ill;
if (sensor_type==1) {
imp_ill = normalizeColorizeLWIRKernels(
title+"-ill", // String title,
dpixels[0], // double [] dpixels,
wh[0], // int width,
illustrationParameters.kernel_inverse_lwir_min, // double mn,
illustrationParameters.kernel_inverse_lwir_max, // double mx,
illustrationParameters.kernel_lwir_palette); // int palette);
} else {
imp_ill = normalizeColorizeEOKernels(
title+"-ill", // String title,
dpixels, // double [] dpixels,
wh[0], // int width,
illustrationParameters.kernel_inverse_red_min, // double mnR,
illustrationParameters.kernel_inverse_red_max, // double mxR,
illustrationParameters.kernel_inverse_green_min, // double mnG,
illustrationParameters.kernel_inverse_green_max, // double mxG,
illustrationParameters.kernel_inverse_blue_min, // double mnB,
illustrationParameters.kernel_inverse_blue_max); // double mnB,
}
// save result
EyesisCorrections.saveAndShow(
imp_ill,
dest_dir, // chn_ill_dir,
illustrationParameters.save_png,
false, // show
illustrationParameters.JPEG_quality, // <0 - keep current, 0 - force Tiff, >0 use for JPEG
0); // debug_level);
// return true; // temporarily
}
//int sensor_type = dcd.eyesisCameraParameters.getSensorType(nChn);
return true;
}
public double [][] getDecimatedStack(
ImagePlus imp,
int [] wh, // will return width, height. If wh[0]!=0, will adjust to it
int src_step, // margins == src_step/2
int decimate, // 1 - no decimation
int out_kernel_widh,
double mingood){ // minimal value to ne considered non-empty kernel
int width = imp.getWidth();
int height = imp.getHeight();
ImageStack stack=imp.getStack();
float [][] pixels=new float[stack.getSize()][]; // now - 8 (x,y,u,v,contrast, vignR,vignG,vignB
for (int i=0;i<pixels.length;i++) pixels[i]= (float[]) stack.getPixels(i+1); // pixel X : negative - no grid here
int khor = width / src_step; // number of available kernels in a row
int kvert = height / src_step; // number of available kernels in a column
int thor = khor / decimate;
int tvert = kvert / decimate;
// int margin_left = (src_step + (thor % decimate)) / 2; // with decimation will be increased to make more center-symmetrical
// int margin_top = (src_step +(tvert % decimate)) / 2;
// int margin_left = src_step/2 + src_step*((thor % decimate) / 2); // with decimation will be increased to make more center-symmetrical
// int margin_top = src_step/2 + src_step*((tvert % decimate) / 2);
if ((wh[0] > 0) && (wh[1]>0)) {
thor = wh[0] / out_kernel_widh;
tvert = wh[1] / out_kernel_widh;
}
int margin_left = src_step/2 + src_step * ((khor - ((thor-1) * decimate + 1))/2);
int margin_top = src_step/2 + src_step * ((kvert - ((tvert -1) * decimate + 1))/2);
wh[0] = thor * out_kernel_widh;
wh[1] = tvert * out_kernel_widh;
double [][] rslt = new double [pixels.length][wh[0]*wh[1]];
// for (int i = 0; i < pixels.length; i++) {
// Arrays.fill(rslt[i], Double.NaN);
// }
boolean nonzero = mingood <= 0; // 0 - do not check
for (int slice=0; slice < pixels.length; slice++) {
for (int tileY=0; tileY < tvert; tileY ++) {
int sbase = width* (margin_top + tileY*src_step*decimate - out_kernel_widh / 2);
int dbase = wh[0]* (tileY*out_kernel_widh);
for (int tileX=0; tileX < thor; tileX ++) {
int sindex = sbase + (margin_left + tileX*src_step*decimate - out_kernel_widh / 2);
int dindex = dbase + (tileX * out_kernel_widh);
for (int i = 0; i < out_kernel_widh; i++) {
if (!nonzero) {
for (int j = 0; j < out_kernel_widh; j++) {
double d = pixels[slice][sindex++];
rslt[slice][dindex++] = d;
nonzero |= (d > mingood);
}
} else { // no need to check, faster
for (int j = 0; j < out_kernel_widh; j++) {
rslt[slice][dindex++] = pixels[slice][sindex++];
}
}
sindex+=(width-out_kernel_widh);
dindex+=(wh[0]-out_kernel_widh);
}
}
}
}
// (new ShowDoubleFloatArrays()).showArrays(rslt, wh[0],wh[1], true,"kernels_compressed");
return nonzero ? rslt : null;
}
public ImagePlus normalizeColorizeLWIRKernels(
String title,
double [] dpixels,
int width,
double mn,
double mx,
int palette) {
double [][] pseudo_pixels = new double [4] [dpixels.length];
ThermalColor tc = new ThermalColor(
illustrationParameters.getPalette(), // public int lwir_palette = 0; // 0 - white - hot, 1 - black - hot, 2+ - colored
mn,
mx,
255.0);
for (int i = 0; i < dpixels.length; i++) {
double [] rgb = tc.getRGB((double) dpixels[i]);
pseudo_pixels[0][i] = rgb[0]; // red
pseudo_pixels[1][i] = rgb[1]; // green
pseudo_pixels[2][i] = rgb[2]; // blue
pseudo_pixels[3][i] = 1.0; // alpha
}
String [] rgb_titles = {"red","green","blue","alpha"};
ImageStack stack = (new ShowDoubleFloatArrays()).makeStack(
pseudo_pixels,
width,
dpixels.length/width,
rgb_titles,
true); // replace NaN with 0.0
ImagePlus imp = EyesisCorrections.convertRGBAFloatToRGBA32(
stack, // ImageStack stackFloat, //r,g,b,a
// name+"ARGB"+suffix, // String title,
title, // String title,
0.0, // double r_min,
255.0, // double r_max,
0.0, // double g_min,
255.0, // double g_max,
0.0, // double b_min,
255.0, // double b_max,
0.0, // double alpha_min,
1.0); // double alpha_max)
return imp;
}
public ImagePlus normalizeColorizeEOKernels(
String title,
double [][] dpixels, // slices: R,B,G
int width,
double mnR,
double mxR,
double mnG,
double mxG,
double mnB,
double mxB) {
double [][] pseudo_pixels = new double [4] [dpixels[0].length];
double kR = 255.0/(mxR-mnR);
double kG = 255.0/(mxG-mnG);
double kB = 255.0/(mxB-mnB);
for (int i = 0; i < dpixels[0].length; i++) {
pseudo_pixels[0][i] = kR * (dpixels[0][i] - mnR); // red
pseudo_pixels[1][i] = kG * (dpixels[2][i] - mnG); // green
pseudo_pixels[2][i] = kB * (dpixels[1][i] - mnB); // blue
pseudo_pixels[3][i] = 1.0; // alpha
}
String [] rgb_titles = {"red","green","blue","alpha"};
ImageStack stack = (new ShowDoubleFloatArrays()).makeStack(
pseudo_pixels,
width,
dpixels[0].length/width,
rgb_titles,
true); // replace NaN with 0.0
ImagePlus imp = EyesisCorrections.convertRGBAFloatToRGBA32(
stack, // ImageStack stackFloat, //r,g,b,a
// name+"ARGB"+suffix, // String title,
title, // String title,
0.0, // double r_min,
255.0, // double r_max,
0.0, // double g_min,
255.0, // double g_max,
0.0, // double b_min,
255.0, // double b_max,
0.0, // double alpha_min,
1.0); // double alpha_max)
return imp;
}
public boolean convertCapturedFiles() {
long startTime=System.nanoTime(); // restart timer after possible interactive dialogs
final boolean [] selectedChannels = illustrationParameters.getSelectedChannels();
final CapturedScene [] captured_scenes = listCapturedScenes(
eyesisAberrations.aberrationParameters.capturedDirectory, // String captured_path,
illustrationParameters.min_ts,// double min_ts,
illustrationParameters.max_ts,// double max_ts,
illustrationParameters.captures_all_lwir,
illustrationParameters.captures_all_eo,
illustrationParameters.captures_all);
// optionally perform balancing
double [][] windows = null;
if (illustrationParameters.calib_offs_gain) {
CapturedScene [] balancing_scenes = captured_scenes;
if ( (illustrationParameters.calib_offs_gain_ts < illustrationParameters.min_ts) ||
((illustrationParameters.calib_offs_gain_ts + illustrationParameters.calib_offs_gain_dur) > illustrationParameters.max_ts)) {
balancing_scenes = listCapturedScenes(
eyesisAberrations.aberrationParameters.capturedDirectory, // String captured_path,
illustrationParameters.calib_offs_gain_ts,// double min_ts,
illustrationParameters.calib_offs_gain_ts + illustrationParameters.calib_offs_gain_dur,// double max_ts,
illustrationParameters.captures_all_lwir,
illustrationParameters.captures_all_eo,
illustrationParameters.captures_all);
}
// read once scene to find width/height
ImagePlus[] imps = getImagesMultithreaded(
balancing_scenes[0].images, // final String [] image_paths,
(1 << LwirReaderParameters.TYPE_LWIR), // final int types_mask, // +1 - TYPE_EO, +2 - TYPE_LWIR
null); // final double [][] pixels) // if not null - will fill
windows = getWindows (imps,illustrationParameters.auto_range_wnd_type);
// (new ShowDoubleFloatArrays()).showArrays(windows, width, height, true, "windows");
double [][] offs_gains = balanceOffsGains(
balancing_scenes, // CapturedScene [] scenes,
windows, // double [][] window,
illustrationParameters.calib_offs_gain_ts,// double min_ts,
illustrationParameters.calib_offs_gain_ts + illustrationParameters.calib_offs_gain_dur,// double max_ts,
illustrationParameters.min_sigma, // double min_sigma, // do not use images with small sigma (noise will be a dominant factor
illustrationParameters.noise_sigma); // noise_sigma); // estimate of sigma in noise-only images (OK to use 0)
illustrationParameters.setLWIROffsetGains(offs_gains); // will not overwrite unused channels
// return false; // temporarily
}
double [][] offs_gains = illustrationParameters.getLWIROffsetGains();
// double [][] illustrationParameters.getLWIROffsetGains() 16-element long, lwir - only
// create directories before threads
for (int nChn = 0; nChn < selectedChannels.length; nChn++) if (selectedChannels[nChn] && (lwirReaderParameters.getTypeMap()[nChn]==LwirReaderParameters.TYPE_LWIR)) {
String footage_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory+Prefs.getFileSeparator()+FOOTAGE_DIR;
String chn_foot_dir = footage_dir+Prefs.getFileSeparator()+ illustrationParameters.getChannelPrefix()+String.format("%02d", nChn);
// create directory if it does not exist
File destDir= new File (chn_foot_dir);
if (!destDir.exists()){
if (!destDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+chn_foot_dir);
continue;
}
}
}
final double [][] dpixels = new double [selectedChannels.length][];
double [][] min_max = new double [selectedChannels.length][];
double percentile_min = illustrationParameters.percentile_min;
double percentile_max = illustrationParameters.percentile_max;
double max_range = illustrationParameters.max_range;
double hot_importance = illustrationParameters.hot_importance;
boolean auto_range = illustrationParameters.auto_range;
boolean auto_lim_range = illustrationParameters.auto_lim_range;
double autorange_offs_up = illustrationParameters.autorange_offs_up; // 0.2; // shift range up (fraction of new value)
double autorange_offs_down = illustrationParameters.autorange_offs_down; // 0.05; // shift range down (fraction of new value)
double autorange_range_up = illustrationParameters.autorange_range_up; // 0.1; // increase range (fraction of new value)
double autorange_range_down = illustrationParameters.autorange_range_down; // 0.02; // decrease range (fraction of new value)
final int captures_palette = illustrationParameters.captures_palette;
double prev_lim_high = 0;
double prev_lim_range = 0;
for (int iScene = 0; iScene < captured_scenes.length; iScene++) {
final int nScene = iScene;
final ImagePlus[] imps = getImagesMultithreaded(
captured_scenes[nScene].images, // final String [] image_paths,
(1 << LwirReaderParameters.TYPE_LWIR), // final int types_mask, // +1 - TYPE_EO, +2 - TYPE_LWIR
dpixels); // final double [][] pixels) // if not null - will fill
// TODO: Make sure all images are read in, continue if any failed !!!\
boolean has_bad_images = false;
int sensor_types[] = lwirReaderParameters.getTypeMap(); // eo - 0, lwir - 1
for (int nChn = 0; nChn < captured_scenes[nScene].images.length; nChn++) {
if ((captured_scenes[nScene].images[nChn] != null) && ((sensor_types[nChn] & (1 << LwirReaderParameters.TYPE_LWIR)) != 0) && (imps[nChn] == null)) {
has_bad_images = true;
System.out.println("***** Failed to read image "+captured_scenes[nScene].images[nChn]+", will skip this scene *****");
}
}
if (has_bad_images) {
continue;
}
// double lim_low = illustrationParameters.lwir_ranges[nChn][0];
// double lim_high = illustrationParameters.lwir_ranges[nChn][1];
final double [][] lim_low_high = new double [illustrationParameters.lwir_ranges.length][2];
for (int i = 0; i < lim_low_high.length; i++) {
lim_low_high[i][0] = illustrationParameters.lwir_ranges[i][0]; // per channel min/max limits
lim_low_high[i][1] = illustrationParameters.lwir_ranges[i][1];
}
if (auto_range) {
if (windows == null) {
windows = getWindows (imps,illustrationParameters.auto_range_wnd_type);
}
double [][] histograms = getMultiHistograms( // calculate min, max and normalized histogram (assuming input data are actually integer
dpixels, // final double [][] dpixels,
windows, // final double [][] windows,
min_max); // final double [][] min_max) // histogram bin [0] corresponds to [(int) min, (int) min +1)
// Normalize and combine min_max
double mn=Double.NaN, mx= Double.NaN;
for (int nChn = 0; nChn < min_max.length; nChn++) if (min_max[nChn] != null) {
double scaled_mn = min_max[nChn][0]/offs_gains[nChn][1] - offs_gains[nChn][0];
double scaled_mx = min_max[nChn][1]/offs_gains[nChn][1] - offs_gains[nChn][0];
if (!(mn <= scaled_mn)) mn = scaled_mn;
if (!(mx >= scaled_mx)) mx = scaled_mx;
}
// now got common min and max
int ioffs = (int) mn - 1; // extra 1 to avoid checking limits
int hist_len = (int) Math.ceil(mx) - ioffs +1; //range is +2 to avoid checkin limits
double [] histogram = new double[hist_len];
for (int nChn = 0; nChn < min_max.length; nChn++) if (min_max[nChn] != null) {
double scale = 1.0/offs_gains[nChn][1];
// double offs_add = -offs_gains[nChn][0] - ioffs + 1; // to get common bin >
double offs_add = (((int) min_max[nChn][0])*scale - offs_gains[nChn][0] - (ioffs+1));
for (int i = 0; i < histograms[nChn].length; i++) {
int b = (int) (offs_add + i* scale);
histogram[b]+=histograms[nChn][i];
}
}
double sum_hist = 0.0;
for (int i = 0; i < histogram.length; i++) {
sum_hist += histogram[i];
}
// normailize, sum(hist) == 1.0;
double k = 1.0/sum_hist;
for (int b = 0; b < histogram.length; b++) {
histogram[b] *= k;
}
// Find desired limits (or low and range)
double lim_low = ioffs; // first bin
double lim_high = ioffs + histogram.length -1; // last bin
if ((percentile_min + percentile_max) >= 1.0) {
percentile_min /= (percentile_min + percentile_max);
percentile_max = 1.0 - percentile_min;
}
if (percentile_min > 0) {
double pix_low = percentile_min; // * ipixels.length *
double cumul = 0.0;
int i;
for (i = 0; i < histogram.length; i++) {
cumul += histogram[i];
if (cumul > pix_low) {
break;
}
}
if (i >=histogram.length) { // should never happen
lim_low = ioffs + histogram.length -1;
} else {
double lo = cumul - histogram[i];
double kk = (pix_low - lo) / histogram[i];
lim_low = ioffs + i - 0.5 + kk;
}
}
if (percentile_max > 0) {
double pix_hi = percentile_max; // * ipixels.length
double cumul = 0.0;
int i;
for (i = histogram.length - 1; i >= 0; i--) {
cumul += histogram[i];
if (cumul > pix_hi) {
break;
}
}
if (i < 0) { // should never happen
lim_high = ioffs;
} else {
double lo = cumul - histogram[i];
double kk = (pix_hi - lo) / histogram[i];
lim_high = ioffs + i + 0.5 - kk;
}
}
if (auto_lim_range && ((lim_high - lim_low) > max_range)) {
double [] weighted_cumul = new double [histogram.length];
double wc = 0.0;
for (int i = 0; i < histogram.length; i++) {
double w = i + (1.0 - hot_importance) * lim_low;
wc+= w * histogram[i];
weighted_cumul[i] = wc;
}
int irange = (int) max_range;
int ibest = 0;
double best = weighted_cumul[irange];
for (int i = 1; i < (histogram.length - irange); i++) {
double w = weighted_cumul[irange + i] - weighted_cumul[i];
if (w > best) {
best = w;
ibest = i;
}
}
lim_low = ioffs + ibest;
lim_high = lim_low + irange;
}
double lim_range = lim_high - lim_low;
if (nScene > 0) { // lpf
if (lim_high > prev_lim_high) {
lim_high = lim_high * autorange_offs_up + prev_lim_high * (1.0 - autorange_offs_up);
} else {
lim_high = lim_high * autorange_offs_down + prev_lim_high * (1.0 - autorange_offs_down);
}
if (lim_range > prev_lim_range) {
lim_range = lim_range * autorange_range_up + prev_lim_range * (1.0 - autorange_range_up);
} else {
lim_range = lim_range * autorange_range_down + prev_lim_range * (1.0 - autorange_range_down);
}
lim_low = lim_high - lim_range;
}
prev_lim_high = lim_high;
prev_lim_range = lim_range;
// Now apply shifts/scales to find individual limits
for (int nChn = 0; nChn < lim_low_high.length; nChn++) {
lim_low_high[nChn][0] = (lim_low + offs_gains[nChn][0]) * offs_gains[nChn][1];
lim_low_high[nChn][1] = (lim_high + offs_gains[nChn][0]) * offs_gains[nChn][1];
}
System.out.println(String.format("---- Scene: %s, lim_low=%8.2f, lim_high=%8.2f, lim_range=%8.2f",
captured_scenes[nScene].name,lim_low,lim_high,lim_range));
} // if (auto_range)
final Thread[] threads = newThreadArray(MAX_THREADS);
final AtomicInteger indxAtomic = new AtomicInteger(0);
// final ImagePlus[] imp_array = new ImagePlus[image_paths.length];
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nChn = indxAtomic.getAndIncrement(); nChn < imps.length; nChn = indxAtomic.getAndIncrement()) if (imps[nChn] != null) {
// imp_array[nChn] = null; // important to set for unused sensor types
// dpixels
int width = imps[nChn].getWidth();
int height = imps[nChn].getHeight();
String title = imps[nChn].getTitle();
if (title.lastIndexOf(".") > 0) {
title = title.substring(0, title.lastIndexOf("."));
}
if (title.lastIndexOf(Prefs.getFileSeparator()) > 0) {
title = title.substring(title.lastIndexOf(Prefs.getFileSeparator())+1);
}
String title_footage = title+"-footage";
ImageStack stack = null;
double [][] pseudo_pixels;
// int line_width = 1; // illustrationParameters.getLineWidthLwir();;
pseudo_pixels = new double [4] [dpixels[nChn].length];
ThermalColor tc = new ThermalColor(
captures_palette, // public int lwir_palette = 0; // 0 - white - hot, 1 - black - hot, 2+ - colored
lim_low_high[nChn][0],
lim_low_high[nChn][1],
255.0);
for (int i = 0; i < dpixels[nChn].length; i++) {
double [] rgb = tc.getRGB(dpixels[nChn][i]);
pseudo_pixels[0][i] = rgb[0]; // red
pseudo_pixels[1][i] = rgb[1]; // green
pseudo_pixels[2][i] = rgb[2]; // blue
pseudo_pixels[3][i] = 1.0; // alpha
}
String [] rgb_titles = {"red","green","blue","alpha"};
stack = (new ShowDoubleFloatArrays()).makeStack(
pseudo_pixels, // iclt_data,
width, // (tilesX + 0) * clt_parameters.transform_size,
height, // (tilesY + 0) * clt_parameters.transform_size,
rgb_titles, // or use null to get chn-nn slice names
true); // replace NaN with 0.0
ImagePlus imp_out = EyesisCorrections.convertRGBAFloatToRGBA32(
stack, // ImageStack stackFloat, //r,g,b,a
// name+"ARGB"+suffix, // String title,
title_footage, // String title,
0.0, // double r_min,
255.0, // double r_max,
0.0, // double g_min,
255.0, // double g_max,
0.0, // double b_min,
255.0, // double b_max,
0.0, // double alpha_min,
1.0); // double alpha_max)
if (imp_out == null) {
continue;
}
if (illustrationParameters.captures_annotate) {
String scene_title = captured_scenes[nScene].name;
if (scene_title.lastIndexOf(Prefs.getFileSeparator()) > 0) {
scene_title = scene_title.substring(scene_title.lastIndexOf(Prefs.getFileSeparator())+1);
}
ImageProcessor ip = imp_out.getProcessor();
int posX=521;
int posY=513;
Font font = new Font("Monospaced", Font.PLAIN, 12);
ip.setColor(illustrationParameters.color_annotate); // Color.BLUE);
ip.setFont(font);
ip.drawString(scene_title, posX, posY,Color.BLACK);
}
String footage_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory+Prefs.getFileSeparator()+FOOTAGE_DIR;
String chn_foot_dir = footage_dir+Prefs.getFileSeparator()+ illustrationParameters.getChannelPrefix()+String.format("%02d", nChn);
// create directory if it does not exist
File destDir= new File (chn_foot_dir);
if (!destDir.exists()){
if (!destDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+chn_foot_dir);
continue;
}
}
EyesisCorrections.saveAndShow(
imp_out,
chn_foot_dir,
illustrationParameters.save_png,
false, // show
illustrationParameters.JPEG_quality, // <0 - keep current, 0 - force Tiff, >0 use for JPEG
((nChn==0)?1:0)); // print only for channel 0
}
}
};
}
startAndJoin(threads);
} // for (int nScene = 0; nScene < captured_scenes.length; nScene++) {
/*
final Thread[] threads = newThreadArray(MAX_THREADS);
final AtomicInteger indxAtomic = new AtomicInteger(0);
for (int iChn = 0; iChn < selectedChannels.length; iChn++) if (selectedChannels[iChn] && (lwirReaderParameters.getTypeMap()[iChn]==LwirReaderParameters.TYPE_LWIR)) {
final int nChn=iChn;
indxAtomic.set(0);
// Create directory before threads
String footage_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory+Prefs.getFileSeparator()+FOOTAGE_DIR;
String chn_foot_dir = footage_dir+Prefs.getFileSeparator()+ illustrationParameters.getChannelPrefix()+String.format("%02d", nChn);
// create directory if it does not exist
File destDir= new File (chn_foot_dir);
if (!destDir.exists()){
if (!destDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+chn_foot_dir);
continue;
}
}
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
ImagejJp4Tiff imagejJp4Tiff = new ImagejJp4Tiff();
for (int nScene = indxAtomic.getAndIncrement(); nScene < captured_scenes.length; nScene = indxAtomic.getAndIncrement()) {
ImagePlus imp_out = convertCapturedLWIR(
imagejJp4Tiff, // ImagejJp4Tiff imagejJp4Tiff,,
captured_scenes[nScene].images[nChn], // String src_path,
illustrationParameters.lwir_ranges[nChn][0], // double abs_min,
illustrationParameters.lwir_ranges[nChn][1], // double abs_max,
illustrationParameters.percentile_min, // double percentile_min,
illustrationParameters.percentile_max, // double percentile_max,
illustrationParameters.max_range, // double max_range,
illustrationParameters.hot_importance, // double hot_importance,
illustrationParameters.auto_range, // boolean auto_range,
illustrationParameters.auto_lim_range, // boolean auto_lim_range,
illustrationParameters.captures_annotate, // boolean captures_annotate,
illustrationParameters.color_annotate, // Color color_annotate,
illustrationParameters.captures_palette); // int captures_palette)
if (imp_out == null) {
continue;
}
if (illustrationParameters.captures_annotate) {
String scene_title = captured_scenes[nScene].name;
if (scene_title.lastIndexOf(Prefs.getFileSeparator()) > 0) {
scene_title = scene_title.substring(scene_title.lastIndexOf(Prefs.getFileSeparator())+1);
}
ImageProcessor ip = imp_out.getProcessor();
int posX=521;
int posY=513;
Font font = new Font("Monospaced", Font.PLAIN, 12);
ip.setColor(illustrationParameters.color_annotate); // Color.BLUE);
ip.setFont(font);
ip.drawString(scene_title, posX, posY,Color.BLACK);
}
String footage_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory+Prefs.getFileSeparator()+FOOTAGE_DIR;
String chn_foot_dir = footage_dir+Prefs.getFileSeparator()+ illustrationParameters.getChannelPrefix()+String.format("%02d", nChn);
// create directory if it does not exist
File destDir= new File (chn_foot_dir);
if (!destDir.exists()){
if (!destDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+chn_foot_dir);
continue;
}
}
EyesisCorrections.saveAndShow(
imp_out,
chn_foot_dir,
illustrationParameters.save_png,
false, // show
illustrationParameters.JPEG_quality, // <0 - keep current, 0 - force Tiff, >0 use for JPEG
0); // debug_level);
}
}
};
}
startAndJoin(threads);
}
*/
System.out.println("All done in "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+" sec.");
return true;
}
ImagePlus convertCapturedLWIR(
ImagejJp4Tiff imagejJp4Tiff,
String src_path,
double abs_min,
double abs_max,
double percentile_min,
double percentile_max,
double max_range,
double hot_importance,
boolean auto_range,
boolean auto_lim_range,
boolean captures_annotate,
Color color_annotate,
int captures_palette) {
// read source image
ImagePlus imp_src = null;
try {
imp_src= imagejJp4Tiff.readTiffJp4(src_path);
} catch (IOException e) {
System.out.println("convertCapturedLWIR IOException " + src_path);
} catch (FormatException e) {
System.out.println("convertCapturedLWIR FormatException " + src_path);
}
if (imp_src == null) {
return null;
}
int width = imp_src.getWidth();
int height = imp_src.getHeight();
String title = imp_src.getTitle();
if (title.lastIndexOf(".") > 0) {
title = title.substring(0, title.lastIndexOf("."));
}
if (title.lastIndexOf(Prefs.getFileSeparator()) > 0) {
title = title.substring(title.lastIndexOf(Prefs.getFileSeparator())+1);
}
String title_footage = title+"-footage";
double lim_low = abs_min;
double lim_high = abs_max;
float [] fpixels = (float[]) imp_src.getProcessor().getPixels();
if (auto_range) {
// got float processor, but actual values arde int16
int imin = 0xffff;
int imax = 0;
int [] ipixels = new int [fpixels.length];
for (int i = 0; i < ipixels.length; i++) {
int d = (int) fpixels[i];
if (d < imin) imin=d;
else if (d > imax) imax=d;
ipixels[i] = d;
}
int [] hist = new int [imax -imin +1];
Arrays.fill(hist, 0);
for (int i = 0; i < ipixels.length; i++) {
hist[ipixels[i]-imin]++;
}
lim_low = imin;
lim_high = imax;
if ((percentile_min + percentile_max) >= 1.0) {
percentile_min /= (percentile_min + percentile_max);
percentile_max = 1.0 - percentile_min;
}
if (percentile_min > 0) {
double pix_low = ipixels.length * percentile_min;
double cumul = 0.0;
int i;
for (i = 0; i < hist.length; i++) {
cumul += hist[i];
if (cumul > pix_low) {
break;
}
}
if (i >=hist.length) { // should never happen
lim_low = imax;
} else {
double lo = cumul - hist[i];
double k = (pix_low - lo) / hist[i];
lim_low = imin + i - 0.5 + k;
}
}
if (percentile_max > 0) {
double pix_hi = ipixels.length * percentile_max;
double cumul = 0.0;
int i;
for (i = hist.length - 1; i >= 0; i--) {
cumul += hist[i];
if (cumul > pix_hi) {
break;
}
}
if (i < 0) { // should never happen
lim_high = imin;
} else {
double lo = cumul - hist[i];
double k = (pix_hi - lo) / hist[i];
lim_high = imin + i + 0.5 - k;
}
}
if (auto_lim_range && ((lim_high - lim_low) > max_range)) {
double [] weighted_cumul = new double [hist.length];
double wc = 0.0;
for (int i = 0; i < hist.length; i++) {
double w = i + (1.0 - hot_importance) * lim_low;
wc+= w * hist[i];
weighted_cumul[i] = wc;
}
int irange = (int) max_range;
int ibest = 0;
double best = weighted_cumul[irange];
for (int i = 1; i < (hist.length - irange); i++) {
double w = weighted_cumul[irange + i] - weighted_cumul[i];
if (w > best) {
best = w;
ibest = i;
}
}
lim_low = imin + ibest;
lim_high = lim_low + irange;
}
}
ImageStack stack = null;
double [][] pseudo_pixels;
// int line_width = 1; // illustrationParameters.getLineWidthLwir();;
pseudo_pixels = new double [4] [fpixels.length];
ThermalColor tc = new ThermalColor(
captures_palette, // public int lwir_palette = 0; // 0 - white - hot, 1 - black - hot, 2+ - colored
lim_low,
lim_high,
255.0);
for (int i = 0; i < fpixels.length; i++) {
double [] rgb = tc.getRGB((double) fpixels[i]);
pseudo_pixels[0][i] = rgb[0]; // red
pseudo_pixels[1][i] = rgb[1]; // green
pseudo_pixels[2][i] = rgb[2]; // blue
pseudo_pixels[3][i] = 1.0; // alpha
}
String [] rgb_titles = {"red","green","blue","alpha"};
stack = (new ShowDoubleFloatArrays()).makeStack(
pseudo_pixels, // iclt_data,
width, // (tilesX + 0) * clt_parameters.transform_size,
height, // (tilesY + 0) * clt_parameters.transform_size,
rgb_titles, // or use null to get chn-nn slice names
true); // replace NaN with 0.0
ImagePlus imp_footage = EyesisCorrections.convertRGBAFloatToRGBA32(
stack, // ImageStack stackFloat, //r,g,b,a
// name+"ARGB"+suffix, // String title,
title_footage, // String title,
0.0, // double r_min,
255.0, // double r_max,
0.0, // double g_min,
255.0, // double g_max,
0.0, // double b_min,
255.0, // double b_max,
0.0, // double alpha_min,
1.0); // double alpha_max)
return imp_footage;
}
class CapturedScene{
String name;
String[] images; // indexed by channel
double ts;
CapturedScene (String name, String [] images, double ts){
this.name = name;
this.images = images;
this.ts = ts;
}
}
CapturedScene [] listCapturedScenes(
String captured_path,
double min_ts,
double max_ts,
boolean captures_all_lwir,
boolean captures_all_eo,
boolean captures_all) {
int sensor_types[] = lwirReaderParameters.getTypeMap(); // eo - 0, lwir - 1
int num_sensors[] = {0,0};
int num_all_sensors = 0;
for (int st:sensor_types) {
num_sensors[st]++;
num_all_sensors++;
}
File dFile=new File(captured_path);
File[] scenesFiles=dFile.listFiles(); // all files
String[] scenePaths = new String [scenesFiles.length];
for (int i = 0; i < scenesFiles.length; i++) {
scenePaths[i] = scenesFiles[i].getPath();
}
Arrays.sort(scenePaths);
// Filter by number of files
ArrayList<CapturedScene> filteredScenesList = new ArrayList<CapturedScene>();
// for (File sceneDir: scenesFiles) {
for (String scenePath: scenePaths) {
int basename_start = scenePath.lastIndexOf(Prefs.getFileSeparator());
if (basename_start >= 0) {
basename_start++;
} else {
basename_start = 0;
}
// double ts = Double.parseDouble(sceneDir.getPath().replace('_','.'));
double ts = Double.parseDouble(scenePath.substring(basename_start).replace('_','.'));
if (ts < min_ts) {
continue;
}
if (ts > max_ts) {
continue;
}
int ns[] = {0,0};
int nsa = 0;
File sceneDir = new File(scenePath);
File [] sFiles = sceneDir.listFiles();
for (File ifile: sFiles) {
int chn = DistortionCalibrationData.getChannelFromPath(ifile.getPath());
ns[sensor_types[chn]]++;
nsa++;
}
if (captures_all && (nsa < num_all_sensors)) {
continue;
}
if (captures_all_lwir &&
// (ns[LwirReaderParameters.TYPE_LWIR] > 0 ) &&
(ns[LwirReaderParameters.TYPE_LWIR] < num_sensors[LwirReaderParameters.TYPE_LWIR])) {
continue;
}
if (captures_all_eo &&
(ns[LwirReaderParameters.TYPE_EO] > 0 ) &&
(ns[LwirReaderParameters.TYPE_EO] < num_sensors[LwirReaderParameters.TYPE_EO])) {
continue;
}
String [] images = new String [num_all_sensors];
for (File ifile: sFiles) {
int chn = DistortionCalibrationData.getChannelFromPath(ifile.getPath());
images[chn] = ifile.getPath();
ns[sensor_types[chn]]++;
}
filteredScenesList.add(new CapturedScene(sceneDir.getPath(), images, ts));
}
System.out.println("Selected "+(filteredScenesList.size())+" scenes");
return filteredScenesList.toArray(new CapturedScene[0]);
}
double [][] getNewMeanSigma(
final double [][] pixels,
final double [][] wnd,
final double noise_sigma) // estimation of sigma with noise only
{
final double [][] new_mean_sigma = new double [pixels.length][];
final Thread[] threads = newThreadArray(MAX_THREADS);
final AtomicInteger indxAtomic = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
for (int nChn = indxAtomic.getAndIncrement(); nChn < new_mean_sigma.length; nChn = indxAtomic.getAndIncrement()) {
double [] pix = pixels[nChn];
if (pix != null) {
double s0=0.0, sx=0.0, sx2=0.0;
for (int i = 0; i < pix.length; i++) {
double w = (wnd == null)? 1.0:wnd[nChn][i];
s0+= w;
double d = pix[i];
double wx = w * d;
sx += wx;
sx2+= wx * pix[i];
}
new_mean_sigma[nChn] = new double[2];
new_mean_sigma[nChn][0] = sx/s0; // mean
double sigma2 = (s0*sx2 - sx*sx) /s0/s0; // - (noise_sigma * noise_sigma);
if (noise_sigma > 0.0) {
sigma2 -= noise_sigma * noise_sigma;
sigma2 = Math.max(sigma2, 0.0);
}
new_mean_sigma[nChn][1] = Math.sqrt(sigma2); // sigma
}
}
}
};
}
startAndJoin(threads);
return new_mean_sigma;
}
ImagePlus[] getImagesMultithreaded(
final String [] image_paths,
final int types_mask, // +1 - TYPE_EO, +2 - TYPE_LWIR
final double [][] pixels) // if not null - will fill
{
int sensor_types[] = lwirReaderParameters.getTypeMap(); // eo - 0, lwir - 1
final Thread[] threads = newThreadArray(MAX_THREADS);
final AtomicInteger indxAtomic = new AtomicInteger(0);
final ImagePlus[] imp_array = new ImagePlus[image_paths.length];
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
ImagejJp4Tiff imagejJp4Tiff = new ImagejJp4Tiff();
for (int nChn = indxAtomic.getAndIncrement(); nChn < image_paths.length; nChn = indxAtomic.getAndIncrement()) {
imp_array[nChn] = null; // important to set for unused sensor types
if (((1 << sensor_types[nChn]) & types_mask) != 0) {
try {
imp_array[nChn]= imagejJp4Tiff.readTiffJp4(image_paths[nChn]);
} catch (IOException e) {
System.out.println("getImagesMultithreaded IOException " + image_paths[nChn]);
} catch (FormatException e) {
System.out.println("getImagesMultithreaded FormatException " + image_paths[nChn]);
}
if (imp_array[nChn] != null) {
if (pixels != null) {
float [] fpixels = (float[]) imp_array[nChn].getProcessor().getPixels();
pixels[nChn] = new double[fpixels.length];
for (int i = 0; i < fpixels.length; i++) {
pixels[nChn][i] = fpixels[i];
}
}
}
}
}
}
};
}
startAndJoin(threads);
return imp_array;
}
double [][] getMultiHistograms( // calculate min, max and normalized histogram (assuming input data are actually integer
final double [][] dpixels,
final double [][] windows,
final double [][] min_max) // histogram bin [0] corresponds to [(int) min, (int) min +1)
{
final double [][] histograms = new double[dpixels.length][];
final Thread[] threads = newThreadArray(MAX_THREADS);
final AtomicInteger indxAtomic = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
@Override
public void run() {
ImagejJp4Tiff imagejJp4Tiff = new ImagejJp4Tiff();
for (int nChn = indxAtomic.getAndIncrement(); nChn < dpixels.length; nChn = indxAtomic.getAndIncrement()) {
double [] pixels = dpixels[nChn];
if (pixels == null) {
histograms[nChn] = null;
min_max[nChn] = null;
} else {
double [] window = windows[nChn];
double mn = pixels[0], mx = pixels[0];
for (int i = 1; i < pixels.length; i++) {
if (mn > pixels[i]) mn = pixels[i];
else if (mx < pixels[i]) mx = pixels[i];
}
int offs = (int) mn;
int hist_len = (int) Math.ceil(mx) - offs + 1;
double sum_hist = 0.0;
double [] histogram = new double[hist_len];
for (int i = 0; i < pixels.length; i++) {
int b = (int) pixels[i] - offs;
double w = window[i];
histogram[b] += w;
sum_hist += w;
}
// noprmailize, sum(hist) == 1.0;
double k = 1.0/sum_hist;
for (int b = 0; b < histogram.length; b++) {
histogram[b] *= k;
}
histograms[nChn] = histogram;
min_max[nChn] = new double[] {mn,mx};
}
}
}
};
}
startAndJoin(threads);
return histograms;
}
double [][] balanceOffsGains(
CapturedScene [] scenes,
double [][] window,
double min_ts, // if not overlapping, will need separate listCapturedScenes() run
double max_ts,
double min_sigma, // do not use images with small sigma (noise will be a dominant factor
// so use large thresholds/good contrast images
double noise_sigma) { // estimate of sigma in noise-only images (OK to use 0)
// double [][] offs_scale;// [chn][0] - offset to subtract to normalize, [chn][1] - scale to divide by to normalize
int sensor_types[] = lwirReaderParameters.getTypeMap(); // eo - 0, lwir - 1
double [][] offs_scale = new double [sensor_types.length][2];
int num_imgs[] = new int[sensor_types.length];
double [][] dpixels = new double [sensor_types.length][];
for (CapturedScene scene: scenes) {
if ((scene.ts >= min_ts) && (scene.ts <= max_ts)) {
ImagePlus [] imps = getImagesMultithreaded(
scene.images, // final String [] image_paths,
(1 << LwirReaderParameters.TYPE_LWIR), // final int types_mask, // +1 - TYPE_EO, +2 - TYPE_LWIR
dpixels); // final double [][] pixels) // if not null - will fill
double [][] mean_sigmas = getNewMeanSigma(
dpixels, // final double [][] pixels,
window, // final double [] wnd);
noise_sigma); // final double noise_sigma);
for (int i = 0; i < mean_sigmas.length; i++) {
if (mean_sigmas[i] != null) {
if (mean_sigmas[i][1] >= min_sigma) {
num_imgs[i]++;
offs_scale[i][0] += mean_sigmas[i][0];
offs_scale[i][1] += mean_sigmas[i][1];
}
}
}
}
}
double mean_sigma_log = 0.0;
int num_avg = 0;
for (int i = 0; i < num_imgs.length; i++) {
if (num_imgs[i] > 0) {
offs_scale[i][0] /= num_imgs[i];
offs_scale[i][1] /= num_imgs[i];
num_avg++;
mean_sigma_log += Math.log(offs_scale[i][1]);
}
}
mean_sigma_log /= num_avg;
double mean_offs = 0;
double mean_sigma = Math.exp(mean_sigma_log); // replace with logs!
for (int i = 0; i < num_imgs.length; i++) {
if (num_imgs[i] > 0) {
offs_scale[i][1] /= mean_sigma;
offs_scale[i][0] /= offs_scale[i][1]; // normalize gain
mean_offs += offs_scale[i][0];
}
}
mean_offs /= num_avg;
for (int i = 0; i < num_imgs.length; i++) {
if (num_imgs[i] > 0) {
offs_scale[i][0] -= mean_offs;
} else {
offs_scale[i] = null;
}
}
return offs_scale; // first scale, then shift
}
/*
double mean_offs = 0;
double mean_sigma_log = 0.0;
int num_avg = 0;
for (int i = 0; i < num_imgs.length; i++) {
if (num_imgs[i] > 0) {
offs_scale[i][0] /= num_imgs[i];
offs_scale[i][1] /= num_imgs[i];
num_avg++;
mean_offs += offs_scale[i][0];
mean_sigma_log += Math.log(offs_scale[i][1]);
}
}
mean_offs /= num_avg;
mean_sigma_log /= num_avg;
double mean_sigma = Math.exp(mean_sigma_log); // replace with logs!
for (int i = 0; i < num_imgs.length; i++) {
if (num_imgs[i] > 0) {
offs_scale[i][0] -= mean_offs;
offs_scale[i][1] /= mean_sigma;
} else {
offs_scale[i] = null;
}
}
*/
double [][] getWindows (ImagePlus [] imps, int wnd_type) {
double [][] windows = new double [imps.length][];
int i0 = -1;
int width = 0;
int height = 0;
for (int i = 0; i < imps.length; i++) {
if (imps[i] != null) {
width = imps[i].getWidth();
height = imps[i].getWidth();
if ((i0 < 0) || (width*height != windows[i0].length)) { // Does not handle different image sizes - possible if needed
i0 = i;
windows[i] = getWindow (
width,
height,
wnd_type); // 3; // 0 - piramid, 1 half-sin, 2-piramid squared, 3 - sin^2
} else {
windows[i] = windows[i0]; // by reference
}
}
}
return windows;
}
double [] getWindow (int width, int height, int type) {
double [] wnd = new double [width * height];
double sy, sx;
double kyl = 2.0/height;
double kxl = 2.0/width;
boolean lin = (type == 0) || (type == 2);
for (int y = 0; y < height; y++) {
if (lin) {
sy = kyl * ((y >= height / 2) ? (height - y) : (y+1));
} else {
sy = Math.sin(Math.PI * y / height);
}
for (int x = 0; x < width; x++) {
if (lin) {
sx = kxl * ((x >= width / 2) ? (width - y) : (y+1));
} else {
sx = Math.sin(Math.PI * x / width);
}
wnd[width*y + x] = sy * sx;
}
}
if ((type == 1) || (type == 3)){ // squared
for (int i = 0; i < wnd.length; i++) {
wnd[i] *= wnd[i];
}
}
return wnd;
}
public boolean convertSourceFiles() { public boolean convertSourceFiles() {
long startTime=System.nanoTime(); // restart timer after possible interactive dialogs long startTime=System.nanoTime(); // restart timer after possible interactive dialogs
final boolean [] selectedChannels = eyesisAberrations.aberrationParameters.getChannelSelection(distortions); // final boolean [] selectedChannels = eyesisAberrations.aberrationParameters.getChannelSelection(distortions);
final boolean [] selectedChannels = illustrationParameters.getSelectedChannels();
final DistortionCalibrationData dcd = distortions.fittingStrategy.distortionCalibrationData; final DistortionCalibrationData dcd = distortions.fittingStrategy.distortionCalibrationData;
final MultipleExtensionsFileFilter sourceFilter = final MultipleExtensionsFileFilter sourceFilter =
new MultipleExtensionsFileFilter("",src_extensions,"Source calibration images"); new MultipleExtensionsFileFilter("",src_extensions,"Source calibration images");
...@@ -207,6 +1690,9 @@ public class CalibrationIllustration { ...@@ -207,6 +1690,9 @@ public class CalibrationIllustration {
// for (int nChn = indxAtomic.getAndIncrement(); nChn < selectedChannels.length; nChn = indxAtomic.getAndIncrement()) if (selectedChannels[nChn]) { // for (int nChn = indxAtomic.getAndIncrement(); nChn < selectedChannels.length; nChn = indxAtomic.getAndIncrement()) if (selectedChannels[nChn]) {
// iterate through all image set (some grids may be missing) // iterate through all image set (some grids may be missing)
for (int nSet = indxAtomic.getAndIncrement(); nSet < dcd.gIS.length; nSet = indxAtomic.getAndIncrement()) { for (int nSet = indxAtomic.getAndIncrement(); nSet < dcd.gIS.length; nSet = indxAtomic.getAndIncrement()) {
if (nSet == 679) {
System.out.println("Debug Set="+nSet);
}
int station = dcd.gIS[nSet].getStationNumber(); int station = dcd.gIS[nSet].getStationNumber();
if (illustrationParameters.useStation(station)) { // some stations only if (illustrationParameters.useStation(station)) { // some stations only
// construct source file name // construct source file name
...@@ -322,6 +1808,9 @@ public class CalibrationIllustration { ...@@ -322,6 +1808,9 @@ public class CalibrationIllustration {
0.0, // double alpha_min, 0.0, // double alpha_min,
1.0); // double alpha_max) 1.0); // double alpha_max)
if (numImg >=0) { if (numImg >=0) {
if (numImg == 2276) {
System.out.println(">>>numImg="+numImg);
}
plotGrid(numImg, plotGrid(numImg,
line_width, line_width,
imp_annot, imp_annot,
...@@ -363,7 +1852,8 @@ public class CalibrationIllustration { ...@@ -363,7 +1852,8 @@ public class CalibrationIllustration {
public boolean removeBadGrids() { public boolean removeBadGrids() {
long startTime=System.nanoTime(); // restart timer after possible interactive dialogs long startTime=System.nanoTime(); // restart timer after possible interactive dialogs
final boolean [] selectedChannels = eyesisAberrations.aberrationParameters.getChannelSelection(distortions); // final boolean [] selectedChannels = eyesisAberrations.aberrationParameters.getChannelSelection(distortions);
final boolean [] selectedChannels = illustrationParameters.getSelectedChannels();
final DistortionCalibrationData dcd = distortions.fittingStrategy.distortionCalibrationData; final DistortionCalibrationData dcd = distortions.fittingStrategy.distortionCalibrationData;
final Thread[] threads = newThreadArray(MAX_THREADS); final Thread[] threads = newThreadArray(MAX_THREADS);
final AtomicInteger indxAtomic = new AtomicInteger(0); final AtomicInteger indxAtomic = new AtomicInteger(0);
......
...@@ -6,8 +6,11 @@ import java.util.Properties; ...@@ -6,8 +6,11 @@ import java.util.Properties;
import com.elphel.imagej.cameras.EyesisCameraParameters; import com.elphel.imagej.cameras.EyesisCameraParameters;
import com.elphel.imagej.common.GenericJTabbedDialog; import com.elphel.imagej.common.GenericJTabbedDialog;
import com.elphel.imagej.common.WindowTools;
import com.elphel.imagej.lwir.LwirReaderParameters; import com.elphel.imagej.lwir.LwirReaderParameters;
import ij.gui.GenericDialog;
public class CalibrationIllustrationParameters { public class CalibrationIllustrationParameters {
static double DFLT_LWIR_LO = 22500.0; static double DFLT_LWIR_LO = 22500.0;
static double DFLT_LWIR_HI = 23500.0; static double DFLT_LWIR_HI = 23500.0;
...@@ -18,6 +21,7 @@ public class CalibrationIllustrationParameters { ...@@ -18,6 +21,7 @@ public class CalibrationIllustrationParameters {
EyesisCameraParameters eyesisCameraParameters; EyesisCameraParameters eyesisCameraParameters;
double [][] lwir_ranges; // = new double [lwirReaderParameters.getLwirChannels(false).length][2]; double [][] lwir_ranges; // = new double [lwirReaderParameters.getLwirChannels(false).length][2];
double [][] lwir_offset_gains; // for balancing channels [0] - offset (subtract) [1] - gain (divide)
int palette = 0; // 0 - white - hot, 1 - black - hot, 2+ - colored int palette = 0; // 0 - white - hot, 1 - black - hot, 2+ - colored
String src_chn_prefix="src_chn-"; String src_chn_prefix="src_chn-";
boolean save_png = true; boolean save_png = true;
...@@ -37,6 +41,71 @@ public class CalibrationIllustrationParameters { ...@@ -37,6 +41,71 @@ public class CalibrationIllustrationParameters {
int line_width_eo = 3; int line_width_eo = 3;
int line_width_lwir = 1; int line_width_lwir = 1;
// kernel illustration
int kernel_dia_direct_lwir = 7; // partial and direct
int kernel_dia_direct_eo = 7;
int kernel_dia_inverse_lwir = 7;
int kernel_dia_inverse_eo = 7;
int kernel_decimate_direct_lwir = 1;
int kernel_decimate_direct_eo = 1;
int kernel_decimate_inverse_lwir = 4;
int kernel_decimate_inverse_eo = 4;
double kernel_direct_lwir_min = 0.0; // -0.007
double kernel_direct_lwir_max = 0.15; // 0.176
double kernel_direct_red_min = 0.0; // -0.001
double kernel_direct_red_max = 0.055; // 0.0448
double kernel_direct_blue_min = 0.0; // -0.0008
double kernel_direct_blue_max = 0.055; // 0.0344
double kernel_direct_green_min = 0.0; // -0.00118
double kernel_direct_green_max = 0.055; // 0.0627
double kernel_inverse_lwir_min = -0.5; // -0.73 (-0.44 most) -.144(-.07)
double kernel_inverse_lwir_max = 1.8; // 0.2 (1.8 - most) .874 (.7)
double kernel_inverse_red_min = -0.8; // -0.73 (-.3)
double kernel_inverse_red_max = 2.75; // 2.3 (1.7)
double kernel_inverse_blue_min = -0.8; // -0.6 (-0.4)
double kernel_inverse_blue_max = 2.75; // 2.3 (1.94)
double kernel_inverse_green_min = -0.8; // -1.1 (-0.53)
double kernel_inverse_green_max = 2.75; // 3.6 (2.87)
int kernel_lwir_palette = 0; // 0 - normal, 2 - heat map
boolean kernels_normalize = false; // make each kernel each component maximum be 1.0
boolean kernel_process_partial = true;
boolean kernel_process_direct = true;
boolean kernel_process_inverse = true;
boolean captures_all_lwir = true;
boolean captures_all_eo = true;
boolean captures_all = false;
double percentile_min = 0.0; // absolute min
double percentile_max = 0.0; // absolute max
double max_range = 1000.0; // 600-1000
double hot_importance = 1.0; // 0 - use value zero, 1.0 - minimal in frame
boolean auto_range = true; // false use per-channel lo/high
boolean auto_lim_range = true; // if difference min/max exceeds max_range, find "optimal" position of fixed range
boolean captures_annotate = true; // Imprint timestamp
Color color_annotate = new Color( 0,200, 200, 255);
int captures_palette = 0; // 0 - white - hot, 1 - black - hot, 2+ - colored
long selected_channels = 0; // bitmask of selected channels
double min_ts = 0.0;
double max_ts = 2000000000.0;
int auto_range_wnd_type = 3; // 0 - piramid, 1 half-sin, 2-piramid squared, 3 - sin^2
boolean calib_offs_gain = true; // perform offset/gain calibration
double calib_offs_gain_ts = 0.0; // timestamp to start gain calibration
double calib_offs_gain_dur = 2000000000.0; // duration for gain calibration
double noise_sigma = 5.0; // image sigma for no-signal
double min_sigma = 100.0; // do not use images with smaller sigmas for gain calibration
double autorange_offs_up = 0.2; // shift range up (fraction of new value)
double autorange_offs_down = 0.05; // shift range down (fraction of new value)
double autorange_range_up = 0.1; // increase range (fraction of new value)
double autorange_range_down = 0.02; // decrease range (fraction of new value)
public CalibrationIllustrationParameters ( public CalibrationIllustrationParameters (
LwirReaderParameters lwirReaderParameters, LwirReaderParameters lwirReaderParameters,
EyesisCameraParameters eyesisCameraParameters) { EyesisCameraParameters eyesisCameraParameters) {
...@@ -67,6 +136,10 @@ public class CalibrationIllustrationParameters { ...@@ -67,6 +136,10 @@ public class CalibrationIllustrationParameters {
properties.setProperty(prefix+"lwir_range_lo_"+i, this.lwir_ranges[i][0]+""); properties.setProperty(prefix+"lwir_range_lo_"+i, this.lwir_ranges[i][0]+"");
properties.setProperty(prefix+"lwir_range_hi_"+i, this.lwir_ranges[i][1]+""); properties.setProperty(prefix+"lwir_range_hi_"+i, this.lwir_ranges[i][1]+"");
} }
for (int i = 0; i < lwir_offset_gains.length; i++) {
properties.setProperty(prefix+"lwir_offset_"+i, this.lwir_offset_gains[i][0]+"");
properties.setProperty(prefix+"lwir_gain_"+i, this.lwir_offset_gains[i][1]+"");
}
properties.setProperty(prefix+"palette", this.palette+""); properties.setProperty(prefix+"palette", this.palette+"");
properties.setProperty(prefix+"save_png", this.save_png+""); properties.setProperty(prefix+"save_png", this.save_png+"");
properties.setProperty(prefix+"JPEG_quality", this.JPEG_quality+""); properties.setProperty(prefix+"JPEG_quality", this.JPEG_quality+"");
...@@ -93,9 +166,70 @@ public class CalibrationIllustrationParameters { ...@@ -93,9 +166,70 @@ public class CalibrationIllustrationParameters {
properties.setProperty(prefix+"line_width_eo", this.line_width_eo+""); properties.setProperty(prefix+"line_width_eo", this.line_width_eo+"");
properties.setProperty(prefix+"line_width_lwir", this.line_width_lwir+""); properties.setProperty(prefix+"line_width_lwir", this.line_width_lwir+"");
}
properties.setProperty(prefix+"kernel_dia_direct_lwir", this.kernel_dia_direct_lwir+"");
properties.setProperty(prefix+"kernel_dia_direct_eo", this.kernel_dia_direct_eo+"");
properties.setProperty(prefix+"kernel_dia_inverse_lwir", this.kernel_dia_inverse_lwir+"");
properties.setProperty(prefix+"kernel_dia_inverse_eo", this.kernel_dia_inverse_eo+"");
properties.setProperty(prefix+"kernel_decimate_direct_lwir", this.kernel_decimate_direct_lwir+"");
properties.setProperty(prefix+"kernel_decimate_direct_eo", this.kernel_decimate_direct_eo+"");
properties.setProperty(prefix+"kernel_decimate_inverse_lwir",this.kernel_decimate_inverse_lwir+"");
properties.setProperty(prefix+"kernel_decimate_inverse_eo", this.kernel_decimate_inverse_eo+"");
properties.setProperty(prefix+"kernel_process_partial", this.kernel_process_partial+"");
properties.setProperty(prefix+"kernel_process_direct", this.kernel_process_direct+"");
properties.setProperty(prefix+"kernel_process_inverse", this.kernel_process_inverse+"");
properties.setProperty(prefix+"kernel_direct_lwir_min", this.kernel_direct_lwir_min+"");
properties.setProperty(prefix+"kernel_direct_lwir_max", this.kernel_direct_lwir_max+"");
properties.setProperty(prefix+"kernel_direct_red_min", this.kernel_direct_red_min+"");
properties.setProperty(prefix+"kernel_direct_red_max", this.kernel_direct_red_max+"");
properties.setProperty(prefix+"kernel_direct_blue_min", this.kernel_direct_blue_min+"");
properties.setProperty(prefix+"kernel_direct_blue_max", this.kernel_direct_blue_max+"");
properties.setProperty(prefix+"kernel_direct_green_min", this.kernel_direct_green_min+"");
properties.setProperty(prefix+"kernel_direct_green_max", this.kernel_direct_green_max+"");
properties.setProperty(prefix+"kernel_inverse_lwir_min", this.kernel_inverse_lwir_min+"");
properties.setProperty(prefix+"kernel_inverse_lwir_max", this.kernel_inverse_lwir_max+"");
properties.setProperty(prefix+"kernel_inverse_red_min", this.kernel_inverse_red_min+"");
properties.setProperty(prefix+"kernel_inverse_red_max", this.kernel_inverse_red_max+"");
properties.setProperty(prefix+"kernel_inverse_blue_min", this.kernel_inverse_blue_min+"");
properties.setProperty(prefix+"kernel_inverse_blue_max", this.kernel_inverse_blue_max+"");
properties.setProperty(prefix+"kernel_inverse_green_min", this.kernel_inverse_green_min+"");
properties.setProperty(prefix+"kernel_inverse_green_max", this.kernel_inverse_green_max+"");
properties.setProperty(prefix+"kernel_lwir_palette", this.kernel_lwir_palette+"");
properties.setProperty(prefix+"kernels_normalize", this.kernels_normalize+"");
properties.setProperty(prefix+"captures_all_lwir", this.captures_all_lwir+"");
properties.setProperty(prefix+"captures_all_eo", this.captures_all_eo+"");
properties.setProperty(prefix+"captures_all", this.captures_all+"");
properties.setProperty(prefix+"percentile_min", this.percentile_min+"");
properties.setProperty(prefix+"percentile_max", this.percentile_max+"");
properties.setProperty(prefix+"max_range", this.max_range+"");
properties.setProperty(prefix+"hot_importance", this.hot_importance+"");
properties.setProperty(prefix+"auto_range", this.auto_range+"");
properties.setProperty(prefix+"auto_lim_range", this.auto_lim_range+"");
properties.setProperty(prefix+"captures_annotate", this.captures_annotate+"");
long lcolor_annotate = (color_annotate == null) ? -1 : getLongColor(color_annotate);
properties.setProperty(prefix+"color_annotate", lcolor_annotate+"");
properties.setProperty(prefix+"captures_palette", this.captures_palette+"");
properties.setProperty(prefix+"selected_channels", this.selected_channels+"");
properties.setProperty(prefix+"min_ts", this.min_ts+"");
properties.setProperty(prefix+"max_ts", this.max_ts+"");
properties.setProperty(prefix+"auto_range_wnd_type", this.auto_range_wnd_type+"");
properties.setProperty(prefix+"calib_offs_gain", this.calib_offs_gain+"");
properties.setProperty(prefix+"calib_offs_gain_ts", this.calib_offs_gain_ts+"");
properties.setProperty(prefix+"calib_offs_gain_dur", this.calib_offs_gain_dur+"");
properties.setProperty(prefix+"noise_sigma", this.noise_sigma+"");
properties.setProperty(prefix+"min_sigma", this.min_sigma+"");
properties.setProperty(prefix+"autorange_offs_up", this.autorange_offs_up+"");
properties.setProperty(prefix+"autorange_offs_down", this.autorange_offs_down+"");
properties.setProperty(prefix+"autorange_range_up", this.autorange_range_up+"");
properties.setProperty(prefix+"autorange_range_down", this.autorange_range_down+"");
}
public void getProperties(String prefix,Properties properties){ public void getProperties(String prefix,Properties properties){
set_parameters(); set_parameters();
...@@ -107,6 +241,23 @@ public class CalibrationIllustrationParameters { ...@@ -107,6 +241,23 @@ public class CalibrationIllustrationParameters {
this.lwir_ranges[i][1] = Double.parseDouble(properties.getProperty(prefix+"lwir_range_hi_"+i)); this.lwir_ranges[i][1] = Double.parseDouble(properties.getProperty(prefix+"lwir_range_hi_"+i));
} }
} }
for (int i = 0; i < lwir_offset_gains.length; i++) {
if (properties.getProperty(prefix+"lwir_offset_"+i)!=null) {
this.lwir_offset_gains[i][0] = Double.parseDouble(properties.getProperty(prefix+"lwir_offset_"+i));
}
if (properties.getProperty(prefix+"lwir_gain_"+i)!=null) {
this.lwir_offset_gains[i][1] = Double.parseDouble(properties.getProperty(prefix+"lwir_gain_"+i));
}
}
/*
for (int i = 0; i < lwir_offset_gains.length; i++) {
properties.setProperty(prefix+"lwir_offset_"+i, this.lwir_offset_gains[i][0]+"");
properties.setProperty(prefix+"lwir_gain_"+i, this.lwir_offset_gains[i][1]+"");
}
*/
if (properties.getProperty(prefix+"palette")!=null) this.palette = Integer.parseInt(properties.getProperty(prefix+"palette")); if (properties.getProperty(prefix+"palette")!=null) this.palette = Integer.parseInt(properties.getProperty(prefix+"palette"));
if (properties.getProperty(prefix+"save_png")!=null) this.save_png = Boolean.parseBoolean(properties.getProperty(prefix+"save_png")); if (properties.getProperty(prefix+"save_png")!=null) this.save_png = Boolean.parseBoolean(properties.getProperty(prefix+"save_png"));
if (properties.getProperty(prefix+"JPEG_quality")!=null) this.JPEG_quality = Integer.parseInt(properties.getProperty(prefix+"JPEG_quality")); if (properties.getProperty(prefix+"JPEG_quality")!=null) this.JPEG_quality = Integer.parseInt(properties.getProperty(prefix+"JPEG_quality"));
...@@ -142,12 +293,75 @@ public class CalibrationIllustrationParameters { ...@@ -142,12 +293,75 @@ public class CalibrationIllustrationParameters {
} }
if (properties.getProperty(prefix+"color_grid_extra")!=null) { if (properties.getProperty(prefix+"color_grid_extra")!=null) {
long lcolor_grid_extra = Long.parseLong(properties.getProperty(prefix+"color_grid_extra")); long lcolor_grid_extra = Long.parseLong(properties.getProperty(prefix+"color_grid_extra"));
if (lcolor_grid_extra < 0) this.color_grid = null; if (lcolor_grid_extra < 0) this.color_grid_extra = null;
else this.color_grid_extra = setLongColor(lcolor_grid_extra); else this.color_grid_extra = setLongColor(lcolor_grid_extra);
} }
if (properties.getProperty(prefix+"line_width_eo")!=null) this.line_width_eo = Integer.parseInt(properties.getProperty(prefix+"line_width_eo")); if (properties.getProperty(prefix+"line_width_eo")!=null) this.line_width_eo = Integer.parseInt(properties.getProperty(prefix+"line_width_eo"));
if (properties.getProperty(prefix+"line_width_lwir")!=null) this.line_width_lwir = Integer.parseInt(properties.getProperty(prefix+"line_width_lwir")); if (properties.getProperty(prefix+"line_width_lwir")!=null) this.line_width_lwir = Integer.parseInt(properties.getProperty(prefix+"line_width_lwir"));
if (properties.getProperty(prefix+"kernel_dia_direct_lwir")!=null) this.kernel_dia_direct_lwir = Integer.parseInt(properties.getProperty(prefix+"kernel_dia_direct_lwir"));
if (properties.getProperty(prefix+"kernel_dia_direct_eo")!=null) this.kernel_dia_direct_eo = Integer.parseInt(properties.getProperty(prefix+"kernel_dia_direct_eo"));
if (properties.getProperty(prefix+"kernel_dia_inverse_lwir")!=null) this.kernel_dia_inverse_lwir = Integer.parseInt(properties.getProperty(prefix+"kernel_dia_inverse_lwir"));
if (properties.getProperty(prefix+"kernel_dia_inverse_eo")!=null) this.kernel_dia_inverse_eo = Integer.parseInt(properties.getProperty(prefix+"kernel_dia_inverse_eo"));
if (properties.getProperty(prefix+"kernel_decimate_direct_lwir")!=null) this.kernel_decimate_direct_lwir = Integer.parseInt(properties.getProperty(prefix+"kernel_decimate_direct_lwir"));
if (properties.getProperty(prefix+"kernel_decimate_direct_eo")!=null) this.kernel_decimate_direct_eo = Integer.parseInt(properties.getProperty(prefix+"kernel_decimate_direct_eo"));
if (properties.getProperty(prefix+"kernel_decimate_inverse_lwir")!=null) this.kernel_decimate_inverse_lwir = Integer.parseInt(properties.getProperty(prefix+"kernel_decimate_inverse_lwir"));
if (properties.getProperty(prefix+"kernel_decimate_inverse_eo")!=null) this.kernel_decimate_inverse_eo = Integer.parseInt(properties.getProperty(prefix+"kernel_decimate_inverse_eo"));
if (properties.getProperty(prefix+"kernel_process_partial")!=null) this.kernel_process_partial = Boolean.parseBoolean(properties.getProperty(prefix+"kernel_process_partial"));
if (properties.getProperty(prefix+"kernel_process_direct")!=null) this.kernel_process_direct = Boolean.parseBoolean(properties.getProperty(prefix+"kernel_process_direct"));
if (properties.getProperty(prefix+"kernel_process_inverse")!=null) this.kernel_process_inverse = Boolean.parseBoolean(properties.getProperty(prefix+"kernel_process_inverse"));
if (properties.getProperty(prefix+"kernel_direct_lwir_min")!=null) this.kernel_direct_lwir_min = Double.parseDouble(properties.getProperty(prefix+"kernel_direct_lwir_min"));
if (properties.getProperty(prefix+"kernel_direct_lwir_max")!=null) this.kernel_direct_lwir_max = Double.parseDouble(properties.getProperty(prefix+"kernel_direct_lwir_max"));
if (properties.getProperty(prefix+"kernel_direct_red_min")!=null) this.kernel_direct_red_min = Double.parseDouble(properties.getProperty(prefix+"kernel_direct_red_min"));
if (properties.getProperty(prefix+"kernel_direct_red_max")!=null) this.kernel_direct_red_max = Double.parseDouble(properties.getProperty(prefix+"kernel_direct_red_max"));
if (properties.getProperty(prefix+"kernel_direct_blue_min")!=null) this.kernel_direct_blue_min = Double.parseDouble(properties.getProperty(prefix+"kernel_direct_blue_min"));
if (properties.getProperty(prefix+"kernel_direct_blue_max")!=null) this.kernel_direct_blue_max = Double.parseDouble(properties.getProperty(prefix+"kernel_direct_blue_max"));
if (properties.getProperty(prefix+"kernel_direct_green_min")!=null) this.kernel_direct_green_min = Double.parseDouble(properties.getProperty(prefix+"kernel_direct_green_min"));
if (properties.getProperty(prefix+"kernel_direct_green_max")!=null) this.kernel_direct_green_max = Double.parseDouble(properties.getProperty(prefix+"kernel_direct_green_max"));
if (properties.getProperty(prefix+"kernel_inverse_lwir_min")!=null) this.kernel_inverse_lwir_min = Double.parseDouble(properties.getProperty(prefix+"kernel_inverse_lwir_min"));
if (properties.getProperty(prefix+"kernel_inverse_lwir_max")!=null) this.kernel_inverse_lwir_max = Double.parseDouble(properties.getProperty(prefix+"kernel_inverse_lwir_max"));
if (properties.getProperty(prefix+"kernel_inverse_red_min")!=null) this.kernel_inverse_red_min = Double.parseDouble(properties.getProperty(prefix+"kernel_inverse_red_min"));
if (properties.getProperty(prefix+"kernel_inverse_red_max")!=null) this.kernel_inverse_red_max = Double.parseDouble(properties.getProperty(prefix+"kernel_inverse_red_max"));
if (properties.getProperty(prefix+"kernel_inverse_blue_min")!=null) this.kernel_inverse_blue_min = Double.parseDouble(properties.getProperty(prefix+"kernel_inverse_blue_min"));
if (properties.getProperty(prefix+"kernel_inverse_blue_max")!=null) this.kernel_inverse_blue_max = Double.parseDouble(properties.getProperty(prefix+"kernel_inverse_blue_max"));
if (properties.getProperty(prefix+"kernel_inverse_green_max")!=null) this.kernel_inverse_green_max = Double.parseDouble(properties.getProperty(prefix+"kernel_inverse_green_max"));
if (properties.getProperty(prefix+"kernel_direct_lwir_min")!=null) this.kernel_direct_lwir_min = Double.parseDouble(properties.getProperty(prefix+"kernel_direct_lwir_min"));
if (properties.getProperty(prefix+"kernel_lwir_palette")!=null) this.kernel_lwir_palette = Integer.parseInt(properties.getProperty(prefix+"kernel_lwir_palette"));
if (properties.getProperty(prefix+"kernels_normalize")!=null) this.kernels_normalize = Boolean.parseBoolean(properties.getProperty(prefix+"kernels_normalize"));
if (properties.getProperty(prefix+"captures_all_lwir")!=null) this.captures_all_lwir = Boolean.parseBoolean(properties.getProperty(prefix+"captures_all_lwir"));
if (properties.getProperty(prefix+"captures_all_eo")!=null) this.captures_all_eo = Boolean.parseBoolean(properties.getProperty(prefix+"captures_all_eo"));
if (properties.getProperty(prefix+"captures_all")!=null) this.captures_all = Boolean.parseBoolean(properties.getProperty(prefix+"captures_all"));
if (properties.getProperty(prefix+"percentile_min")!=null) this.percentile_min = Double.parseDouble(properties.getProperty(prefix+"percentile_min"));
if (properties.getProperty(prefix+"percentile_max")!=null) this.percentile_max = Double.parseDouble(properties.getProperty(prefix+"percentile_max"));
if (properties.getProperty(prefix+"max_range")!=null) this.max_range = Double.parseDouble(properties.getProperty(prefix+"max_range"));
if (properties.getProperty(prefix+"hot_importance")!=null) this.hot_importance = Double.parseDouble(properties.getProperty(prefix+"hot_importance"));
if (properties.getProperty(prefix+"auto_range")!=null) this.auto_range = Boolean.parseBoolean(properties.getProperty(prefix+"auto_range"));
if (properties.getProperty(prefix+"auto_lim_range")!=null) this.auto_lim_range = Boolean.parseBoolean(properties.getProperty(prefix+"auto_lim_range"));
if (properties.getProperty(prefix+"captures_annotate")!=null) this.captures_annotate = Boolean.parseBoolean(properties.getProperty(prefix+"captures_annotate"));
if (properties.getProperty(prefix+"color_annotate")!=null) {
long lcolor_annotate = Long.parseLong(properties.getProperty(prefix+"color_annotate"));
if (lcolor_annotate < 0) this.color_annotate = null;
else this.color_annotate = setLongColor(lcolor_annotate);
}
if (properties.getProperty(prefix+"captures_palette")!=null) this.captures_palette = Integer.parseInt(properties.getProperty(prefix+"captures_palette"));
if (properties.getProperty(prefix+"selected_channels")!=null) this.selected_channels = Long.parseLong(properties.getProperty(prefix+"selected_channels"));
if (properties.getProperty(prefix+"min_ts")!=null) this.min_ts = Double.parseDouble(properties.getProperty(prefix+"min_ts"));
if (properties.getProperty(prefix+"max_ts")!=null) this.max_ts = Double.parseDouble(properties.getProperty(prefix+"max_ts"));
if (properties.getProperty(prefix+"auto_range_wnd_type")!=null) this.auto_range_wnd_type = Integer.parseInt(properties.getProperty(prefix+"auto_range_wnd_type"));
if (properties.getProperty(prefix+"calib_offs_gain")!=null) this.calib_offs_gain = Boolean.parseBoolean(properties.getProperty(prefix+"calib_offs_gain"));
if (properties.getProperty(prefix+"calib_offs_gain_ts")!=null) this.calib_offs_gain_ts = Double.parseDouble(properties.getProperty(prefix+"calib_offs_gain_ts"));
if (properties.getProperty(prefix+"calib_offs_gain_dur")!=null) this.calib_offs_gain_dur = Double.parseDouble(properties.getProperty(prefix+"calib_offs_gain_dur"));
if (properties.getProperty(prefix+"noise_sigma")!=null) this.noise_sigma = Double.parseDouble(properties.getProperty(prefix+"noise_sigma"));
if (properties.getProperty(prefix+"min_sigma")!=null) this.min_sigma = Double.parseDouble(properties.getProperty(prefix+"min_sigma"));
if (properties.getProperty(prefix+"autorange_offs_up")!=null) this.autorange_offs_up = Double.parseDouble(properties.getProperty(prefix+"autorange_offs_up"));
if (properties.getProperty(prefix+"autorange_offs_down")!=null) this.autorange_offs_down = Double.parseDouble(properties.getProperty(prefix+"autorange_offs_down"));
if (properties.getProperty(prefix+"autorange_range_up")!=null) this.autorange_range_up = Double.parseDouble(properties.getProperty(prefix+"autorange_range_up"));
if (properties.getProperty(prefix+"autorange_range_down")!=null) this.autorange_range_down = Double.parseDouble(properties.getProperty(prefix+"autorange_range_down"));
} }
public void dialogQuestions(GenericJTabbedDialog gd) { public void dialogQuestions(GenericJTabbedDialog gd) {
final int lwir0 = getLwirReaderParameters().getLwirChn0(); final int lwir0 = getLwirReaderParameters().getLwirChn0();
final int eo0 = getLwirReaderParameters().getEoChn0(); final int eo0 = getLwirReaderParameters().getEoChn0();
...@@ -189,9 +403,79 @@ public class CalibrationIllustrationParameters { ...@@ -189,9 +403,79 @@ public class CalibrationIllustrationParameters {
gd.addNumericField("JPEG quality", this.JPEG_quality, 0,3,"","JPEG quality, 0 - use Tiff"); gd.addNumericField("JPEG quality", this.JPEG_quality, 0,3,"","JPEG quality, 0 - use Tiff");
gd.addNumericField("Threshold contrast", this.threshold_contrast, 3,6,"","Consider grid nodes with higher contrast to determine bad grids."); gd.addNumericField("Threshold contrast", this.threshold_contrast, 3,6,"","Consider grid nodes with higher contrast to determine bad grids.");
gd.addNumericField("Minimal number of high-contrast nodes", this.threshold_number, 0,3,"","Consider a failed grid if the number of strong nodes is below this."); gd.addNumericField("Minimal number of high-contrast nodes", this.threshold_number, 0,3,"","Consider a failed grid if the number of strong nodes is below this.");
}
gd.addTab("Kernels","'Humanize' partial, direct and inverse kernels");
gd.addNumericField("Kernel (partial, direct) size to keep, LWIR", this.kernel_dia_direct_lwir, 0,3,"pix","Size=3 preserves 3x3 center from each kernel, even add 1 pixel gap");
gd.addNumericField("Kernel (partial, direct) size to keep, EO", this.kernel_dia_direct_eo, 0,3,"pix","Size=3 preserves 3x3 center from each kernel, even add 1 pixel gap");
gd.addNumericField("Kernel (inverted) size to keep, LWIR", this.kernel_dia_inverse_lwir, 0,3,"pix","Size=3 preserves 3x3 center from each kernel, even add 1 pixel gap");
gd.addNumericField("Kernel (inverted) size to keep, EO", this.kernel_dia_inverse_eo, 0,3,"pix","Size=3 preserves 3x3 center from each kernel, even add 1 pixel gap");
gd.addNumericField("Decimate direct LWIR kernels", this.kernel_decimate_direct_lwir, 0,3,"","reduce output kernel density");
gd.addNumericField("Decimate direct EO kernels", this.kernel_decimate_direct_eo, 0,3,"pix","reduce output kernel density");
gd.addNumericField("Decimate inverted LWIR kernels", this.kernel_decimate_inverse_lwir, 0,3,"pix","reduce output kernel density");
gd.addNumericField("Decimate inverted EO kernels", this.kernel_decimate_inverse_eo, 0,3,"pix","reduce output kernel density");
gd.addCheckbox ("Illustrate partial kernels", this.kernel_process_partial, "Process and save partial kernels");
gd.addCheckbox ("Illustrate direct kernels", this.kernel_process_direct, "Process and save combined direct kernels");
gd.addCheckbox ("Illustrate inverted kernels", this.kernel_process_inverse, "Process and save inverted kernels");
gd.addMessage("Levels for direct LWIR kernels");
gd.addNumericField("Low level for LWIR direct kernels", this.kernel_direct_lwir_min, 4,8,"","Applies to partial and direct kernels (from histograms: -0.007)");
gd.addNumericField("High level for LWIR direct kernels", this.kernel_direct_lwir_max, 4,8,"","Applies to partial and direct kernels (from histograms: 0.176)");
gd.addMessage("Levels for direct RGB kernels (same for all color components to merge into a color image)");
gd.addNumericField("Low level for RGB/red direct kernels", this.kernel_direct_red_min, 4,8,"","Applies to partial and direct kernels (from histograms: -0.001)");
gd.addNumericField("High level for RGB/red direct kernels", this.kernel_direct_red_max, 4,8,"","Applies to partial and direct kernels (from histograms: 0.0448)");
gd.addNumericField("Low level for RGB/green direct kernels", this.kernel_direct_green_min, 4,8,"","Applies to partial and direct kernels (from histograms: -0.00118)");
gd.addNumericField("High level for RGB/green direct kernels", this.kernel_direct_green_max, 4,8,"","Applies to partial and direct kernels (from histograms: 0.0627)");
gd.addNumericField("Low level for RGB/blue direct kernels", this.kernel_direct_blue_min, 4,8,"","Applies to partial and direct kernels (from histograms: -0.0008)");
gd.addNumericField("High level for RGB/blue direct kernels", this.kernel_direct_blue_max, 4,8,"","Applies to partial and direct kernels (from histograms: 0.0344)");
gd.addMessage("Levels for inverse LWIR kernels");
gd.addNumericField("Low level for LWIR inverse kernels", this.kernel_inverse_lwir_min, 4,8,"","Applies to inverse kernels (from histograms: -0.144 (-0.07 most))");
gd.addNumericField("High level for LWIR inverse kernels", this.kernel_inverse_lwir_max, 4,8,"","Applies to inverse kernels (from histograms: .874 (.7 - most))");
gd.addMessage("Levels for inverse RGB kernels");
gd.addNumericField("Low level for RGB/red inverse kernels", this.kernel_inverse_red_min, 4,8,"","Applies to inverse kernels (from histograms: -0.73 (-0.3 most))");
gd.addNumericField("High level for RGB/red inverse kernels", this.kernel_inverse_red_max, 4,8,"","Applies to inverse kernels (from histograms: 0.23 ( 1.7 most))");
gd.addNumericField("Low level for RGB/green inverse kernels", this.kernel_inverse_green_min,4,8,"","Applies to inverse kernels (from histograms: -1.1 (-0.53 most))");
gd.addNumericField("High level for RGB/green inverse kernels", this.kernel_inverse_green_max,4,8,"","Applies to inverse kernels (from histograms: 3.6 ( 2.87 most))");
gd.addNumericField("Low level for RGB/blue inverse kernels", this.kernel_inverse_blue_min, 4,8,"","Applies to inverse kernels (from histograms: -0.6 (-0.4 most))");
gd.addNumericField("High level for RGB/blue inverse kernels", this.kernel_inverse_blue_max, 4,8,"","Applies to inverse kernels (from histograms: 2.3 (1.94 most))");
gd.addNumericField("Palette to use for monochrome kernels", this.kernel_lwir_palette, 0,3,"","0 - normal, 1 - inverted, 2+ - heatmap");
gd.addCheckbox ("Normalize each kernel/component", this.kernels_normalize, "Make each kernel component maximum be 1.0");
gd.addTab("Field footage","Coverting raw captured images into PNG/JPEG sequences to convert to video");
gd.addCheckbox ("Ignore scenes with partial LWIR channels", this.captures_all_lwir, "Skip scenes where not all or none LWIR channels are available");
gd.addCheckbox ("Ignore scenes with partial EO channels", this.captures_all_eo, "Skip scenes where not all or none EO channels are available");
gd.addCheckbox ("Ignore partial scenes", this.captures_all, "Skip scenes where not all (20) images are present");
gd.addNumericField("Ignore coldest percentile", 100*this.percentile_min, 4,8,"%","This fraction of all pixels will be considered 'too cold'");
gd.addNumericField("Ignore hottest percentile", 100*this.percentile_max, 4,8,"%","This fraction of all pixels will be considered 'too hot'");
gd.addNumericField("Maximal range", this.max_range, 4,8,"counts","Maximal range (in 16-bit raw TIFF counts) to use while presenting output data");
gd.addNumericField("Hot importance", this.hot_importance, 4,8,"","Maximal range (in 16-bit raw TIFF counts) to use while presenting output data");
gd.addCheckbox ("Auto range LWIR images", this.auto_range, "Auto range images, if unchecked - use per-channel ranges specified in LWIR tab");
gd.addCheckbox ("Limit range", this.auto_lim_range, "When difference between max and min exceeds maximal range, use maximal range and find best offset");
gd.addCheckbox ("Annotate images with timestamps", this.captures_annotate, "Imprint timestamps into output images");
scolor = (this.color_annotate==null)?"none":String.format("%08x", getLongColor(this.color_annotate));
gd.addStringField ("Line color for the grid lines (actual grid)",scolor, 8, "Any invalid hex number disables annotation");
gd.addNumericField("Thermal color palette", this.captures_palette, 0,3,"","0 - white-hot, 1 - black-hot, 2+ - colored");
gd.addNumericField("Minimal timestamp to process", this.min_ts, 4,20,"s","Do not process scenes earlier than that timestamp");
gd.addNumericField("Maximal timestamp to process", this.max_ts, 4,20,"s","Do not process scenes later than that timestamp");
gd.addNumericField("Sensor balancing window type", this.auto_range_wnd_type, 0,3,"","0 - piramid, 1 half-sin, 2-piramid squared, 3 - sin^2");
gd.addCheckbox ("Perform LWIR sensors offset/gain balancing ", this.calib_offs_gain, "Calculate sensor channels offset and gains from selected imagery");
gd.addNumericField("Balancing start timestamp", this.calib_offs_gain_ts, 4,20,"s","Earliest scene to use for sensor channel balancing");
gd.addNumericField("Balancing duration", this.calib_offs_gain_dur, 4,20,"s","Balancing duration (end timestamp - start timestamp)");
gd.addNumericField("Noise sigma", this.noise_sigma, 2,8,"counts","Typical sigma of the LWIR images with uniform illumination");
gd.addNumericField("Minimal LWIR sigma", this.min_sigma, 2,8,"counts","Do not use images were sigma is below for gain calibration");
gd.addNumericField("Shift range up (fraction of new value)", this.autorange_offs_up, 4,6,"","If system wants to shift range up, use this (<=1.0) fraction of the new value");
gd.addNumericField("Shift range down (fraction of new value)", this.autorange_offs_down, 4,6,"","If system wants to shift range up, use this (<=1.0) fraction of the new value");
gd.addNumericField("Increase range (fraction of new value)", this.autorange_range_up, 4,6,"","If system wants to increase range, use this (<=1.0) fraction of the new value");
gd.addNumericField("Decrease range (fraction of new value)", this.autorange_range_down, 4,6,"","If system wants to decrease range, use this (<=1.0) fraction of the new value");
gd.addCheckbox ("Edit selected channels", false, "check to edit selected channels");
}
//kernels_normalize
public void dialogAnswers(GenericJTabbedDialog gd) { public void dialogAnswers(GenericJTabbedDialog gd) {
// --- LWIR --- // --- LWIR ---
this.palette = (int) gd.getNextNumber(); this.palette = (int) gd.getNextNumber();
...@@ -250,7 +534,76 @@ public class CalibrationIllustrationParameters { ...@@ -250,7 +534,76 @@ public class CalibrationIllustrationParameters {
this.JPEG_quality = (int) gd.getNextNumber(); this.JPEG_quality = (int) gd.getNextNumber();
this.threshold_contrast = gd.getNextNumber(); this.threshold_contrast = gd.getNextNumber();
this.threshold_number= (int) gd.getNextNumber(); this.threshold_number= (int) gd.getNextNumber();
// --- Kernels ---
this.kernel_dia_direct_lwir = (int) gd.getNextNumber();
this.kernel_dia_direct_eo = (int) gd.getNextNumber();
this.kernel_dia_inverse_lwir = (int) gd.getNextNumber();
this.kernel_dia_inverse_eo = (int) gd.getNextNumber();
this.kernel_decimate_direct_lwir = (int) gd.getNextNumber();
this.kernel_decimate_direct_eo = (int) gd.getNextNumber();
this.kernel_decimate_inverse_lwir = (int) gd.getNextNumber();
this.kernel_decimate_inverse_eo = (int) gd.getNextNumber();
this.kernel_process_partial = gd.getNextBoolean();
this.kernel_process_direct = gd.getNextBoolean();
this.kernel_process_inverse = gd.getNextBoolean();
// kernel levels
this.kernel_direct_lwir_min = gd.getNextNumber();
this.kernel_direct_lwir_max = gd.getNextNumber();
this.kernel_direct_red_min = gd.getNextNumber();
this.kernel_direct_red_max = gd.getNextNumber();
this.kernel_direct_green_min = gd.getNextNumber();
this.kernel_direct_green_max = gd.getNextNumber();
this.kernel_direct_blue_min = gd.getNextNumber();
this.kernel_direct_blue_max = gd.getNextNumber();
this.kernel_inverse_lwir_min = gd.getNextNumber();
this.kernel_inverse_lwir_max = gd.getNextNumber();
this.kernel_inverse_red_min = gd.getNextNumber();
this.kernel_inverse_red_max = gd.getNextNumber();
this.kernel_inverse_green_min = gd.getNextNumber();
this.kernel_inverse_green_max = gd.getNextNumber();
this.kernel_inverse_blue_min = gd.getNextNumber();
this.kernel_inverse_blue_max = gd.getNextNumber();
this.kernel_lwir_palette = (int) gd.getNextNumber();
this.kernels_normalize = gd.getNextBoolean();
this.captures_all_lwir = gd.getNextBoolean();
this.captures_all_eo = gd.getNextBoolean();
this.captures_all = gd.getNextBoolean();
this.percentile_min = 0.01*gd.getNextNumber();
this.percentile_max = 0.01*gd.getNextNumber();
this.max_range = gd.getNextNumber();
this.hot_importance = gd.getNextNumber();
this.auto_range = gd.getNextBoolean();
this.auto_lim_range = gd.getNextBoolean();
this.captures_annotate = gd.getNextBoolean();
scolor = gd.getNextString();
lcolor = -1;
try {
lcolor = Long.parseLong(scolor,16);
this.color_annotate = setLongColor(lcolor);
} catch(NumberFormatException e){
this.color_annotate = null;
} }
this.captures_palette = (int) gd.getNextNumber();
this.min_ts = gd.getNextNumber();
this.max_ts = gd.getNextNumber();
this.auto_range_wnd_type = (int) gd.getNextNumber();
this.calib_offs_gain = gd.getNextBoolean();
this.calib_offs_gain_ts = gd.getNextNumber();
this.calib_offs_gain_dur = gd.getNextNumber();
this.noise_sigma = gd.getNextNumber();
this.min_sigma = gd.getNextNumber();
this.autorange_offs_up = gd.getNextNumber();
this.autorange_offs_down = gd.getNextNumber();
this.autorange_range_up = gd.getNextNumber();
this.autorange_range_down = gd.getNextNumber();
if (gd.getNextBoolean()) {
selectChannelsToProcess("Select channels to process");
}
}
public boolean showJDialog() { public boolean showJDialog() {
set_parameters(); set_parameters();
GenericJTabbedDialog gd = new GenericJTabbedDialog("Set illustration parameters",800,900); GenericJTabbedDialog gd = new GenericJTabbedDialog("Set illustration parameters",800,900);
...@@ -277,6 +630,25 @@ public class CalibrationIllustrationParameters { ...@@ -277,6 +630,25 @@ public class CalibrationIllustrationParameters {
eo_rb2g_hi[i][2] = DFLT_EO_HI; // range to map to 255.0 eo_rb2g_hi[i][2] = DFLT_EO_HI; // range to map to 255.0
} }
} }
if ((lwir_offset_gains == null) || (lwir_offset_gains.length != lwirReaderParameters.getLwirChannels(false).length)){
lwir_offset_gains = new double [lwirReaderParameters.getLwirChannels(false).length][2];
for (int i = 0; i < lwir_offset_gains.length; i++) {
this.lwir_offset_gains[i][0] = 0.0;
this.lwir_offset_gains[i][1] = 1.0;
}
}
}
public void setLWIROffsetGains(double [][] offset_gains) {
for (int i = 0; i < lwir_offset_gains.length; i++) { // offset_gains may be [20], while lwir_offset_gains - just 16
if (offset_gains[i] != null) {
lwir_offset_gains[i] = offset_gains[i].clone();
}
}
}
public double [][] getLWIROffsetGains(){
return lwir_offset_gains;
} }
public double getGamma() { public double getGamma() {
...@@ -339,4 +711,48 @@ public class CalibrationIllustrationParameters { ...@@ -339,4 +711,48 @@ public class CalibrationIllustrationParameters {
public LwirReaderParameters getLwirReaderParameters() { public LwirReaderParameters getLwirReaderParameters() {
return lwirReaderParameters; return lwirReaderParameters;
} }
public boolean [] getSelectedChannels() {
int num_lwir_channels = lwirReaderParameters.getLwirChannels(true).length;
int num_eo_channels = lwirReaderParameters.getEoChannels(true).length;
boolean [] selection = new boolean[num_lwir_channels + num_eo_channels];
for (int i = 0; i < selection.length; i++) {
selection[i] = ((this.selected_channels >> i) & 1) != 0;
}
return selection;
}
public boolean selectChannelsToProcess(String title) {
int num_lwir_channels = lwirReaderParameters.getLwirChannels(true).length;
int num_eo_channels = lwirReaderParameters.getEoChannels(true).length;
boolean [] selection = getSelectedChannels();
int numChannels=selection.length;
while (true) {
GenericJTabbedDialog gd = new GenericJTabbedDialog(title);
// GenericDialog gd = new GenericDialog(title);
gd.addMessage("LWIR channels");
for (int i=0;i<num_lwir_channels;i++) gd.addCheckbox("channel "+i, selection[i]);
gd.addMessage("EO channels");
for (int i=num_lwir_channels; i < (num_lwir_channels + num_eo_channels);i++) gd.addCheckbox("channel "+i, selection[i]);
String [] labels = {"OK", "All like channel 0/"+num_lwir_channels, "Cancel"};
String [] actions = {"OK", "_All like channel 0/"+num_lwir_channels, "Cancel"};
String [] tooltips = labels;
gd.addButtons(labels, actions, tooltips);
// gd.enableYesNoCancel("OK", "All like channel 0");
// WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
for (int i=0;i<numChannels;i++) selection[i]=gd.getNextBoolean();
if (gd.wasOKed()){
this.selected_channels = 0;
for (int i=0;i<numChannels;i++) {
this.selected_channels |= (selection[i] ? 1 : 0) << i;
}
return true;
} else {
for (int i=1;i<num_lwir_channels;i++) selection[i]=selection[0];
for (int i=1;i<num_eo_channels;i++) selection[num_lwir_channels+i]=selection[num_lwir_channels];
}
}
}
} }
...@@ -957,9 +957,20 @@ import ij.text.TextWindow; ...@@ -957,9 +957,20 @@ import ij.text.TextWindow;
(path.charAt(indexLastDash)!='_') && (path.charAt(indexLastDash)!='_') &&
(path.charAt(indexLastDash)!='-')) indexLastDash--; (path.charAt(indexLastDash)!='-')) indexLastDash--;
return Integer.parseInt(path.substring(indexLastDash+1,indexSuffix)); return Integer.parseInt(path.substring(indexLastDash+1,indexSuffix));
} }
/*
public static double getTimestampFromPath(String path) {
if (path == null) return Double.NaN;
int i1=path.indexOf('-',path.lastIndexOf(Prefs.getFileSeparator()));
int i2=path.indexOf('-',i1+1);
int i3=path.indexOf('.',i2+1);
// Extract timestamp from the filename
if ((i1<0) || (i2<0)) {
return Double.NaN;
}
return Double.parseDouble(path.substring(i1+1,i2).replace('_','.'));
}
*/
private boolean invertColor(int chn) { private boolean invertColor(int chn) {
//TODO: Add looking at the image property to find out if inversion is already contained in the grid files //TODO: Add looking at the image property to find out if inversion is already contained in the grid files
return eyesisCameraParameters.isLWIR(chn); return eyesisCameraParameters.isLWIR(chn);
......
...@@ -2290,7 +2290,7 @@ public class EyesisAberrations { ...@@ -2290,7 +2290,7 @@ public class EyesisAberrations {
final int masterDebugLevel, // get rid of it? // ** NEW final int masterDebugLevel, // get rid of it? // ** NEW
final int globalDebugLevel,// ** NEW final int globalDebugLevel,// ** NEW
final int debug_level){// debug level used inside loops final int debug_level){// debug level used inside loops
boolean is_lwir = ((lwirReaderParameters != null) && lwirReaderParameters.is_LWIR(imp_sel)); boolean is_lwir = ((lwirReaderParameters != null) && LwirReaderParameters.is_LWIR(imp_sel));
boolean is_mono = false; boolean is_mono = false;
try { try {
is_mono = Boolean.parseBoolean((String) imp_sel.getProperty("MONOCHROME")); is_mono = Boolean.parseBoolean((String) imp_sel.getProperty("MONOCHROME"));
...@@ -4785,6 +4785,7 @@ public class EyesisAberrations { ...@@ -4785,6 +4785,7 @@ public class EyesisAberrations {
public String sourceDirectory=""; public String sourceDirectory="";
public String partialKernelDirectory=""; public String partialKernelDirectory="";
public String illustrationsDirectory=""; public String illustrationsDirectory="";
public String capturedDirectory = "";
public String psfKernelDirectory=""; public String psfKernelDirectory="";
public String aberrationsKernelDirectory=""; public String aberrationsKernelDirectory="";
public String calibrationDirectory=""; public String calibrationDirectory="";
...@@ -4823,10 +4824,10 @@ public class EyesisAberrations { ...@@ -4823,10 +4824,10 @@ public class EyesisAberrations {
properties.setProperty(prefix+"sourceDirectory",this.sourceDirectory); properties.setProperty(prefix+"sourceDirectory",this.sourceDirectory);
properties.setProperty(prefix+"partialKernelDirectory",this.partialKernelDirectory); properties.setProperty(prefix+"partialKernelDirectory",this.partialKernelDirectory);
properties.setProperty(prefix+"illustrationsDirectory",this.illustrationsDirectory); properties.setProperty(prefix+"illustrationsDirectory",this.illustrationsDirectory);
properties.setProperty(prefix+"capturedDirectory", this.capturedDirectory);
properties.setProperty(prefix+"psfKernelDirectory",this.psfKernelDirectory); properties.setProperty(prefix+"psfKernelDirectory",this.psfKernelDirectory);
properties.setProperty(prefix+"aberrationsKernelDirectory",this.aberrationsKernelDirectory); properties.setProperty(prefix+"aberrationsKernelDirectory",this.aberrationsKernelDirectory);
properties.setProperty(prefix+"calibrationDirectory",this.calibrationDirectory); properties.setProperty(prefix+"calibrationDirectory",this.calibrationDirectory);
properties.setProperty(prefix+"autoRestore",this.autoRestore+""); properties.setProperty(prefix+"autoRestore",this.autoRestore+"");
properties.setProperty(prefix+"calibrationPath",this.calibrationPath); properties.setProperty(prefix+"calibrationPath",this.calibrationPath);
properties.setProperty(prefix+"strategyPath",this.strategyPath); properties.setProperty(prefix+"strategyPath",this.strategyPath);
...@@ -4869,6 +4870,7 @@ public class EyesisAberrations { ...@@ -4869,6 +4870,7 @@ public class EyesisAberrations {
if (properties.getProperty(prefix+"sourceDirectory")!=null) this.sourceDirectory=properties.getProperty(prefix+"sourceDirectory"); if (properties.getProperty(prefix+"sourceDirectory")!=null) this.sourceDirectory=properties.getProperty(prefix+"sourceDirectory");
if (properties.getProperty(prefix+"partialKernelDirectory")!=null) this.partialKernelDirectory=properties.getProperty(prefix+"partialKernelDirectory"); if (properties.getProperty(prefix+"partialKernelDirectory")!=null) this.partialKernelDirectory=properties.getProperty(prefix+"partialKernelDirectory");
if (properties.getProperty(prefix+"illustrationsDirectory")!=null) this.illustrationsDirectory=properties.getProperty(prefix+"illustrationsDirectory"); if (properties.getProperty(prefix+"illustrationsDirectory")!=null) this.illustrationsDirectory=properties.getProperty(prefix+"illustrationsDirectory");
if (properties.getProperty(prefix+"capturedDirectory")!=null) this.capturedDirectory=properties.getProperty(prefix+"capturedDirectory");
if (properties.getProperty(prefix+"psfKernelDirectory")!=null) this.psfKernelDirectory=properties.getProperty(prefix+"psfKernelDirectory"); if (properties.getProperty(prefix+"psfKernelDirectory")!=null) this.psfKernelDirectory=properties.getProperty(prefix+"psfKernelDirectory");
if (properties.getProperty(prefix+"aberrationsKernelDirectory")!=null) this.aberrationsKernelDirectory=properties.getProperty(prefix+"aberrationsKernelDirectory"); if (properties.getProperty(prefix+"aberrationsKernelDirectory")!=null) this.aberrationsKernelDirectory=properties.getProperty(prefix+"aberrationsKernelDirectory");
if (properties.getProperty(prefix+"calibrationDirectory")!=null) this.calibrationDirectory=properties.getProperty(prefix+"calibrationDirectory"); if (properties.getProperty(prefix+"calibrationDirectory")!=null) this.calibrationDirectory=properties.getProperty(prefix+"calibrationDirectory");
...@@ -5023,6 +5025,8 @@ public class EyesisAberrations { ...@@ -5023,6 +5025,8 @@ public class EyesisAberrations {
gd.addCheckbox("Select partial kernels directory", false); gd.addCheckbox("Select partial kernels directory", false);
gd.addStringField("Illustrations directory", this.illustrationsDirectory, 60); gd.addStringField("Illustrations directory", this.illustrationsDirectory, 60);
gd.addCheckbox("Select illustrations directory", false); gd.addCheckbox("Select illustrations directory", false);
gd.addStringField("Captured images directory", this.capturedDirectory, 60);
gd.addCheckbox("Select captured images directory", false);
gd.addStringField("Combined kernels directory", this.psfKernelDirectory, 60); gd.addStringField("Combined kernels directory", this.psfKernelDirectory, 60);
gd.addCheckbox("Select combined kernsls directory", false); gd.addCheckbox("Select combined kernsls directory", false);
gd.addStringField("Aberrations kernels directory", this.aberrationsKernelDirectory, 60); gd.addStringField("Aberrations kernels directory", this.aberrationsKernelDirectory, 60);
...@@ -5078,6 +5082,8 @@ public class EyesisAberrations { ...@@ -5078,6 +5082,8 @@ public class EyesisAberrations {
if (gd.getNextBoolean()) selectPartialKernelDirectory(false, this.partialKernelDirectory, false); if (gd.getNextBoolean()) selectPartialKernelDirectory(false, this.partialKernelDirectory, false);
this.illustrationsDirectory=gd.getNextString(); this.illustrationsDirectory=gd.getNextString();
if (gd.getNextBoolean()) selectIllustrationsDirectory(false, this.illustrationsDirectory, false); if (gd.getNextBoolean()) selectIllustrationsDirectory(false, this.illustrationsDirectory, false);
this.capturedDirectory=gd.getNextString();
if (gd.getNextBoolean()) selectCapturedDirectory(false, this.capturedDirectory, false);
this.psfKernelDirectory=gd.getNextString(); this.psfKernelDirectory=gd.getNextString();
if (gd.getNextBoolean()) selectPSFKernelDirectory(false, this.psfKernelDirectory, false); if (gd.getNextBoolean()) selectPSFKernelDirectory(false, this.psfKernelDirectory, false);
this.aberrationsKernelDirectory=gd.getNextString(); this.aberrationsKernelDirectory=gd.getNextString();
...@@ -5153,6 +5159,18 @@ public class EyesisAberrations { ...@@ -5153,6 +5159,18 @@ public class EyesisAberrations {
return dir; return dir;
} }
public String selectCapturedDirectory(boolean smart, String defaultPath, boolean newAllowed) {
String dir= CalibrationFileManagement.selectDirectory(
smart,
newAllowed, // save
"Captured images directory", // title
"Select captured images directory", // button
null, // filter
defaultPath); //this.sourceDirectory);
if (dir!=null) this.capturedDirectory=dir;
return dir;
}
public String selectPSFKernelDirectory(boolean smart, String defaultPath, boolean newAllowed) { public String selectPSFKernelDirectory(boolean smart, String defaultPath, boolean newAllowed) {
String dir= CalibrationFileManagement.selectDirectory( String dir= CalibrationFileManagement.selectDirectory(
smart, smart,
......
...@@ -325,6 +325,10 @@ public class GenericJTabbedDialog implements ActionListener { ...@@ -325,6 +325,10 @@ public class GenericJTabbedDialog implements ActionListener {
} else if (e.getActionCommand().equals("OK")) { } else if (e.getActionCommand().equals("OK")) {
result = e.getActionCommand(); result = e.getActionCommand();
jd.dispose(); jd.dispose();
// Added 07/18/2021 - button names starting with "_" exit from dialog
} else if ((e.getActionCommand().length()>0) && (e.getActionCommand().charAt(0) == '_')){
result = e.getActionCommand().substring(1);
jd.dispose();
} }
} }
...@@ -332,6 +336,9 @@ public class GenericJTabbedDialog implements ActionListener { ...@@ -332,6 +336,9 @@ public class GenericJTabbedDialog implements ActionListener {
public boolean wasCanceled() { public boolean wasCanceled() {
return (result == null) || (result.equals("Cancel")); return (result == null) || (result.equals("Cancel"));
} }
public boolean wasOKed() {
return result.equals("OK");
}
private boolean skipComments ( private boolean skipComments (
boolean incTab) { // increment tab if nothing left in this one (false - keep read_component equal to tab's components length boolean incTab) { // increment tab if nothing left in this one (false - keep read_component equal to tab's components length
......
...@@ -2721,7 +2721,8 @@ public class EyesisCorrections { ...@@ -2721,7 +2721,8 @@ public class EyesisCorrections {
if (debugLevel > 0) System.out.println("Saving RGBA result to "+path+".png"); if (debugLevel > 0) System.out.println("Saving RGBA result to "+path+".png");
(new EyesisTiff()).savePNG_ARGB32( (new EyesisTiff()).savePNG_ARGB32(
imp, imp,
path +".png" path +".png",
debugLevel
); );
} else { } else {
......
...@@ -1157,7 +1157,7 @@ public class JP46_Reader_camera implements PlugIn, ActionListener { ...@@ -1157,7 +1157,7 @@ public class JP46_Reader_camera implements PlugIn, ActionListener {
try { try {
url = new URL(cameraurl); url = new URL(cameraurl);
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
System.out.println("Bad URL: " + cameraurl); System.out.println("Bad URL4: " + cameraurl);
return null; return null;
} }
......
...@@ -1096,6 +1096,9 @@ public class Lwir16Reader { ...@@ -1096,6 +1096,9 @@ public class Lwir16Reader {
set_dir.mkdirs(); // including parent set_dir.mkdirs(); // including parent
LOGGER.warn("Saving image set to: "+set_dir.getAbsolutePath()); LOGGER.warn("Saving image set to: "+set_dir.getAbsolutePath());
for (ImagePlus imp:imgs) { for (ImagePlus imp:imgs) {
if (imp==null) { // channel was not selected?
continue;
}
String fname = imp.getTitle(); String fname = imp.getTitle();
// fname = fname.substring(0, fname.lastIndexOf('_')) + ".tiff"; // remove _average // fname = fname.substring(0, fname.lastIndexOf('_')) + ".tiff"; // remove _average
// fname = fname.substring(0, fname.lastIndexOf('.')) + ".tiff"; // remove _average // fname = fname.substring(0, fname.lastIndexOf('.')) + ".tiff"; // remove _average
...@@ -1199,9 +1202,18 @@ public class Lwir16Reader { ...@@ -1199,9 +1202,18 @@ public class Lwir16Reader {
public boolean programLWIRCamera(LwirReaderParameters lrp) {
return programLWIRCamera(lrp, 0);
}
/**
* Program all 5 cameras for calibration mode
* @param lrp LWIR Reader parameters
* @param compressor_run 0 - exit with compressors stopped, 2 - keep compressors running
* @return true if OK, false otherwise
*/
public boolean programLWIRCamera(LwirReaderParameters lrp) { public boolean programLWIRCamera(LwirReaderParameters lrp, int compressor_run) {
String [] all_IPs = lrp.getAllIPs(); String [] all_IPs = lrp.getAllIPs();
String [] lwir_IPs = lrp.getLwirIPs(); String [] lwir_IPs = lrp.getLwirIPs();
String eo_ip = lrp.getEOIP(); String eo_ip = lrp.getEOIP();
...@@ -1228,12 +1240,13 @@ public class Lwir16Reader { ...@@ -1228,12 +1240,13 @@ public class Lwir16Reader {
"&XMIT_TIMESTAMP=1"; "&XMIT_TIMESTAMP=1";
} }
for (int i = 0; i < lwir_IPs.length; i++) { // Alpply to only 4 lwir cameras, port 0 (some to all ports) for (int i = 0; i < lwir_IPs.length; i++) { // Apply to only 4 lwir cameras, port 0 (some to all ports)
urls[i] += "&TRIG_DELAY="+lrp.lwir_trig_dly+"&*TRIG_DELAY=15"+ // apply to all ports urls[i] += "&TRIG_DELAY="+lrp.lwir_trig_dly+"&*TRIG_DELAY=15"+ // apply to all ports
"&BITS=16&*BITS=15"+ "&BITS=16&*BITS=15"+
"&COLOR="+COLOR_RAW +"&*COLOR=15"+ "&COLOR="+COLOR_RAW +"&*COLOR=15"+
"&WOI_HEIGHT="+(LWIR_HEIGHT + (lrp.lwir_telemetry?LWIR_TELEMETRY_LINES:0))+"&*WOI_HEIGHT=15"+ "&WOI_HEIGHT="+(LWIR_HEIGHT + (lrp.lwir_telemetry?LWIR_TELEMETRY_LINES:0))+"&*WOI_HEIGHT=15"+
"&"+REG_FFC_FRAMES+"="+lrp.getFFCFrames() +"&*"+REG_FFC_FRAMES+"=15"; // apply to all channels "&"+REG_FFC_FRAMES+"="+lrp.getFFCFrames() +"&*"+REG_FFC_FRAMES+"=15"; // apply to all channels
urls[i] += "&COMPRESSOR_RUN=2&*COMPRESSOR_RUN=15"; // turn compressor and keep fort at least one frame after TRIG=4
} }
for (int chn:lrp.eo_channels) { // add color settings to all EO channels for (int chn:lrp.eo_channels) { // add color settings to all EO channels
...@@ -1276,6 +1289,9 @@ public class Lwir16Reader { ...@@ -1276,6 +1289,9 @@ public class Lwir16Reader {
"&WOI_TOP=0"+ "&WOI_TOP=0"+
"&WOI_WIDTH=2592"+ "&WOI_WIDTH=2592"+
"&WOI_HEIGHT=1936"; "&WOI_HEIGHT=1936";
if (chn == 0) {
urls[all_IPs.length-1] += "&COMPRESSOR_RUN=2&*COMPRESSOR_RUN=15"; // turn compressor and keep fort at least one frame after TRIG=4
}
} }
} }
// run all programming not including TRIG=4 // run all programming not including TRIG=4
...@@ -1303,7 +1319,8 @@ public class Lwir16Reader { ...@@ -1303,7 +1319,8 @@ public class Lwir16Reader {
// set external trigger mode for all LWIR and EO cameras // set external trigger mode for all LWIR and EO cameras
urls = new String[all_IPs.length]; urls = new String[all_IPs.length];
for (int i = 0; i < urls.length; i++) { for (int i = 0; i < urls.length; i++) {
urls[i] = "http://"+all_IPs[i]+"/parsedit.php?immediate&sensor_port=0&TRIG=4&*TRIG=15"; urls[i] = "http://"+all_IPs[i]+"/parsedit.php?immediate&sensor_port=0&TRIG=4&*TRIG=15"+
"&COMPRESSOR_RUN=" + compressor_run +"*5&*COMPRESSOR_RUN=15"; // delay turning off COMPRESSOR_RUN
} }
docs = collectXmlResponses(urls); docs = collectXmlResponses(urls);
......
...@@ -44,6 +44,9 @@ public class LwirReaderParameters { ...@@ -44,6 +44,9 @@ public class LwirReaderParameters {
public final static int [] FFC_GROUPS= {1,2,4}; public final static int [] FFC_GROUPS= {1,2,4};
public static final String [] SENSOR_TYPES = {"EO","LWIR"}; public static final String [] SENSOR_TYPES = {"EO","LWIR"};
public static final String SENSOR_TYPE = "SENSOR_TYPE"; public static final String SENSOR_TYPE = "SENSOR_TYPE";
public final static int TYPE_EO= 0;
public final static int TYPE_LWIR= 1;
protected static int MAX_LWIR_WIDTH = 1024; // protected static int MAX_LWIR_WIDTH = 1024; //
private boolean parameters_updated = false; private boolean parameters_updated = false;
...@@ -168,7 +171,7 @@ public class LwirReaderParameters { ...@@ -168,7 +171,7 @@ public class LwirReaderParameters {
public int [] getTypeMap() { // eo - 0, lwir - 1 public int [] getTypeMap() { // eo - 0, lwir - 1
int [] types = new int [getNumChannels()]; int [] types = new int [getNumChannels()];
for (int i = 0; i < types.length; i++) { for (int i = 0; i < types.length; i++) {
types[i] = (i >= getEoChn0())? 0 : 1; types[i] = (i >= getEoChn0())? TYPE_EO : TYPE_LWIR;
} }
return types; return types;
} }
...@@ -195,7 +198,7 @@ public class LwirReaderParameters { ...@@ -195,7 +198,7 @@ public class LwirReaderParameters {
if (imp.getProperty(SENSOR_TYPE)!=null) { if (imp.getProperty(SENSOR_TYPE)!=null) {
return (is_LWIR((String) imp.getProperty(SENSOR_TYPE)))? 1:0; return (is_LWIR((String) imp.getProperty(SENSOR_TYPE)))? 1:0;
} }
return is_LWIR(imp.getWidth())? 1 : 0; return is_LWIR(imp.getWidth())? TYPE_LWIR : TYPE_EO;
} }
......
...@@ -172,7 +172,7 @@ public class ElphelJp4Reader extends ImageIOReader{ ...@@ -172,7 +172,7 @@ public class ElphelJp4Reader extends ImageIOReader{
try { try {
url = new URL(id); url = new URL(id);
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
LOGGER.warn("Bad URL: " + id); LOGGER.warn("Bad URL1: " + id);
} }
if (url != null) { if (url != null) {
LOGGER.debug("Starting initFile() method, read "+ id +" to memory first"); LOGGER.debug("Starting initFile() method, read "+ id +" to memory first");
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
** **
*/ */
package com.elphel.imagej.readers; package com.elphel.imagej.readers;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
...@@ -187,11 +188,21 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader { ...@@ -187,11 +188,21 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
url = null; url = null;
// String mime = null; // use to select jp4/tiff later? Or to check it is correct // String mime = null; // use to select jp4/tiff later? Or to check it is correct
content_fileName = null; content_fileName = null;
boolean bad_file = false;
try {
File test_file = new File(id);
test_file.getCanonicalPath();
} catch (IOException e) {
bad_file = true;
}
if (bad_file) {
try { try {
url = new URL(id); url = new URL(id);
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
LOGGER.warn("Bad URL: " + id); LOGGER.warn("Bad URL2: " + id);
} }
}
if (url != null) { if (url != null) {
LOGGER.debug("Starting initFile() method, read "+ id +" to memory first"); LOGGER.debug("Starting initFile() method, read "+ id +" to memory first");
//https://www.rgagnon.com/javadetails/java-0487.html //https://www.rgagnon.com/javadetails/java-0487.html
......
...@@ -258,10 +258,24 @@ the type of pixel data in this file getPixelType() ...@@ -258,10 +258,24 @@ the type of pixel data in this file getPixelType()
ImagePlus imp, ImagePlus imp,
String path String path
){ ){
savePNG_ARGB32(
imp,
path,
1 // will print - for cdompatibility with older code
);
}
public void savePNG_ARGB32(
ImagePlus imp,
String path,
int debug_level
){
int width = imp.getWidth(); int width = imp.getWidth();
int height = imp.getHeight(); int height = imp.getHeight();
int [] pixels = (int []) imp.getProcessor().getPixels(); int [] pixels = (int []) imp.getProcessor().getPixels();
if (debug_level > 0) {
System.out.println("savePNG_ARGB32("+path+"): width="+width+", height="+height+" length="+pixels.length); System.out.println("savePNG_ARGB32("+path+"): width="+width+", height="+height+" length="+pixels.length);
}
DataBufferInt buffer = new DataBufferInt(pixels, pixels.length); DataBufferInt buffer = new DataBufferInt(pixels, pixels.length);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
*/ */
package com.elphel.imagej.readers; package com.elphel.imagej.readers;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
...@@ -141,13 +142,26 @@ public class ImagejJp4Tiff { ...@@ -141,13 +142,26 @@ public class ImagejJp4Tiff {
public ImagePlus readTiffJp4(String path_url, boolean scale, String std ) throws IOException, FormatException { // std - include non-elphel properties with prefix std public ImagePlus readTiffJp4(String path_url, boolean scale, String std ) throws IOException, FormatException { // std - include non-elphel properties with prefix std
// determine if it is a file or URL and read url to memory // determine if it is a file or URL and read url to memory
// If URL, then read to memory, if normal file - use direct access // If URL, then read to memory, if normal file - use direct access
if (path_url == null) {
LOGGER.warn("readTiffJp4(): null path_url");
return null;
}
url = null; url = null;
// String mime = null; // use to select jp4/tiff later? Or to check it is correct // String mime = null; // use to select jp4/tiff later? Or to check it is correct
content_fileName = null; content_fileName = null;
boolean bad_file = false;
try {
File test_file = new File(path_url); // null
test_file.getCanonicalPath();
} catch (IOException e) {
bad_file = true;
}
if (bad_file) {
try { try {
url = new URL(path_url); url = new URL(path_url);
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
LOGGER.warn("Bad URL: " + path_url); LOGGER.warn("Bad URL3: " + path_url);
}
} }
//https://stackoverflow.com/questions/39086500/read-http-response-header-and-body-from-one-http-request-in-java //https://stackoverflow.com/questions/39086500/read-http-response-header-and-body-from-one-http-request-in-java
if (url != null) { if (url != null) {
......
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