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

debugging illustrations

parent 7c9b8ed9
......@@ -667,7 +667,9 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
public static Goniometer GONIOMETER=null;
public static LwirReaderParameters LWIR_PARAMETERS = new LwirReaderParameters();
public static CalibrationIllustrationParameters CALIBRATION_ILLUSTRATION_PARAMETERS = new CalibrationIllustrationParameters(LWIR_PARAMETERS);
public static CalibrationIllustrationParameters CALIBRATION_ILLUSTRATION_PARAMETERS = new CalibrationIllustrationParameters(
LWIR_PARAMETERS,
EYESIS_CAMERA_PARAMETERS);
// new CalibrationHardwareInterface.LaserPointers();
public class SyncCommand{
public boolean isRunning= false;
......@@ -1069,6 +1071,7 @@ if (MORE_BUTTONS) {
panelIllustrations.setLayout(new GridLayout(1, 0, 5, 5)); // rows, columns, vgap, hgap
addButton("Illustrations Configure", panelIllustrations,color_configure);
addButton("Illustrations", panelIllustrations,color_bundle);
addButton("Remove Bad grids", panelIllustrations,color_stop);
add(panelIllustrations);
......@@ -9434,22 +9437,29 @@ if (MORE_BUTTONS) {
LENS_DISTORTIONS, // Distortions distortions,
SYNC_COMMAND.stopRequested, // AtomicInteger stopRequested,
MASTER_DEBUG_LEVEL); // int debug_level);
/*
CALIBRATION_ILLUSTRATION = new CalibrationIllustration(
LWIR_PARAMETERS, // LwirReaderParameters lwirReaderParameters,
LENS_DISTORTION_PARAMETERS, // LensDistortionParameters lensDistortionParameters,
PATTERN_PARAMETERS, // PatternParameters patternParameters,
REFINE_PARAMETERS, // RefineParameters refineParameters,
DISTORTION_PROCESS_CONFIGURATION, // DistortionProcessConfiguration distortionProcessConfiguration,
EYESIS_CAMERA_PARAMETERS, // EyesisCameraParameters eyesisCameraParameters,
SYNC_COMMAND.stopRequested, // AtomicInteger stopRequested,
MASTER_DEBUG_LEVEL); // int debug_level);
*/
}
// CALIBRATION_ILLUSTRATION.selectUsefulGrids();
CALIBRATION_ILLUSTRATION.convertSourceFiles();
return;
}
/* ======================================================================== */
if (label.equals("Remove Bad grids")) {
if (LENS_DISTORTIONS==null) {
IJ.showMessage("LENS_DISTORTION is not set"); // to use all grids imported
return;
}
EYESIS_ABERRATIONS.setDistortions(LENS_DISTORTIONS);
if (CALIBRATION_ILLUSTRATION == null) {
CALIBRATION_ILLUSTRATION = new CalibrationIllustration(
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.removeBadGrids();
return;
}
/* ======================================================================== */
if (label.equals("Manual hint")) {
package com.elphel.imagej.calibration;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Rectangle;
import java.io.File;
......@@ -20,6 +21,9 @@ import ij.gui.Line;
import ij.process.ImageProcessor;
public class CalibrationIllustration {
public static final int MAX_THREADS = 100; // combine from all classes?
public static final int CONTRAST_INDEX = 2;
EyesisAberrations eyesisAberrations;
Distortions distortions;
CalibrationIllustrationParameters illustrationParameters;
......@@ -49,18 +53,23 @@ public class CalibrationIllustration {
public void plotGrid(
int numImg,
int line_width,
ImagePlus imp,
Color color_grid,
Color color_grid_extra // at least one end points to extra (unreliable) nodes (may be null)
Color color_grid,
Color color_grid_weak,
Color color_grid_extra, // at least one end points to extra (unreliable) nodes (may be null)
double weak_threshold
) {
int line_width = 1; //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;
GridImageParameters gip = dcd.gIP[numImg];
int [][] pUV = gip.pixelsUV;
int [][] pUV_extra = gip.pixelsUV_extra;
double [][] pXY = gip.pixelsXY;
double [][] pXY_extra = gip.pixelsXY_extra;
if ((pUV == null) || (pUV.length==0)) {
return;
}
int minU=pUV[0][0],maxU=minU,minV=pUV[0][1],maxV=minV;
for (int i = 0; i < pUV.length; i++) {
if (pUV[i][0] < minU) minU = pUV[i][0];
......@@ -93,6 +102,17 @@ public class CalibrationIllustration {
}
ImageProcessor ip = imp.getProcessor();
ip.setLineWidth(line_width);
// only use stroke for line_width>1
/*
BasicStroke stroke = null;
if (line_width>1) {
stroke = new BasicStroke(line_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
}
*/
// BasicStroke stroke = new BasicStroke(line_width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
// BasicStroke stroke = new BasicStroke(line_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
// roi.setStrokeColor(new Color(red, green, blue, alpha));
// roi.setStroke(stroke);
// int upper = dimsUV.width * (dimsUV.height-1);
int upper = dimsUV.width * dimsUV.height;
for (int indx = dimsUV.width + 1; indx < upper; indx++) if (grid[indx] >= 0){
......@@ -103,15 +123,52 @@ public class CalibrationIllustration {
if (indx1 < grid.length) {
int g1 = grid[indx1];
if (g1 >= 0) {
double [] pXY0 = (g0 < main_len) ? pXY[g0] : pXY_extra[g0 - main_len];
double [] pXY1 = (g1 < main_len) ? pXY[g1] : pXY_extra[g1 - main_len];
// Line line = new Line(pXY0[0], pXY0[1], pXY1[0],pXY1[1]);
if ((g0 < main_len) && (g1 < main_len)) {
ip.setColor(color_grid);
if ((pXY0[CONTRAST_INDEX] >= weak_threshold) && (pXY1[CONTRAST_INDEX] >= weak_threshold)) {
if (color_grid == null) {
continue;
}
ip.setColor(color_grid);
} else {
if (color_grid_weak == null) {
continue;
}
ip.setColor(color_grid_weak);
}
} else {
if (color_grid_extra == null) {
continue;
}
ip.setColor(color_grid_extra); // should not get here with color_grid_extra==null
}
double [] pXY0 = (g0 < main_len) ? pXY[g0] : pXY_extra[g0 - main_len];
double [] pXY1 = (g1 < main_len) ? pXY[g1] : pXY_extra[g1 - main_len];
Line line = new Line(pXY0[0], pXY0[1], pXY1[0],pXY1[1]);
line.drawPixels(ip);
/*
if (stroke != null) {
if ((g0 < main_len) && (g1 < main_len)) {
line.setStrokeColor(color_grid);
} else {
line.setStrokeColor(color_grid_extra); // should not get here with color_grid_extra==null
}
line.setStroke(stroke);
}
line.setStrokeWidth(1.0);
*/
for (int dy = -line_width+1; dy < line_width; dy+=2) {
for (int dx = -line_width+1; dx < line_width; dx+=2) {
Line line = new Line(pXY0[0] + 0.5*dx, pXY0[1] + 0.5*dy, pXY1[0] + 0.5*dx,pXY1[1] + 0.5*dy);
line.drawPixels(ip);
}
}
// Line line = new Line(pXY0[0], pXY0[1], pXY1[0],pXY1[1]);
// line.drawPixels(ip);
/*
for (double lw = 0.5; lw <= line_width; lw+=0.5) {
line.setStrokeWidth(lw);
line.drawPixels(ip);
}
*/
}
}
}
......@@ -119,160 +176,280 @@ public class CalibrationIllustration {
}
public boolean convertSourceFiles() {
double threshold_contrast = 10.0;
int threshold_number = 10; // grid should have this number of nodes with above-threshold contrast
int CONTRAST_INDEX = 2;
//this.eyesisCameraParameters.numStations
boolean [] selectedChannels = eyesisAberrations.aberrationParameters.getChannelSelection(distortions);
DistortionCalibrationData dcd = distortions.fittingStrategy.distortionCalibrationData;
int numStations = dcd.eyesisCameraParameters.getNumStations();
boolean [] station_sel = new boolean[numStations];
// Arrays.fill(station_sel, true);
station_sel[0]= true; // only 06-L
MultipleExtensionsFileFilter sourceFilter =
long startTime=System.nanoTime(); // restart timer after possible interactive dialogs
final boolean [] selectedChannels = eyesisAberrations.aberrationParameters.getChannelSelection(distortions);
final DistortionCalibrationData dcd = distortions.fittingStrategy.distortionCalibrationData;
final MultipleExtensionsFileFilter sourceFilter =
new MultipleExtensionsFileFilter("",src_extensions,"Source calibration images");
int lwir0 = illustrationParameters.getLwirReaderParameters().getLwirChn0();
int eo0 = illustrationParameters.getLwirReaderParameters().getEoChn0();
for (int nChn = 0; nChn < selectedChannels.length; nChn++) if (selectedChannels[nChn]) {
// iterate through all image set (some grids may be missing)
for (int nSet = 0; nSet < dcd.gIS.length; nSet++) {
if (station_sel[dcd.gIS[nSet].getStationNumber()]) { // some stations only
// construct source file name
String srcPath = null;
int numImg = -1;
if (dcd.gIS[nSet].imageSet[nChn] != null) {
srcPath = dcd.gIS[nSet].imageSet[nChn].source_path;
numImg = dcd.gIS[nSet].imageSet[nChn].getImageNumber();
} else {
// find other non-null
for (int i = 0; i < dcd.gIS[nSet].imageSet.length; i++) {
if (dcd.gIS[nSet].imageSet[i] != null) {
String other_path = dcd.gIS[nSet].imageSet[i].source_path;
String set_path = other_path.substring(0,other_path.lastIndexOf(Prefs.getFileSeparator()));
File set_dir = new File(set_path);
String [] sfiles = set_dir.list(sourceFilter);
for (String spath:sfiles) {
int chn = DistortionCalibrationData.pathToChannel(spath);
if (chn == nChn) {
srcPath = (new File(set_dir,spath)).getPath();
break;
}
}
break;
final int lwir0 = illustrationParameters.getLwirReaderParameters().getLwirChn0();
final int eo0 = illustrationParameters.getLwirReaderParameters().getEoChn0();
final Thread[] threads = newThreadArray(MAX_THREADS);
final AtomicInteger indxAtomic = new AtomicInteger(0);
for (int iChn = 0; iChn < selectedChannels.length; iChn++) if (selectedChannels[iChn]) {
final int nChn=iChn;
indxAtomic.set(0);
// Create directory before threads
String illustrations_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory;
String chn_ill_dir = illustrations_dir+Prefs.getFileSeparator()+ illustrationParameters.getChannelPrefix()+String.format("%02d", nChn);
// create directory if it does not exist
File destDir= new File (chn_ill_dir);
if (!destDir.exists()){
if (!destDir.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 nSet = indxAtomic.getAndIncrement(); nSet < dcd.gIS.length; nSet = indxAtomic.getAndIncrement()) {
int station = dcd.gIS[nSet].getStationNumber();
if (illustrationParameters.useStation(station)) { // some stations only
// construct source file name
String srcPath = null;
int numImg = -1;
if (dcd.gIS[nSet].imageSet[nChn] != null) {
srcPath = dcd.gIS[nSet].imageSet[nChn].source_path;
numImg = dcd.gIS[nSet].imageSet[nChn].getImageNumber();
} else {
// find other non-null
for (int i = 0; i < dcd.gIS[nSet].imageSet.length; i++) {
if (dcd.gIS[nSet].imageSet[i] != null) {
String other_path = dcd.gIS[nSet].imageSet[i].source_path;
String set_path = other_path.substring(0,other_path.lastIndexOf(Prefs.getFileSeparator()));
File set_dir = new File(set_path);
String [] sfiles = set_dir.list(sourceFilter);
for (String spath:sfiles) {
int chn = DistortionCalibrationData.pathToChannel(spath);
if (chn == nChn) {
srcPath = (new File(set_dir,spath)).getPath();
break;
}
}
break;
}
}
}
// open 32-bit image
if (srcPath == null) {
System.out.println ("Source image for set "+nSet+", channel "+nChn+" does not exist");
continue;
}
ImagePlus imp = new ImagePlus(srcPath);
// convert to 8-bit color?
int width = imp.getWidth();
int height = imp.getHeight();
float [] pixels = (float[]) imp.getProcessor().getPixels();
String title = imp.getTitle();
if (title.lastIndexOf(".") > 0) {
title = title.substring(0, title.lastIndexOf("."));
}
String title_annot = title+"-annot";
if (illustrationParameters.useStationInFilenames()) {
title_annot = "station-"+station+"_"+title_annot;
}
if (numImg >=0) { // check if it is a bad image
int num_above = 0;
GridImageParameters gip = dcd.gIP[numImg];
double [][] pXY = gip.pixelsXY;
for (int i = 0; i < pXY.length; i++ ) {
if (pXY[i][CONTRAST_INDEX] > illustrationParameters.getThresholdContrast()) num_above++;
}
if (num_above < illustrationParameters.getThresholdNumber()) {
title_annot += "-BAD";
}
} else {
title_annot += "-EMPTY";
}
int sensor_type = dcd.eyesisCameraParameters.getSensorType(nChn);
ImageStack stack = null;
double [][] pseudo_pixels;
int line_width = 1;
if (sensor_type == 1) {
pseudo_pixels = new double [4] [pixels.length];
ThermalColor tc = new ThermalColor(
illustrationParameters.getPalette(), // public int lwir_palette = 0; // 0 - white - hot, 1 - black - hot, 2+ - colored
illustrationParameters.getLwirRange(nChn- lwir0)[0],
illustrationParameters.getLwirRange(nChn- lwir0)[1],
255.0);
for (int i = 0; i < pixels.length; i++) {
double [] rgb = tc.getRGB((double) pixels[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
}
line_width = illustrationParameters.getLineWidthLwir();
} else { // eo
double [][] drgb = MatchSimulatedPattern.simpleDemosaic(
imp,
illustrationParameters.eo_rb2g_hi[nChn-eo0][0], // r2g,
illustrationParameters.eo_rb2g_hi[nChn-eo0][1], // b2g,
illustrationParameters.getSaturation(), // saturation,
illustrationParameters.getGamma(), // gamma,
illustrationParameters.getMinLin(), //minlin_gamma, // do not apply gamma to lower values
illustrationParameters.eo_rb2g_hi[nChn-eo0][2]); // ,rgb_hi); // map to 255, gamma will preserve
pseudo_pixels = new double [4][];
for (int i = 0; i < drgb.length; i++) {
pseudo_pixels[i] = drgb[i];
}
pseudo_pixels[3] = new double [pseudo_pixels[0].length];
Arrays.fill(pseudo_pixels[3], 1.0);
line_width = illustrationParameters.getLineWidthEo();
}
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_annot = EyesisCorrections.convertRGBAFloatToRGBA32(
stack, // ImageStack stackFloat, //r,g,b,a
// name+"ARGB"+suffix, // String title,
title_annot, // 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 (numImg >=0) {
plotGrid(numImg,
line_width,
imp_annot,
illustrationParameters.getGridColor(), // new Color(250, 0, 0), // color_grid,
illustrationParameters.getGridWeakColor(), // new Color(250, 0, 0), // color_grid,
illustrationParameters.getGridExtraColor(), // new Color(200, 200,0) // null // //at least one end points to extra (unreliable) nodes
illustrationParameters.getThresholdContrast()
);
}
String illustrations_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory;
String chn_ill_dir = illustrations_dir+Prefs.getFileSeparator()+ illustrationParameters.getChannelPrefix()+String.format("%02d", nChn);
// create directory if it does not exist
File destDir= new File (chn_ill_dir);
if (!destDir.exists()){ // Should be created before threads !
if (!destDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+chn_ill_dir+". *** It should be already created! ***");
continue;
}
}
EyesisCorrections.saveAndShow(
imp_annot,
chn_ill_dir,
illustrationParameters.save_png,
false, // show
illustrationParameters.JPEG_quality, // <0 - keep current, 0 - force Tiff, >0 use for JPEG
0); // debug_level);
}
}
}
// open 32-bit image
if (srcPath == null) {
System.out.println ("Source image for set "+nSet+", channel "+nChn+" does not exist");
continue;
}
ImagePlus imp = new ImagePlus(srcPath);
// convert to 8-bit color?
int width = imp.getWidth();
int height = imp.getHeight();
float [] pixels = (float[]) imp.getProcessor().getPixels();
String title = imp.getTitle();
if (title.lastIndexOf(".") > 0) {
title = title.substring(0, title.lastIndexOf("."));
}
String title_annot = title+"-annot";
if (numImg >=0) { // check if it is a bad image
int num_above = 0;
GridImageParameters gip = dcd.gIP[numImg];
double [][] pXY = gip.pixelsXY;
for (int i = 0; i < pXY.length; i++ ) {
if (pXY[i][CONTRAST_INDEX] > threshold_contrast) num_above++;
}
if (num_above < threshold_number) {
title_annot = title+"-annot"+"-BAD";
}
}
double [][] pseudo_pixels = new double [4] [pixels.length];
ThermalColor tc = new ThermalColor(
illustrationParameters.getPalette(), // public int lwir_palette = 0; // 0 - white - hot, 1 - black - hot, 2+ - colored
illustrationParameters.getLwirRange(nChn- lwir0)[0],
illustrationParameters.getLwirRange(nChn- lwir0)[1],
255.0);
for (int i = 0; i < pixels.length; i++) {
double [] rgb = tc.getRGB((double) pixels[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, // 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_annot = EyesisCorrections.convertRGBAFloatToRGBA32(
stack, // ImageStack stackFloat, //r,g,b,a
// name+"ARGB"+suffix, // String title,
title_annot, // 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 (numImg >=0) {
plotGrid(numImg,
imp_annot,
new Color(250, 0, 0), // color_grid,
new Color(200, 200,0) // null // //at least one end points to extra (unreliable) nodes
);
}
// imp_pseudo.getProcessor().resetMinAndMax();
// imp_pseudo.show();
String illustrations_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory;
String chn_ill_dir = illustrations_dir+Prefs.getFileSeparator()+ illustrationParameters.channel_dir_prefix+String.format("%02d", nChn);
// create directory if it does not exist
File destDir= new File (chn_ill_dir);
if (!destDir.exists()){
if (!destDir.mkdirs()) {
IJ.showMessage("Error","Failed to create results directory "+chn_ill_dir);
continue;
};
}
startAndJoin(threads);
}
System.out.println("All done in "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+" sec.");
return true;
}
public boolean removeBadGrids() {
long startTime=System.nanoTime(); // restart timer after possible interactive dialogs
final boolean [] selectedChannels = eyesisAberrations.aberrationParameters.getChannelSelection(distortions);
final DistortionCalibrationData dcd = distortions.fittingStrategy.distortionCalibrationData;
final Thread[] threads = newThreadArray(MAX_THREADS);
final AtomicInteger indxAtomic = new AtomicInteger(0);
final AtomicInteger numRemoved = new AtomicInteger(0);
for (int iChn = 0; iChn < selectedChannels.length; iChn++) if (selectedChannels[iChn]) {
final int nChn=iChn;
indxAtomic.set(0);
// Create directory before threads
String illustrations_dir = eyesisAberrations.aberrationParameters.illustrationsDirectory;
String chn_ill_dir = illustrations_dir+Prefs.getFileSeparator()+ illustrationParameters.getChannelPrefix()+String.format("%02d", nChn);
// create directory if it does not exist
File destDir= new File (chn_ill_dir);
if (!destDir.exists()){
if (!destDir.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 nSet = indxAtomic.getAndIncrement(); nSet < dcd.gIS.length; nSet = indxAtomic.getAndIncrement()) {
int station = dcd.gIS[nSet].getStationNumber();
if (illustrationParameters.useStation(station)) { // some stations only
// construct source file name
if (dcd.gIS[nSet].imageSet[nChn] != null) {
int numImg = dcd.gIS[nSet].imageSet[nChn].getImageNumber();
int num_above = 0;
GridImageParameters gip = dcd.gIP[numImg];
double [][] pXY = gip.pixelsXY;
for (int i = 0; i < pXY.length; i++ ) {
if (pXY[i][CONTRAST_INDEX] > illustrationParameters.getThresholdContrast()) num_above++;
}
if (num_above < illustrationParameters.getThresholdNumber()) {
String grid_path = dcd.getImagePath(numImg);
System.out.println("Removing bad grid file: "+grid_path);
new File(dcd.getImagePath(numImg)).delete();
numRemoved.getAndIncrement();
}
}
}
}
}
EyesisCorrections.saveAndShow(
imp_annot,
chn_ill_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("Remoded "+(numRemoved.get())+" bad grid files in "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+" sec.");
return true;
}
/*
public CalibrationIllustration (
LwirReaderParameters lwirReaderParameters,
LensDistortionParameters lensDistortionParameters,
PatternParameters patternParameters,
RefineParameters refineParameters,
DistortionProcessConfiguration distortionProcessConfiguration,
EyesisCameraParameters eyesisCameraParameters,
AtomicInteger stopRequested,
int debug_level) {
this.lwirReaderParameters = lwirReaderParameters;
this.lensDistortionParameters = lensDistortionParameters;
this.patternParameters = patternParameters;
this.refineParameters = refineParameters;
this.distortionProcessConfiguration = distortionProcessConfiguration;
this.eyesisCameraParameters = eyesisCameraParameters;
this.stopRequested = stopRequested;
this.debug_level = debug_level;
/* Create a Thread[] array as large as the number of processors available.
* From Stephan Preibisch's Multithreading.java class. See:
* http://repo.or.cz/w/trakem2.git?a=blob;f=mpi/fruitfly/general/MultiThreading.java;hb=HEAD
*/
private static Thread[] newThreadArray(int maxCPUs) {
int n_cpus = Runtime.getRuntime().availableProcessors();
if (n_cpus>maxCPUs)n_cpus=maxCPUs;
return new Thread[n_cpus];
}
*/
/* Start all given threads and wait on each of them until all are done.
* From Stephan Preibisch's Multithreading.java class. See:
* http://repo.or.cz/w/trakem2.git?a=blob;f=mpi/fruitfly/general/MultiThreading.java;hb=HEAD
*/
private static void startAndJoin(Thread[] threads)
{
for (int ithread = 0; ithread < threads.length; ++ithread)
{
threads[ithread].setPriority(Thread.NORM_PRIORITY);
threads[ithread].start();
}
try
{
for (int ithread = 0; ithread < threads.length; ++ithread)
threads[ithread].join();
} catch (InterruptedException ie)
{
throw new RuntimeException(ie);
}
}
}
package com.elphel.imagej.calibration;
import java.awt.Color;
import java.net.MalformedURLException;
import java.util.Properties;
import com.elphel.imagej.cameras.EyesisCameraParameters;
import com.elphel.imagej.common.GenericJTabbedDialog;
import com.elphel.imagej.lwir.LwirReaderParameters;
public class CalibrationIllustrationParameters {
double dflt_lwir_lo = 22500.0;
double dflt_lwir_hi = 23500.0;
LwirReaderParameters lwirReaderParameters;
double [][] lwir_ranges; // = new double [lwirReaderParameters.getLwirChannels(false).length][2];
int palette = 0; // 0 - white - hot, 1 - black - hot, 2+ - colored
String src_chn_prefix="src_chn-";
boolean save_png = true;
int JPEG_quality = 90;
String channel_dir_prefix = "chn_";
static double DFLT_LWIR_LO = 22500.0;
static double DFLT_LWIR_HI = 23500.0;
static double DFLT_EO_R2G = 1.03; // gain red relative to green
static double DFLT_EO_B2G = 1.03; // gain blue relative to green
static double DFLT_EO_HI = 255.0; // range to map to 255.0
LwirReaderParameters lwirReaderParameters;
EyesisCameraParameters eyesisCameraParameters;
public CalibrationIllustrationParameters (LwirReaderParameters lwirReaderParameters) {
double [][] lwir_ranges; // = new double [lwirReaderParameters.getLwirChannels(false).length][2];
int palette = 0; // 0 - white - hot, 1 - black - hot, 2+ - colored
String src_chn_prefix="src_chn-";
boolean save_png = true;
int JPEG_quality = 90;
String channel_dir_prefix = "chn_";
double [][] eo_rb2g_hi; // []{r2g,b2g,rgb_hi}
double eo_gamma = 0.57;
double eo_minlin_gamma = 20.0;
double eo_saturation = 1.5; // color saturation
double threshold_contrast = 10.0;
int threshold_number = 10;// grid should have this number of nodes with above-threshold contrast
int station_sel = 0xf; // bitmask: 0 - station 0; 1 - station 1, ...
boolean station_in_filenames = true;
Color color_grid = new Color(250, 0, 0, 255);
Color color_grid_weak = new Color(200, 100, 0, 128);
Color color_grid_extra = new Color(150, 150,0, 255); // at least one end points to extra (unreliable) nodes (may be null)
int line_width_eo = 3;
int line_width_lwir = 1;
public CalibrationIllustrationParameters (
LwirReaderParameters lwirReaderParameters,
EyesisCameraParameters eyesisCameraParameters) {
this.lwirReaderParameters = lwirReaderParameters;
this.eyesisCameraParameters = eyesisCameraParameters;
}
public static long getLongColor(Color color) {
return ((long) color.getRGB()) & 0xffffffffL;
}
public static Color setLongColor(long lcolor) {
if (lcolor < (1 << 24)) { // no alpha
return new Color((int) lcolor);
} else { // has alpha, may or may not fit into int
if (lcolor > Integer.MAX_VALUE) {
lcolor -= (1L << 32);
}
return new Color((int) lcolor, true);
}
}
public void setProperties(String prefix,Properties properties){
// properties.setProperty(prefix+"camera_name", this.camera_name+"");
set_parameters();
......@@ -30,8 +71,32 @@ public class CalibrationIllustrationParameters {
properties.setProperty(prefix+"save_png", this.save_png+"");
properties.setProperty(prefix+"JPEG_quality", this.JPEG_quality+"");
properties.setProperty(prefix+"channel_dir_prefix", this.channel_dir_prefix);
for (int i = 0; i < eo_rb2g_hi.length; i++) {
properties.setProperty(prefix+"eo_r2g_"+i, this.eo_rb2g_hi[i][0]+"");
properties.setProperty(prefix+"eo_b2g_"+i, this.eo_rb2g_hi[i][1]+"");
properties.setProperty(prefix+"eo_hi_"+i, this.eo_rb2g_hi[i][2]+"");
}
properties.setProperty(prefix+"eo_gamma", this.eo_gamma+"");
properties.setProperty(prefix+"eo_minlin_gamma", this.eo_minlin_gamma+"");
properties.setProperty(prefix+"eo_saturation", this.eo_saturation+"");
properties.setProperty(prefix+"threshold_contrast", this.threshold_contrast+"");
properties.setProperty(prefix+"threshold_number", this.threshold_number+"");
properties.setProperty(prefix+"station_sel", this.station_sel+"");
properties.setProperty(prefix+"station_in_filenames", this.station_in_filenames+"");
long lcolor_grid = (color_grid == null) ? -1 : getLongColor(color_grid);
long lcolor_grid_weak = (color_grid_weak == null) ? -1 : getLongColor(color_grid_weak);
long lcolor_grid_extra = (color_grid_extra == null) ? -1 : getLongColor(color_grid_extra);
properties.setProperty(prefix+"color_grid", lcolor_grid+"");
properties.setProperty(prefix+"color_grid_weak", lcolor_grid_weak+"");
properties.setProperty(prefix+"color_grid_extra", lcolor_grid_extra+"");
properties.setProperty(prefix+"line_width_eo", this.line_width_eo+"");
properties.setProperty(prefix+"line_width_lwir", this.line_width_lwir+"");
}
public void getProperties(String prefix,Properties properties){
set_parameters();
for (int i = 0; i < lwir_ranges.length; i++) {
......@@ -47,27 +112,144 @@ public class CalibrationIllustrationParameters {
if (properties.getProperty(prefix+"JPEG_quality")!=null) this.JPEG_quality = Integer.parseInt(properties.getProperty(prefix+"JPEG_quality"));
if (properties.getProperty(prefix+"channel_dir_prefix")!=null) this.channel_dir_prefix = (String) properties.getProperty(prefix+"channel_dir_prefix");
for (int i = 0; i < eo_rb2g_hi.length; i++) {
if (properties.getProperty(prefix+"eo_r2g_"+i)!=null) {
this.eo_rb2g_hi[i][0] = Double.parseDouble(properties.getProperty(prefix+"eo_r2g_"+i));
}
if (properties.getProperty(prefix+"eo_b2g_"+i)!=null) {
this.eo_rb2g_hi[i][1] = Double.parseDouble(properties.getProperty(prefix+"eo_b2g_"+i));
}
if (properties.getProperty(prefix+"eo_hi_"+i)!=null) {
this.eo_rb2g_hi[i][2] = Double.parseDouble(properties.getProperty(prefix+"eo_hi_"+i));
}
}
if (properties.getProperty(prefix+"eo_gamma")!=null) this.eo_gamma = Double.parseDouble(properties.getProperty(prefix+"eo_gamma"));
if (properties.getProperty(prefix+"eo_minlin_gamma")!=null) this.eo_minlin_gamma = Double.parseDouble(properties.getProperty(prefix+"eo_minlin_gamma"));
if (properties.getProperty(prefix+"eo_saturation")!=null) this.eo_saturation = Double.parseDouble(properties.getProperty(prefix+"eo_saturation"));
if (properties.getProperty(prefix+"threshold_contrast")!=null) this.threshold_contrast = Double.parseDouble(properties.getProperty(prefix+"threshold_contrast"));
if (properties.getProperty(prefix+"threshold_number")!=null) this.threshold_number = Integer.parseInt(properties.getProperty(prefix+"threshold_number"));
if (properties.getProperty(prefix+"station_sel")!=null) this.station_sel = Integer.parseInt(properties.getProperty(prefix+"station_sel"));
if (properties.getProperty(prefix+"station_in_filenames")!=null) this.station_in_filenames = Boolean.parseBoolean(properties.getProperty(prefix+"station_in_filenames"));
if (properties.getProperty(prefix+"color_grid")!=null) {
long lcolor_grid = Long.parseLong(properties.getProperty(prefix+"color_grid"));
if (lcolor_grid < 0) this.color_grid = null;
else this.color_grid = setLongColor(lcolor_grid);
}
if (properties.getProperty(prefix+"color_grid_weak")!=null) {
long lcolor_grid_weak = Long.parseLong(properties.getProperty(prefix+"color_grid_weak"));
if (lcolor_grid_weak < 0) this.color_grid_weak = null;
else this.color_grid_weak = setLongColor(lcolor_grid_weak);
}
if (properties.getProperty(prefix+"color_grid_extra")!=null) {
long lcolor_grid_extra = Long.parseLong(properties.getProperty(prefix+"color_grid_extra"));
if (lcolor_grid_extra < 0) this.color_grid = null;
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_lwir")!=null) this.line_width_lwir = Integer.parseInt(properties.getProperty(prefix+"line_width_lwir"));
}
public void dialogQuestions(GenericJTabbedDialog gd) {
final int lwir0 = getLwirReaderParameters().getLwirChn0();
final int eo0 = getLwirReaderParameters().getEoChn0();
final int numStations = eyesisCameraParameters.getNumStations();
gd.addTab("LWIR","LWIR photometric parameters");
gd.addNumericField("Thermal color palette", this.palette, 0,3,"","0 - white-hot, 1 - black-hot, 2+ - colored");
for (int i = 0; i < lwir_ranges.length; i++) {
gd.addNumericField("LWIR chn:"+i+" low range", this.lwir_ranges[i][0], 0,8,"","LWIR sensor range low level ");
gd.addNumericField("LWIR chn:"+i+" high range", this.lwir_ranges[i][1], 0,8,"","LWIR sensor range high level ");
gd.addNumericField("LWIR chn:"+(i+lwir0)+" center", 0.5*(this.lwir_ranges[i][1]+this.lwir_ranges[i][0]), 1,8,"","LWIR sensor range center");
gd.addNumericField("LWIR chn:"+(i+lwir0)+" range", this.lwir_ranges[i][1]-this.lwir_ranges[i][0], 1,8,"","LWIR sensor range");
}
gd.addNumericField("Thermal color palette", this.palette, 0,3,"","0 - white-hot, 1 - black-hot, 2+ - colored");
gd.addTab("EO","EO photometric parameters");
for (int i = 0; i < eo_rb2g_hi.length; i++) {
gd.addNumericField("EO chn:"+(i+eo0)+" r2g", this.eo_rb2g_hi[i][0], 4,8,"","gain ratio red to green");
gd.addNumericField("EO chn:"+(i+eo0)+" b2g", this.eo_rb2g_hi[i][1], 4,8,"","gain ratio red to green");
gd.addNumericField("EO chn:"+(i+eo0)+" full range", this.eo_rb2g_hi[i][2], 1,8,"","Full intensity range to map to 255 in the output");
}
gd.addNumericField("Gamma correction", this.eo_gamma, 3,6,"","Gamma correction: 1.0 - linear, lower increases dynamic range.");
gd.addNumericField("Linear range", this.eo_minlin_gamma, 1,6,"","Apply gamma only to higher input values");
gd.addNumericField("Color saturation", this.eo_saturation, 3,6,"","Boost color saturation from the linear representation");
gd.addTab("Grid lines","Grid lines parameters");
gd.addNumericField("Line width for LWIR images", this.line_width_lwir, 0,3,"pix","line width for the grid in LWIR images");
gd.addNumericField("Line width for LWIR images", this.line_width_eo, 0,3,"pix","line width for the grid in EO images");
String scolor = (this.color_grid==null)?"none":String.format("%08x", getLongColor(this.color_grid));
gd.addStringField ("Line color for the grid lines (actual grid)",scolor, 8, "Any invalid hex number disables drawing lines");
String scolor_weak = (this.color_grid_weak==null)?"none":String.format("%08x", getLongColor(this.color_grid_weak));
gd.addStringField ("Line color for the weak grid lines (below threshold)",scolor_weak, 8, "Any invalid hex number disables drawing lines");
String scolor_extra = (this.color_grid_extra==null)?"none":String.format("%08x", getLongColor(this.color_grid_extra));
gd.addStringField ("Line color for the extended grid lines (extra grid)",scolor_extra, 8, "Any invalid hex number disables drawing lines");
gd.addTab("General","Output format and other parameters");
gd.addStringField ("Channel directory prefix",this.channel_dir_prefix, 15,"Prefix to a directory name to save channel annotated files");
gd.addMessage("Stations to include");
for (int i = 0; i < numStations;i++) {
gd.addCheckbox("Use station "+i, ((this.station_sel >> i) & 1) != 0, "Include Station "+i+" in generated files.");
}
gd.addCheckbox("Include station number in result file names", this.station_in_filenames, "Use station number as a part of the result file names.");
gd.addCheckbox("Save as PNG instead of JPEG", save_png);
gd.addNumericField("JPEG quality", this.JPEG_quality, 0,3,"","Jpeg quality, 0 - use Tiff");
gd.addStringField ("Channel directory prefix",this.channel_dir_prefix, 15,"prefix to a directory name to save channel annotated files");
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("Minimal number of high-contrast nodes", this.threshold_number, 0,3,"","Consider a failed grid if the number of strong nodes is below this.");
}
public void dialogAnswers(GenericJTabbedDialog gd) {
// --- LWIR ---
this.palette = (int) gd.getNextNumber();
for (int i = 0; i < lwir_ranges.length; i++) {
this.lwir_ranges[i][0] = gd.getNextNumber();
this.lwir_ranges[i][1] = gd.getNextNumber();
double center = gd.getNextNumber();
double range = gd.getNextNumber();
this.lwir_ranges[i][0] = center - 0.5*range;
this.lwir_ranges[i][1] = center + 0.5*range;
}
// --- EO ---
for (int i = 0; i < eo_rb2g_hi.length; i++) {
this.eo_rb2g_hi[i][0] = gd.getNextNumber();
this.eo_rb2g_hi[i][1] = gd.getNextNumber();
this.eo_rb2g_hi[i][2] = gd.getNextNumber();
}
this.eo_gamma = gd.getNextNumber();
this.eo_minlin_gamma = gd.getNextNumber();
this.eo_saturation = gd.getNextNumber();
// --- Grid lines ---
this.line_width_lwir = (int) gd.getNextNumber();
this.line_width_eo = (int) gd.getNextNumber();
String scolor = gd.getNextString();
long lcolor = -1;
try {
lcolor = Long.parseLong(scolor,16);
this.color_grid = setLongColor(lcolor);
} catch(NumberFormatException e){
this.color_grid = null;
}
this.palette = (int) gd.getNextNumber();
this.save_png = gd.getNextBoolean();
this.JPEG_quality = (int) gd.getNextNumber();
this.channel_dir_prefix = gd.getNextString();
scolor = gd.getNextString();
try {
lcolor = Long.parseLong(scolor,16);
this.color_grid_weak = setLongColor(lcolor);
} catch(NumberFormatException e){
this.color_grid_weak = null;
}
scolor = gd.getNextString();
try {
lcolor = Long.parseLong(scolor,16);
this.color_grid_extra = setLongColor(lcolor);
} catch(NumberFormatException e){
this.color_grid_extra = null;
}
// --- General ---
this.channel_dir_prefix = gd.getNextString();
this.station_sel = 0;
for (int i = 0; i < eyesisCameraParameters.getNumStations();i++) {
if (gd.getNextBoolean()) {
this.station_sel |= 1 << i;
}
}
this.station_in_filenames = gd.getNextBoolean();
this.save_png = gd.getNextBoolean();
this.JPEG_quality = (int) gd.getNextNumber();
this.threshold_contrast = gd.getNextNumber();
this.threshold_number= (int) gd.getNextNumber();
}
public boolean showJDialog() {
set_parameters();
......@@ -83,12 +265,71 @@ public class CalibrationIllustrationParameters {
if ((lwir_ranges == null) || (lwir_ranges.length != lwirReaderParameters.getLwirChannels(false).length)){
lwir_ranges = new double [lwirReaderParameters.getLwirChannels(false).length][2];
for (int i = 0; i < lwir_ranges.length; i++) {
this.lwir_ranges[i][0] = dflt_lwir_lo;
this.lwir_ranges[i][1] = dflt_lwir_hi;
this.lwir_ranges[i][0] = DFLT_LWIR_LO;
this.lwir_ranges[i][1] = DFLT_LWIR_HI;
}
}
if ((eo_rb2g_hi == null) || (eo_rb2g_hi.length != lwirReaderParameters.getEoChannels(false).length)) {
eo_rb2g_hi = new double [lwirReaderParameters.getEoChannels(false).length][3];
for (int i = 0; i < lwir_ranges.length; i++) {
eo_rb2g_hi[i][0] = DFLT_EO_R2G; // gain red relative to green
eo_rb2g_hi[i][1] = DFLT_EO_B2G; // gain blue relative to green
eo_rb2g_hi[i][2] = DFLT_EO_HI; // range to map to 255.0
}
}
}
public double getGamma() {
return this.eo_gamma;
}
public double getMinLin() {
return this.eo_minlin_gamma;
}
public double getSaturation() {
return this.eo_saturation;
}
public int getLineWidthLwir() {
return this.line_width_lwir;
}
public int getLineWidthEo() {
return this.line_width_eo;
}
public Color getGridColor() {
return this.color_grid;
}
public Color getGridWeakColor() {
return this.color_grid_weak;
}
public Color getGridExtraColor() {
return this.color_grid_extra;
}
public String getChannelPrefix() {
return this.channel_dir_prefix;
}
public boolean useStation(int st_num) {
return (this.station_sel & (1 << st_num)) != 0;
}
public boolean useStationInFilenames() {
return this.station_in_filenames;
}
public boolean usePNG() {
return this.save_png;
}
public int getJPEG_quality() {
return this.JPEG_quality;
}
public double getThresholdContrast() {
return this.threshold_contrast;
}
public int getThresholdNumber() {
return this.threshold_number;
}
public int getPalette() {
return this.palette;
}
......
......@@ -3346,7 +3346,7 @@ public class MatchSimulatedPattern {
}
/* ======================================================================== */
private double[] combineDiagonalGreens(double[] green0, double[] green3, int half_width, int half_height) {
private static double[] combineDiagonalGreens(double[] green0, double[] green3, int half_width, int half_height) {
int y, x, base;
int base_b = 0;
double[] result = new double[green0.length];
......@@ -3568,18 +3568,27 @@ public class MatchSimulatedPattern {
* Wave vector 2 x component [2][1] - Wave vector 2 y component [2][2] - Wave
* vector 2 phase (not used here)
*/
public double[][] tryPattern(LwirReaderParameters lwirReaderParameters, // null is OK
DoubleFHT doubleFHT, double[] point, // xy to try
public double[][] tryPattern(
LwirReaderParameters lwirReaderParameters, // null is OK
DoubleFHT doubleFHT,
double[] point, // xy to try
final DistortionParameters distortionParameters, //
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters, final double min_half_period,
final double max_half_period, final SimulationPattern.SimulParameters thisSimulParameters,
final MatchSimulatedPattern matchSimulatedPattern, final MatchSimulatedPattern matchSimulatedPatternCorr,
final SimulationPattern simulationPattern, final boolean equalizeGreens, final ImagePlus imp, // image to
// process
double[] bPattern, double[] windowFunction, double[] windowFunctionCorr, double[] windowFunctionCorr2,
double[] windowFunctionCorr4, double[][] locsNeib, // which neibors to try (here - just the center)
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
final double min_half_period,
final double max_half_period,
final SimulationPattern.SimulParameters thisSimulParameters,
final MatchSimulatedPattern matchSimulatedPattern,
final MatchSimulatedPattern matchSimulatedPatternCorr,
final SimulationPattern simulationPattern,
final boolean equalizeGreens,
final ImagePlus imp, // image to process
double[] bPattern,
double[] windowFunction,
double[] windowFunctionCorr,
double[] windowFunctionCorr2,
double[] windowFunctionCorr4,
double[][] locsNeib, // which neibors to try (here - just the center)
String dbgStr) {
// this.debugLevel = 3;
if (this.debugLevel == 3) {
System.out.println("tryPattern(): this.debugLevel = 3");
......@@ -3590,7 +3599,7 @@ public class MatchSimulatedPattern {
System.out.println(dbgStr + " imp==null");
return null;
}
boolean is_lwir = ((lwirReaderParameters != null) && lwirReaderParameters.is_LWIR(imp));
boolean is_lwir = ((lwirReaderParameters != null) && LwirReaderParameters.is_LWIR(imp));
int fft_size = is_lwir ? distortionParameters.FFTSize_lwir : distortionParameters.FFTSize;
int xc = (int) (2 * Math.round(0.5 * point[0]));
......@@ -3906,33 +3915,27 @@ public class MatchSimulatedPattern {
// it now can start with non-empty Grid
public int distortions( // returns number of grid cells
final LwirReaderParameters lwirReaderParameters, // null is OK
final boolean[] triedIndices, final DistortionParameters distortionParameters, //
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters, final double min_half_period,
final double max_half_period, final SimulationPattern.SimulParameters simulParameters,
final boolean equalizeGreens, final ImagePlus imp, // image to process
final int threadsMax, final boolean updateStatus, final int debug_level, // debug level used inside loops
final boolean[] triedIndices,
final DistortionParameters distortionParameters, //
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
final double min_half_period,
final double max_half_period,
final SimulationPattern.SimulParameters simulParameters,
final boolean equalizeGreens,
final ImagePlus imp, // image to process
final int threadsMax,
final boolean updateStatus,
final int debug_level, // debug level used inside loops
final int global_debug_level) {
if (imp == null)
return 0;
final int debugThreshold = 1;
// final boolean is_lwir = ((lwirReaderParameters != null) && lwirReaderParameters.is_LWIR(imp));
// final int fft_size = is_lwir ? distortionParameters.FFTSize_lwir : distortionParameters.FFTSize;
// final int correlation_size = is_lwir ? distortionParameters.correlationSizeLwir
// : distortionParameters.correlationSize;
// final int max_correlation_size = is_lwir ? distortionParameters.maximalCorrelationSizeLwir
// : distortionParameters.maximalCorrelationSize;
// final int minimal_pattern_cluster = is_lwir ? distortionParameters.minimalPatternClusterLwir
// : distortionParameters.minimalPatternCluster;
final int sensor_type = LwirReaderParameters.sensorType(imp);
final int fft_size = distortionParameters.getFFTSize(sensor_type);
final int correlation_size = distortionParameters.getCorrelationSize(sensor_type);
// final int max_correlation_size = distortionParameters.getMaximalCorrelationSize(sensor_type);
final int minimal_pattern_cluster = distortionParameters.getMinimalPatternCluster(sensor_type);
final int[][] directionsUV = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } }; // should have opposite direction
// shifted by half
final int[][] directionsUV8 = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 1 }, { -1, 1 }, { -1, -1 },
{ 1, -1 } }; // first 8 should be the same as in directionsUV
final int[] directionsBits8 = { 1, 4, 1, 4, 2, 8, 2, 8 }; // should match directionsUV8
......@@ -4103,19 +4106,33 @@ public class MatchSimulatedPattern {
System.out.println("distortions(): startScanIndex=" + startScanIndex + " > 3 ####");
if (startScanIndex < numTries) {
nodeQueue = findPatternCandidates(lwirReaderParameters, // LwirReaderParameters
// lwirReaderParameters, // null is OK
triedIndices, startScanIndex, // [0] will be updated
tryHor, tryVert,
nodeQueue = findPatternCandidates(
lwirReaderParameters, // LwirReaderParameters
triedIndices,
startScanIndex, // [0] will be updated
tryHor,
tryVert,
// numTries,
selection, thisDistortionParameters, // no control of the displacement
patternDetectParameters, min_half_period, max_half_period, thisSimulParameters,
matchSimulatedPattern, matchSimulatedPatternCorr, simulationPattern, equalizeGreens, imp, // image
// to
// process
bPattern, windowFunction, windowFunctionCorr, windowFunctionCorr2, windowFunctionCorr4,
selection,
thisDistortionParameters, // no control of the displacement
patternDetectParameters,
min_half_period,
max_half_period,
thisSimulParameters,
matchSimulatedPattern,
matchSimulatedPatternCorr,
simulationPattern,
equalizeGreens,
imp, // image to process
bPattern,
windowFunction,
windowFunctionCorr,
windowFunctionCorr2,
windowFunctionCorr4,
locsNeib, // which neighbors to try (here - just the center)
threadsMax, updateStatus, this.debugLevel);
threadsMax,
updateStatus,
this.debugLevel);
if (nodeQueue.isEmpty()) { // nodes==null){
// if (debugLevel>1) System.out.println("All start points tried");
if (global_debug_level > (debugThreshold + 1)) {
......@@ -4932,26 +4949,32 @@ public class MatchSimulatedPattern {
}
}
private Queue<GridNode> findPatternCandidates(final LwirReaderParameters lwirReaderParameters, // null is OK
private Queue<GridNode> findPatternCandidates(
final LwirReaderParameters lwirReaderParameters, // null is OK
final boolean[] triedIndices, // which indices are already tried
final int startScanIndex, final int tryHor, final int tryVert, final Rectangle selection,
final int startScanIndex,
final int tryHor,
final int tryVert,
final Rectangle selection,
final DistortionParameters distortionParameters, //
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters, final double min_half_period,
final double max_half_period, final SimulationPattern.SimulParameters thisSimulParameters,
final MatchSimulatedPattern matchSimulatedPattern, final MatchSimulatedPattern matchSimulatedPatternCorr,
final SimulationPattern simulationPattern, final boolean equalizeGreens, final ImagePlus imp, // image to
// process
final double[] bPattern, final double[] windowFunction, final double[] windowFunctionCorr,
final double[] windowFunctionCorr2, final double[] windowFunctionCorr4, final double[][] locsNeib, // which
// neibors
// to
// try
// (here
// -
// just
// the
// center)
final int threadsMax, final boolean updateStatus, final int debugLevel) {
final MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
final double min_half_period,
final double max_half_period,
final SimulationPattern.SimulParameters thisSimulParameters,
final MatchSimulatedPattern matchSimulatedPattern,
final MatchSimulatedPattern matchSimulatedPatternCorr,
final SimulationPattern simulationPattern,
final boolean equalizeGreens,
final ImagePlus imp, // image to process
final double[] bPattern,
final double[] windowFunction,
final double[] windowFunctionCorr,
final double[] windowFunctionCorr2,
final double[] windowFunctionCorr4,
final double[][] locsNeib, // which neibors to try (here - just the center)
final int threadsMax,
final boolean updateStatus,
final int debugLevel) {
final int debugThreshold = 2; // -1; // 1; ** Restore 1
if ((debugThreshold < 0) || (debugLevel < -10000)) {
System.out.println("findPatternCandidates(): debugThreshold < 0 - restore when done");
......@@ -5013,17 +5036,26 @@ public class MatchSimulatedPattern {
+ ", nh=" + nh + ")");
if (debugLevel > 2)
System.out.println(debugNumThread + ":" + n + " >> ");
double[][] node = tryPattern(lwirReaderParameters, // LwirReaderParameters
// lwirReaderParameters, // null is
// OK
doubleFHT, point, // xy to try
double[][] node = tryPattern(
lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, null is OK
doubleFHT,
point, // xy to try
distortionParameters, // no control of the displacement
patternDetectParameters, min_half_period, max_half_period, thisSimulParameters,
matchSimulatedPattern, matchSimulatedPatternCorr, simulationPattern,
equalizeGreens, imp, // image to process
bPattern, windowFunction, windowFunctionCorr, windowFunctionCorr2,
windowFunctionCorr4, locsNeib, // which neighbors to try (here - just the
// center)
patternDetectParameters,
min_half_period,
max_half_period,
thisSimulParameters,
matchSimulatedPattern,
matchSimulatedPatternCorr,
simulationPattern,
equalizeGreens,
imp, // image to process
bPattern,
windowFunction,
windowFunctionCorr,
windowFunctionCorr2,
windowFunctionCorr4,
locsNeib, // which neighbors to try (here - just the center)
(debugLevel > debugThreshold)
? ("" + debugNumThread + ":" + n + ", nv=" + nv + ", nh=" + nh + ", nb="
+ nb + " " + point[0] + "/" + point[1])
......@@ -6590,6 +6622,7 @@ public class MatchSimulatedPattern {
&& (grid[uv[1]][uv[0]] != null) && (grid[uv[1]][uv[0]][0] != null));
}
private boolean isCellDefined(double[][][][] grid, int u, int v) {
return ((v >= 0) && (u >= 0) && (v < grid.length) && (u < grid[v].length) && (grid[v][u] != null)
&& (grid[v][u][0] != null));
......@@ -6679,16 +6712,31 @@ public class MatchSimulatedPattern {
return numDefinedCells(this.PATTERN_GRID);
}
public int numDefinedCells(double[][][][] grid) { // calulate/print number of defined nodes in a grid
public int numDefinedCells(double[][][][] grid) { // calculate/print number of defined nodes in a grid
int[] iUV = new int[2];
int numDefinedCells = 0;
int numCells = 0;
for (iUV[1] = 0; iUV[1] < grid.length; iUV[1]++)
for (iUV[0] = 0; iUV[0] < grid[0].length; iUV[0]++)
if (this.isCellDefined(grid, iUV))
numDefinedCells++;
return numDefinedCells;
numCells++;
return numCells;
}
public int numStrongCells(double min_contrast) {
return numStrongCells(this.PATTERN_GRID, min_contrast);
}
public int numStrongCells(double[][][][] grid, double min_contrast) { // calculate/print number of defined high-contrast nodes in a grid
int[] iUV = new int[2];
int numCells = 0;
for (iUV[1] = 0; iUV[1] < grid.length; iUV[1]++)
for (iUV[0] = 0; iUV[0] < grid[0].length; iUV[0]++)
if (this.getCellContrast(grid, iUV) > min_contrast) {
numCells++;
}
return numCells;
}
public int gridUVWidth() {
return ((this.PATTERN_GRID == null) || (this.PATTERN_GRID.length == 0l) || (this.PATTERN_GRID[0] == null)) ? 0
: this.PATTERN_GRID[0].length;
......@@ -6704,20 +6752,20 @@ public class MatchSimulatedPattern {
* returns number of laser pointers matched (or negative error) if
* (this.flatFieldForGrid!=null) it should already be applied !!
*/
public int calculateDistortions(LwirReaderParameters lwirReaderParameters, // null is OK
public int calculateDistortions(
LwirReaderParameters lwirReaderParameters, // null is OK
MatchSimulatedPattern.DistortionParameters distortionParameters, //
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
SimulationPattern.SimulParameters simulParameters, boolean equalizeGreens, ImagePlus imp, // image to
// process //
// has WOI_TOP
// and possibly
// -
// WOI_COMPENSATED
SimulationPattern.SimulParameters simulParameters,
boolean equalizeGreens,
ImagePlus imp, // image to process has WOI_TOP and possibly WOI_COMPENSATED
LaserPointer laserPointer, // LaserPointer object or null
boolean removeOutOfGridPointers, //
double[][][] hintGrid, // predicted grid array (or null)
double hintGridTolerance, // allowed mismatch (fraction of period) or 0 - orientation only
int threadsMax, boolean updateStatus, int global_debug_level, // DEBUG_LEVEL
int threadsMax,
boolean updateStatus,
int global_debug_level, // DEBUG_LEVEL
int debug_level, // debug level used inside loops
boolean noMessageBoxes) {
......@@ -6726,13 +6774,16 @@ public class MatchSimulatedPattern {
return 0;
}
final int debugThreshold = 1;
boolean is_lwir = ((lwirReaderParameters != null) && lwirReaderParameters.is_LWIR(imp));
boolean is_lwir = ((lwirReaderParameters != null) && LwirReaderParameters.is_LWIR(imp));
double min_half_period = (is_lwir ? patternDetectParameters.minGridPeriodLwir
: patternDetectParameters.minGridPeriod) / 2;
double max_half_period = (is_lwir ? patternDetectParameters.maxGridPeriodLwir
: patternDetectParameters.maxGridPeriod) / 2;
int minimal_pattern_cluster = is_lwir ? distortionParameters.minimalPatternClusterLwir
: distortionParameters.minimalPatternCluster;
double threshold_contrast = distortionParameters.threshold_contrast;
int threshold_number = distortionParameters.threshold_number;
boolean invert = false; // is_lwir;
......@@ -6802,126 +6853,153 @@ public class MatchSimulatedPattern {
boolean[] triedIndices = new boolean[numTries + 1]; // last set - all used
for (int i = 0; i < triedIndices.length; i++)
triedIndices[i] = (i < 3); // mark first 3 as if they are already used
while (reTries > 0) { // outer loop, including refines
while (reTries-- > 0) {
this.PATTERN_GRID = null;
invalidateCalibration();
patternCells = distortions( // calculates matchSimulatedPattern.DIST_ARRAY // invalidates calibration,
// flatFieldForGrid, resets this.PATTERN_GRID
lwirReaderParameters, // null is OK
triedIndices,
distortionParameters, //
patternDetectParameters,
min_half_period,
max_half_period,
simulParameters,
equalizeGreens,
imp,
threadsMax, updateStatus, debug_level, global_debug_level); // debug level
if (global_debug_level > 0)
System.out.println(
"Pattern correlation done at " + IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3)
+ " found " + patternCells + " cells, reTries left: " + reTries);
if (patternCells > 0) {
foundGoodCluster = true;
break; // new distortions() code - returns non-zero only if passed other tests
}
while (reTries-- > 0) {
this.PATTERN_GRID = null;
invalidateCalibration();
patternCells = distortions( // calculates matchSimulatedPattern.DIST_ARRAY // invalidates calibration,
// flatFieldForGrid, resets this.PATTERN_GRID
lwirReaderParameters, // null is OK
triedIndices, distortionParameters, //
patternDetectParameters, min_half_period, max_half_period, simulParameters, equalizeGreens, imp,
threadsMax, updateStatus, debug_level, global_debug_level); // debug level
if (global_debug_level > 0)
System.out.println(
"Pattern correlation done at " + IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3)
+ " found " + patternCells + " cells, reTries left: " + reTries);
if (patternCells > 0) {
foundGoodCluster = true;
break; // new distortions() code - returns non-zero only if passed other tests
}
boolean someLeft = false;
int startScanIndex = 0;
for (startScanIndex = 3; startScanIndex < triedIndices.length; startScanIndex++)
if (!triedIndices[startScanIndex]) {
someLeft = true;
boolean someLeft = false;
int startScanIndex = 0;
for (startScanIndex = 3; startScanIndex < triedIndices.length; startScanIndex++)
if (!triedIndices[startScanIndex]) {
someLeft = true;
break;
}
if (someLeft) {
if (global_debug_level > 0) {
System.out.println("Initial pattern cluster is too small (" + patternCells
+ "), continuing scanning from index " + startScanIndex);
}
} else { // all tried
if (global_debug_level > 0)
System.out.println("--- Tried all - nothing found --- at "
+ IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3));
break;
}
}
if (someLeft) {
if (global_debug_level > 0) {
System.out.println("Initial pattern cluster is too small (" + patternCells
+ "), continuing scanning from index " + startScanIndex);
}
// restore initial distortionParameters.correlationMinInitialContrast
distortionParameters.correlationMinInitialContrast = savedCorrelationMinInitialContrast;
if (!foundGoodCluster) {
if (global_debug_level > (debugThreshold + 1))
System.out.println(
"calculateDistortions(): Pattern too small, initial cluster had " + patternCells + " cells");
if (global_debug_level > (debugThreshold + 2))
IJ.showMessage("Error", "Pattern too small: " + patternCells);
return distortionParameters.errPatternNotFound;
}
if (!patternOK()) {
if (global_debug_level > (debugThreshold + 1))
System.out.println("Pattern not found");
if (global_debug_level > (debugThreshold + 2))
IJ.showMessage("Error", "Pattern not found");
return distortionParameters.errPatternNotFound;
} else {
if (global_debug_level > 0)
System.out.println("--- Tried all - nothing found --- at "
+ IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3));
break;
if (global_debug_level > 0) // (debugThreshold + 1))
System.out.println("Initial pattern cluster has " + patternCells + " cells");
}
}
// restore initial distortionParameters.correlationMinInitialContrast
distortionParameters.correlationMinInitialContrast = savedCorrelationMinInitialContrast;
if (!foundGoodCluster) {
if (global_debug_level > (debugThreshold + 1))
System.out.println(
"calculateDistortions(): Pattern too small, initial cluster had " + patternCells + " cells");
if (global_debug_level > (debugThreshold + 2))
IJ.showMessage("Error", "Pattern too small: " + patternCells);
return distortionParameters.errPatternNotFound;
}
if (!patternOK()) {
if (global_debug_level > (debugThreshold + 1))
System.out.println("Pattern not found");
if (global_debug_level > (debugThreshold + 2))
IJ.showMessage("Error", "Pattern not found");
return distortionParameters.errPatternNotFound;
} else {
if (global_debug_level > 0) // (debugThreshold + 1))
System.out.println("Initial pattern cluster has " + patternCells + " cells");
}
if (global_debug_level > (debugThreshold + 1))
System.out.println(
"Wave vectors recalculated at " + IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3));
recalculateWaveVectors(updateStatus, debug_level);// debug level used inside loops
ImagePlus imp_eq;
if (distortionParameters.flatFieldCorrection && (this.flatFieldForGrid == null)) // if it is not null it is
// already supposed to be
// applied!
imp_eq = equalizeGridIntensity(
imp,
this.PATTERN_GRID,
distortionParameters, // // makes no sense for LWIR as it normalizes absolute data - actually it does!
equalizeGreens,
global_debug_level,
updateStatus,
threadsMax);
else
imp_eq = imp;
if (distortionParameters.refineCorrelations) {
double maxActualCorr = refineDistortionCorrelation(
lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters,
simulParameters,
equalizeGreens,
imp_eq,
0.0, // final double maxCorr, maximal allowed correction, in pixels (0.0) - any
threadsMax,
updateStatus,
debug_level); // debug level
System.out.println(".... maxActualCorr="+maxActualCorr);
if (maxActualCorr <= 0.0) {
return distortionParameters.errRefineFailed; // 2021
}
recalculateWaveVectors(
updateStatus,
debug_level);// debug level used inside loops
if (global_debug_level > (debugThreshold + 1))
System.out.println("Second pass over at " + IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3));
}
// hack gridSize
if ((distortionParameters.gridSize & 1) != 0) {
refineDistortionCorrelation(lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters,
simulParameters,
equalizeGreens,
imp_eq,
0.0, // final double maxCorr, maximal allowed correction, in pixels (0.0) - any
threadsMax,
updateStatus,
debug_level); // debug level
"Wave vectors recalculated at " + IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3));
recalculateWaveVectors(updateStatus, debug_level);// debug level used inside loops
if (global_debug_level > 0)
System.out.println("Third pass over at " + IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3));
ImagePlus imp_eq;
if (distortionParameters.flatFieldCorrection && (this.flatFieldForGrid == null)) // if it is not null it is
// already supposed to be
// applied!
imp_eq = equalizeGridIntensity(
imp,
this.PATTERN_GRID,
distortionParameters, // // makes no sense for LWIR as it normalizes absolute data - actually it does!
equalizeGreens,
global_debug_level,
updateStatus,
threadsMax);
else
imp_eq = imp;
if (distortionParameters.refineCorrelations) {
double maxActualCorr = refineDistortionCorrelation(
lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters,
simulParameters,
equalizeGreens,
imp_eq,
0.0, // final double maxCorr, maximal allowed correction, in pixels (0.0) - any
threadsMax,
updateStatus,
debug_level); // debug level
System.out.println(".... maxActualCorr="+maxActualCorr);
if (maxActualCorr <= 0.0) {
return distortionParameters.errRefineFailed; // 2021
}
recalculateWaveVectors(
updateStatus,
debug_level);// debug level used inside loops
if (global_debug_level > (debugThreshold + 1))
System.out.println("Second pass over at " + IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3));
}
// hack gridSize
}
if ((distortionParameters.gridSize & 1) != 0) {
refineDistortionCorrelation(lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, // null is OK
distortionParameters, //
patternDetectParameters,
simulParameters,
equalizeGreens,
imp_eq,
0.0, // final double maxCorr, maximal allowed correction, in pixels (0.0) - any
threadsMax,
updateStatus,
debug_level); // debug level
recalculateWaveVectors(updateStatus, debug_level);// debug level used inside loops
if (global_debug_level > 0)
System.out.println("Third pass over at " + IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3));
// hack gridSize
}
// Test number of cells with contrast > (~10.0) and fail if number Of over threshold is below minimal_pattern_cluster?
patternCells = numDefinedCells();
if ((roi != null) && (patternCells < minimal_pattern_cluster) && !(roi instanceof PointRoi)) {
if (global_debug_level > (debugThreshold + 0))
System.out.println("Detected pattern is too small: " + patternCells + ", minimum is set to "
+ minimal_pattern_cluster+". Will try again search for a new start point.");
//return distortionParameters.errTooFewCells; // -10
continue;
}
patternCells = numStrongCells(threshold_contrast);
if ((roi != null) && (patternCells < threshold_number) && !(roi instanceof PointRoi)) {
if (global_debug_level > (debugThreshold + 0))
System.out.println("Detected pattern has too few strong cells (with contrast > "+ threshold_contrast+
"): " + patternCells + ", minimum number is set to "
+ threshold_number+". Will try again search for a new start point.");
//return distortionParameters.errTooFewCells; // -10
continue;
}
break; // enough cells?
} // end of outer loop that includes refines
patternCells = numDefinedCells();
if ((roi != null) && (patternCells < minimal_pattern_cluster) && !(roi instanceof PointRoi)) {
if (global_debug_level > (debugThreshold + 0))
......@@ -6929,6 +7007,15 @@ public class MatchSimulatedPattern {
+ minimal_pattern_cluster);
return distortionParameters.errTooFewCells; // -10
}
patternCells = numStrongCells(threshold_contrast);
if ((roi != null) && (patternCells < threshold_number) && !(roi instanceof PointRoi)) {
if (global_debug_level > (debugThreshold + 0))
System.out.println("Detected pattern has too few strong cells (with contrast > "+ threshold_contrast+
"): " + patternCells + ", minimum number is set to "
+ threshold_number+".");
//return distortionParameters.errTooFewCells; // -10
return distortionParameters.errTooFewCells; // -10
}
double[] xy0 = { simulParameters.offsetX, simulParameters.offsetY }; // debug
createUV_INDEX(imp, // or null - just to determine WOI (when getWOI matches image size)
......@@ -12554,6 +12641,10 @@ public class MatchSimulatedPattern {
/* ======================================================================== */
public static class DistortionParameters {
// TODO: make configurable
public double threshold_contrast = 10.0;
public int threshold_number = 10; // grid should have this number of nodes with above-threshold contrast
private int correlationSize; // FFTSize/4
private int correlationSizeLwir;
private int maximalCorrelationSize; // FFTSize/2
......@@ -12746,6 +12837,10 @@ public class MatchSimulatedPattern {
gd.addNumericField("Minimal initial pattern cluster size (0 - disable retries)", distortionParameters.minimalPatternCluster, 0); // 40
gd.addNumericField("Minimal initial LWIR pattern cluster size (0 - disable retries)", distortionParameters.minimalPatternClusterLwir, 0); // 10
gd.addMessage("thresholdContrast=" + threshold_contrast);
gd.addMessage("threshold_number=" + threshold_number);
gd.addNumericField("Scale minimal contrast if the initial cluster is nonzero but smaller", distortionParameters.scaleMinimalInitialContrast, 3);
gd.addNumericField("Overlap of FFT areas when searching for pattern", distortionParameters.searchOverlap, 3);
......@@ -13506,6 +13601,276 @@ public class MatchSimulatedPattern {
return bayer_pixels;
}
public static double[][] splitBayer(ImagePlus imp, int sliceNumber, Rectangle r, boolean equalize_greens, int debug_level) {
if (imp == null)
return null;
ImageProcessor ip = null;
float[] pixels;
if (imp.getStackSize() > 1) {
ip = imp.getStack().getProcessor(sliceNumber);
} else {
ip = imp.getProcessor();
}
pixels = (float[]) ip.getPixels(); // null pointer
int full_width = imp.getWidth(); // full image width
int full_height = imp.getHeight(); // full image height
if (r == null)
r = new Rectangle(0, 0, full_width, full_height);
if (debug_level > 10)
IJ.showMessage("splitBayer", "r.width=" + r.width + "\nr.height=" + r.height + "\nr.x=" + r.x + "\nr.y="
+ r.y + "\nlength=" + pixels.length);
if ((debug_level > 2)
&& ((r.x < 0) || (r.y < 0) || ((r.x + r.width) >= full_width) || ((r.y + r.height) >= full_height)))
System.out.println("r.width=" + r.width + " r.height=" + r.height + " r.x=" + r.x + " r.y=" + r.y);
int x, y, base, base_b, bv, i, j;
int half_height = (r.height >> 1);
int half_width = (r.width >> 1);
// make them all 0 if not a single pixel falls into the image
int numColors = (half_height == half_width) ? 5 : 4;
int pixX, pixY;
double[][] bayer_pixels = new double[numColors][half_height * half_width];
if ((r.x >= full_width) || (r.y >= full_height) || ((r.x + r.width) < 0) || ((r.y + r.height) < 0)) {
for (i = 0; i < bayer_pixels.length; i++)
for (j = 0; j < bayer_pixels[i].length; j++)
bayer_pixels[i][j] = 0.0;
return bayer_pixels;
}
// base=r.width*((y<<1)+bv);
for (y = 0; y < half_height; y++)
for (bv = 0; bv < 2; bv++) {
pixY = (y * 2) + bv + r.y;
base_b = half_width * y;
// if ((pixY>=0)
if (pixY < 0) {
pixY = bv;
} else if (pixY >= full_height) {
pixY = full_height - 2 + bv;
}
base = full_width * pixY + ((r.x > 0) ? r.x : 0);
// base=full_width*((y*2)+bv+r.y)+r.x;
pixX = r.x;
if (bv == 0)
for (x = 0; x < half_width; x++) {
if ((pixX < 0) || (pixX >= (full_width - 2))) {
bayer_pixels[0][base_b] = pixels[base];
bayer_pixels[1][base_b] = pixels[base + 1];
} else {
bayer_pixels[0][base_b] = pixels[base++];
bayer_pixels[1][base_b] = pixels[base++];
}
base_b++;
pixX += 2;
}
else
for (x = 0; x < half_width; x++) {
if ((pixX < 0) || (pixX >= (full_width - 2))) {
bayer_pixels[2][base_b] = pixels[base];
bayer_pixels[3][base_b] = pixels[base + 1];
} else {
bayer_pixels[2][base_b] = pixels[base++];
bayer_pixels[3][base_b] = pixels[base++];
}
base_b++;
pixX += 2;
}
}
if (equalize_greens) {
double g0 = 0.0, g3 = 0.0, g02 = 0.0, g32 = 0.0, a0, a3, b0, b3;
int n = bayer_pixels[0].length;
for (i = 0; i < bayer_pixels[0].length; i++) {
g0 += bayer_pixels[0][i];
g02 += bayer_pixels[0][i] * bayer_pixels[0][i];
g3 += bayer_pixels[3][i];
g32 += bayer_pixels[3][i] * bayer_pixels[3][i];
}
g0 /= n; // mean value
g3 /= n; // meran value
g02 = g02 / n - g0 * g0;
g32 = g32 / n - g3 * g3;
b0 = Math.sqrt(Math.sqrt(g32 / g02));
b3 = 1.0 / b0;
a0 = (g0 + g3) / 2 - b0 * g0;
a3 = (g0 + g3) / 2 - b3 * g3;
if (debug_level > 2) {
System.out.println("g0= " + g0 + ", g3= " + g3);
System.out.println("g02=" + g02 + ", g32=" + g32);
System.out.println("a0=" + a0 + ", b0=" + b0);
System.out.println("a3=" + a3 + ", b3=" + b3);
}
for (i = 0; i < bayer_pixels[0].length; i++) {
bayer_pixels[0][i] = a0 + bayer_pixels[0][i] * b0;
bayer_pixels[3][i] = a3 + bayer_pixels[3][i] * b3;
}
}
if (numColors > 4)
bayer_pixels[4] = combineDiagonalGreens(bayer_pixels[0], bayer_pixels[3], half_width, half_height);
return bayer_pixels;
}
//Assuming gr/bg
public static double [][] simpleDemosaic(
ImagePlus imp,
double r2g,
double b2g,
double saturation,
double gamma,
double minlin_gamma, // do not apply gamma to lower values
double hi // map to 255, gamma will preserve
) {
boolean debug_this = false;
double kr= 0.299;
double kb = 0.114;
double kg = 1.0 - kr - kb;
ImageProcessor ip = null;
float[] pixels;
ip = imp.getProcessor();
pixels = (float[]) ip.getPixels(); // null pointer
int width = imp.getWidth(); // full image width
int height = imp.getHeight(); // full image height
double [][] rgb = new double [3][width*height];
double [] sg= {0.0,0.0};
for (int y = 0; y < height; y+=2) {
for (int x = 0; x < width; x+=2) {
int indx0 = width*y+x;
int indx3 = indx0+width+1;
sg[0]+=pixels[indx0];
sg[1]+=pixels[indx3];
}
}
double g_av = Math.sqrt(sg[0] * sg[1]);
double g2g0 = g_av/sg[0];
double g2g3 = g_av/sg[1];
for (int y = 0; y < height; y+=2) {
for (int x = 0; x < width; x+=2) {
int indx0 = width*y+x;
int indx1 = indx0+1;
int indx2 = indx0+width;
int indx3 = indx2+1;
sg[0]+=pixels[indx0];
sg[1]+=pixels[indx3];
rgb[1][indx0] = pixels[indx0] * g2g0;
rgb[1][indx3] = pixels[indx3] * g2g3;
rgb[0][indx1] = pixels[indx1] * r2g;
rgb[2][indx2] = pixels[indx2] * b2g;
}
}
if (debug_this) {
(new ShowDoubleFloatArrays()).showArrays(rgb, width, height, true,imp.getTitle()+"split");
}
if (debug_this) { // remove
System.out.println("sg="+sg[0]+", "+sg[1]+", g_av="+g_av);
}
// bi-linear interpolation
for (int y = 0; y < height; y+=2) {
for (int x = 0; x < width; x+=2) {
int [][] ind = new int[4][4];
int base = (y-1)*width+(x-1);
for (int i = 0; i < 4;i++) {
int ie = i;
if ((i==0) && (y==0)) {
ie = 2;
} else if ((i==3) && (y==(height - 2))) {
ie = 1;
}
for (int j = 0; j < 4; j++) {
int je = j;
if ((j==0) && (x==0)) {
je = 2;
} else if ((j==3) && (x==(width - 2))) {
je = 1;
}
ind[i][j] = base+ie*width+je;
}
}
// red in top left
rgb[0][ind[1][1]] = 0.5* (
rgb[0][ind[1][0]] +
rgb[0][ind[1][2]]);
// blue in top left
rgb[2][ind[1][1]] = 0.5* (
rgb[2][ind[0][1]] +
rgb[2][ind[2][1]]);
// green in top right
rgb[1][ind[1][2]] = 0.25*(
rgb[1][ind[0][2]] +
rgb[1][ind[1][1]] +
rgb[1][ind[1][3]] +
rgb[1][ind[2][2]]);
// blue in top right
rgb[2][ind[1][2]] = 0.25*(
rgb[2][ind[0][1]] +
rgb[2][ind[0][3]] +
rgb[2][ind[2][1]] +
rgb[2][ind[2][3]]);
// red in bottom left
rgb[0][ind[2][1]] = 0.25*(
rgb[0][ind[1][0]] +
rgb[0][ind[1][2]] +
rgb[0][ind[3][0]] +
rgb[0][ind[3][2]]);
// green in bottom left
rgb[1][ind[2][1]] = 0.25*(
rgb[1][ind[1][1]] +
rgb[1][ind[2][0]] +
rgb[1][ind[2][2]] +
rgb[1][ind[3][1]]);
// red in bottom right
rgb[0][ind[2][2]] = 0.5* (
rgb[0][ind[1][2]] +
rgb[0][ind[3][2]]);
// blue in bottom right
rgb[2][ind[2][2]] = 0.5* (
rgb[2][ind[2][1]] +
rgb[2][ind[2][3]]);
}
}
if (debug_this) {
(new ShowDoubleFloatArrays()).showArrays(rgb, width, height, true,imp.getTitle()+"bilinear");
}
if (saturation != 1.0) {
for (int i = 0; i < rgb[0].length; i++) {
rgb[0][i] = rgb[1][i] * Math.pow(rgb[0][i]/rgb[1][i], saturation);
rgb[2][i] = rgb[1][i] * Math.pow(rgb[2][i]/rgb[1][i], saturation);
}
}
// gamma-correction
/*
double gamma,
double minlin_gamma, // do not apply gamma to lower values
double hi // map to 255, gamma will preserve
*/
boolean nogamma = (gamma == 1.0);
double out_range = 255.0;
double lin_scale = out_range/hi;
if (nogamma) {
minlin_gamma = hi;
}
double scale_out = out_range / (Math.pow(hi, gamma) - Math.pow(minlin_gamma, gamma)*(1.0 - gamma));
// double Y0 = scale_out * Math.pow(minlin_gamma, gamma)*(1.0 - gamma);
double rY0 = Math.pow(minlin_gamma, gamma)*(1.0 - gamma);
if (!nogamma) {
lin_scale = scale_out* gamma*Math.pow(minlin_gamma, gamma - 1);
}
for (int indx = 0; indx < rgb[0].length; indx++) {
double Y = rgb[0][indx]*kr+rgb[1][indx]*kg+rgb[2][indx]*kb; // intensity to apply gamma
double s = lin_scale;
if (!nogamma && (Y > minlin_gamma)) {
s = scale_out * (Math.pow(Y, gamma) - rY0)/Y;
}
for (int i = 0; i < 3; i++) {
rgb[i][indx] *= s;
}
}
if (debug_this) {
(new ShowDoubleFloatArrays()).showArrays(rgb, width, height, true,imp.getTitle()+"gamma");
}
return rgb;
}
public double[][] splitBayerOne(ImagePlus imp, Rectangle r, boolean equalize_greens) {
ImageProcessor ip = imp.getProcessor();
float[] pixels;
......
......@@ -748,7 +748,7 @@ public class LwirReader {
* From Stephan Preibisch's Multithreading.java class. See:
* http://repo.or.cz/w/trakem2.git?a=blob;f=mpi/fruitfly/general/MultiThreading.java;hb=HEAD
*/
private Thread[] newThreadArray(int maxCPUs) {
private static Thread[] newThreadArray(int maxCPUs) {
int n_cpus = Runtime.getRuntime().availableProcessors();
if (n_cpus>maxCPUs)n_cpus=maxCPUs;
return new Thread[n_cpus];
......
......@@ -111,7 +111,7 @@ public class LwirReaderParameters {
return absolute_chn;
}
public int [] getAbsoluteEoChannels(boolean absolote) {
public int [] getEoChannels(boolean absolote) {
int [] absolute_chn = new int [eo_channels.length];
for (int i = 0; i < absolute_chn.length; i++) {
absolute_chn[i] = eo_channels[i] + + (absolote? getEoChn0():0);
......
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