Commit 67a6a946 authored by Andrey Filippov's avatar Andrey Filippov

simultaneously correcting a quad

parent 5578f549
......@@ -1892,6 +1892,7 @@ public class EyesisCorrectionParameters {
public double vignetting_max = 0.4; // value in vignetting data to correspond to 1x in the kernel
public double vignetting_range = 5.0; // do not try to correct vignetting less than vignetting_max/vignetting_range
public int kernel_step = 16; // source kernels step in pixels (have 1 kernel margin on each side)
public double disparity = 0.0; // nominal disparity between side of square cameras (pix)
public CLTParameters(){}
public void setProperties(String prefix,Properties properties){
......@@ -1919,6 +1920,7 @@ public class EyesisCorrectionParameters {
properties.setProperty(prefix+"vignetting_max", this.vignetting_max+"");
properties.setProperty(prefix+"vignetting_range", this.vignetting_range+"");
properties.setProperty(prefix+"kernel_step", this.kernel_step+"");
properties.setProperty(prefix+"disparity", this.disparity +"");
}
public void getProperties(String prefix,Properties properties){
......@@ -1945,6 +1947,7 @@ public class EyesisCorrectionParameters {
if (properties.getProperty(prefix+"vignetting_max")!=null) this.vignetting_max=Double.parseDouble(properties.getProperty(prefix+"vignetting_max"));
if (properties.getProperty(prefix+"vignetting_range")!=null) this.vignetting_range=Double.parseDouble(properties.getProperty(prefix+"vignetting_range"));
if (properties.getProperty(prefix+"kernel_step")!=null) this.kernel_step=Integer.parseInt(properties.getProperty(prefix+"kernel_step"));
if (properties.getProperty(prefix+"disparity")!=null) this.disparity=Double.parseDouble(properties.getProperty(prefix+"disparity"));
}
public boolean showDialog() {
......@@ -1972,6 +1975,7 @@ public class EyesisCorrectionParameters {
gd.addNumericField("Value (max) in vignetting data to correspond to 1x in the kernel", this.vignetting_max, 3);
gd.addNumericField("Do not try to correct vignetting smaller than this fraction of max", this.vignetting_range, 3);
gd.addNumericField("Kernel step in pixels (has 1 kernel margin on each side)", this.kernel_step, 0);
gd.addNumericField("Nominal (rectilinear) disparity between side of square cameras (pix)", this.disparity, 3);
WindowTools.addScrollBars(gd);
gd.showDialog();
......@@ -2000,6 +2004,7 @@ public class EyesisCorrectionParameters {
this.vignetting_max= gd.getNextNumber();
this.vignetting_range= gd.getNextNumber();
this.kernel_step= (int) gd.getNextNumber();
this.disparity= gd.getNextNumber();
return true;
}
......
This diff is collapsed.
......@@ -495,6 +495,7 @@ private Panel panel1,
addButton("Reset CLT kernels", panelClt1, color_stop);
addButton("CLT process files", panelClt1, color_process);
addButton("CLT process sets", panelClt1, color_process);
addButton("CLT process quads", panelClt1, color_process);
add(panelClt1);
}
pack();
......@@ -4282,6 +4283,15 @@ private Panel panel1,
DEBUG_LEVEL);
}
}
if (!EYESIS_DCT.geometryCorrectionAvailable()){
if (DEBUG_LEVEL > 0){
System.out.println("Calculating geometryCorrection");
}
if (!EYESIS_DCT.initGeometryCorrection(DEBUG_LEVEL+2)){
return;
}
}
///========================================
......@@ -4307,6 +4317,100 @@ private Panel panel1,
}
return;
} else if (label.equals("CLT process quads")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
if (EYESIS_DCT == null){
EYESIS_DCT = new EyesisDCT (
EYESIS_CORRECTIONS,
CORRECTION_PARAMETERS,
DCT_PARAMETERS);
if (DEBUG_LEVEL > 0){
System.out.println("Created new EyesisDCT instance, will need to read CLT kernels");
}
}
String configPath=null;
if (EYESIS_CORRECTIONS.correctionsParameters.saveSettings) {
configPath=EYESIS_CORRECTIONS.correctionsParameters.selectResultsDirectory(
true,
true);
if (configPath==null){
String msg="No results directory selected, command aborted";
System.out.println("Warning: "+msg);
IJ.showMessage("Warning",msg);
return;
}
configPath+=Prefs.getFileSeparator()+"autoconfig";
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;
}
}
EYESIS_CORRECTIONS.initSensorFiles(DEBUG_LEVEL);
int numChannels=EYESIS_CORRECTIONS.getNumChannels();
NONLIN_PARAMETERS.modifyNumChannels(numChannels);
CHANNEL_GAINS_PARAMETERS.modifyNumChannels(numChannels);
if (!EYESIS_DCT.CLTKernelsAvailable()){
if (DEBUG_LEVEL > 0){
System.out.println("Reading CLT kernels");
}
EYESIS_DCT.readCLTKernels(
CLT_PARAMETERS,
THREADS_MAX,
UPDATE_STATUS, // update status info
DEBUG_LEVEL);
if (DEBUG_LEVEL > 1){
EYESIS_DCT.showCLTKernels(
THREADS_MAX,
UPDATE_STATUS, // update status info
DEBUG_LEVEL);
}
}
if (!EYESIS_DCT.geometryCorrectionAvailable()){
if (DEBUG_LEVEL > 0){
System.out.println("Calculating geometryCorrection");
}
if (!EYESIS_DCT.initGeometryCorrection(DEBUG_LEVEL+2)){
return;
}
}
///========================================
EYESIS_DCT.processCLTQuads(
CLT_PARAMETERS, // EyesisCorrectionParameters.DCTParameters dct_parameters,
DEBAYER_PARAMETERS, //EyesisCorrectionParameters.DebayerParameters debayerParameters,
NONLIN_PARAMETERS, //EyesisCorrectionParameters.NonlinParameters nonlinParameters,
COLOR_PROC_PARAMETERS, //EyesisCorrectionParameters.ColorProcParameters colorProcParameters,
CHANNEL_GAINS_PARAMETERS, //CorrectionColorProc.ColorGainsParameters channelGainParameters,
RGB_PARAMETERS, //EyesisCorrectionParameters.RGBParameters rgbParameters,
EQUIRECTANGULAR_PARAMETERS, // EyesisCorrectionParameters.EquirectangularParameters equirectangularParameters,
CONVOLVE_FFT_SIZE, //int convolveFFTSize, // 128 - fft size, kernel size should be size/2
THREADS_MAX, //final int threadsMax, // maximal number of threads to launch
UPDATE_STATUS, //final boolean updateStatus,
DEBUG_LEVEL); //final int debugLevel);
if (configPath!=null) {
saveTimestampedProperties( // save config again
configPath, // full path or null
null, // use as default directory if path==null
true,
PROPERTIES);
}
return;
......
......@@ -114,6 +114,7 @@ public class GeometryCorrection {
double heading, // NaN - keep
double [] forward, // null - keep all, NaN - keep individual
double [] right, // null - keep all, NaN - keep individual
double [] height, // null - keep all, NaN - keep individual
double [] roll, // null - keep all, NaN - keep individual
double [][] pXY0){ // null - keep all, [] null - keep individual
......@@ -136,6 +137,14 @@ public class GeometryCorrection {
for (int i = 0; i < numSensors; i++) if (!Double.isNaN(right[i])) this.right[i] = right[i];
}
if (height != null){
if (height.length != numSensors){
throw new IllegalArgumentException ("height.length ("+height.length+") != numSensors ("+numSensors+")");
}
if ((this.height == null) || (this.height.length != numSensors)) this.height = new double [numSensors];
for (int i = 0; i < numSensors; i++) if (!Double.isNaN(height[i])) this.height[i] = height[i];
}
if (roll != null){
if (roll.length != numSensors){
throw new IllegalArgumentException ("roll.length ("+roll.length+") != numSensors ("+numSensors+")");
......@@ -244,10 +253,61 @@ public class GeometryCorrection {
for (int j = 0; j<2;j++) this.rXY[i][j] = this.XYZ_her[i][j]/this.disparityRadius;
}
}
public void listGeometryCorrection(boolean showAll){
System.out.println("'=== Constant parameters ===");
System.out.println("pixelCorrectionWidth =\t"+ pixelCorrectionWidth+"\tpix");
System.out.println("pixelCorrectionHeight =\t"+ pixelCorrectionHeight+"\tpix");
System.out.println("pixelSize =\t"+ pixelSize+"\tum");
System.out.println("distortionRadius =\t"+ distortionRadius+"\tmm");
System.out.println("'=== Common input parameters ===");
System.out.println("focalLength =\t"+ focalLength + " mm");
System.out.println("distortionA8 =\t"+ distortionA8);
System.out.println("distortionA7 =\t"+ distortionA7);
System.out.println("distortionA6 =\t"+ distortionA6);
System.out.println("distortionA5 =\t"+ distortionA5);
System.out.println("distortionA =\t"+ distortionA);
System.out.println("distortionB =\t"+ distortionB);
System.out.println("distortionC =\t"+ distortionC);
System.out.println("elevation =\t"+ elevation+"\tdegrees");
System.out.println("heading =\t"+ heading+"\tdegrees");
System.out.println("numSensors =\t"+ numSensors);
System.out.println("'=== Individual input parameters ===");
System.out.print ("forward = ");for (int i = 0; i < numSensors;i++) System.out.print("\t"+forward[i]); System.out.println("\tmm");
System.out.print ("right = "); for (int i = 0; i < numSensors;i++) System.out.print("\t"+right[i]); System.out.println("\tmm");
System.out.print ("height = "); for (int i = 0; i < numSensors;i++) System.out.print("\t"+height[i]); System.out.println("\tmm");
System.out.print ("roll = "); for (int i = 0; i < numSensors;i++) System.out.print("\t"+roll[i]); System.out.println("\tdegrees");
System.out.print ("px0 = "); for (int i = 0; i < numSensors;i++) System.out.print("\t"+pXY0[i][0]); System.out.println("\tpix");
System.out.print ("py0 = "); for (int i = 0; i < numSensors;i++) System.out.print("\t"+pXY0[i][1]); System.out.println("\tpix");
System.out.println("'=== Common calculated parameters ===");
System.out.println("common_right =\t"+common_right + "\tmm");
System.out.println("common_forward =\t"+common_forward + "\tmm");
System.out.println("common_height =\t"+common_height + "\tmm");
System.out.println("common_roll =\t"+common_roll + "\tdegrees");
System.out.println("cameraRadius =\t"+cameraRadius + "\tmm");
System.out.println("disparityRadius =\t"+disparityRadius + "\tmm");
if (showAll){
System.out.println("'=== Intermediate data: coordinates corrected for common elevation and heading ===");
System.out.print ("X_he ="); for (int i = 0; i < numSensors;i++) System.out.print("\t"+XYZ_he[i][0]); System.out.println("\tmm");
System.out.print ("Y_he ="); for (int i = 0; i < numSensors;i++) System.out.print("\t"+XYZ_he[i][1]); System.out.println("\tmm");
System.out.print ("Z_he ="); for (int i = 0; i < numSensors;i++) System.out.print("\t"+XYZ_he[i][2]); System.out.println("\tmm");
System.out.println("'=== Intermediate data: coordinates corrected for common elevation, heading and roll ===");
System.out.print ("X_her ="); for (int i = 0; i < numSensors;i++) System.out.print("\t"+XYZ_her[i][0]); System.out.println("\tmm");
System.out.print ("Y_her ="); for (int i = 0; i < numSensors;i++) System.out.print("\t"+XYZ_her[i][1]); System.out.println("\tmm");
System.out.print ("Z_her ="); for (int i = 0; i < numSensors;i++) System.out.print("\t"+XYZ_her[i][2]); System.out.println("\tmm");
}
System.out.println("'=== Individual calculated parameters ===");
System.out.print ("residual_roll = "); for (int i = 0; i < numSensors;i++) System.out.print("\t"+(roll[i]-common_roll));System.out.println("\tdegrees");
System.out.print ("X_rel ="); for (int i = 0; i < numSensors;i++) System.out.print("\t"+rXY[i][0]); System.out.println("\trelative to disparityRadius");
System.out.print ("Y_rel ="); for (int i = 0; i < numSensors;i++) System.out.print("\t"+rXY[i][1]); System.out.println("\trelative to disparityRadius");
}
// return distance from disparity (in pixel units) for the current camera geometry
public double getZFromDisparity(double disparity){
return disparity * this.focalLength * this.pixelSize / this.disparityRadius;
return disparity * this.focalLength * 0.001*this.pixelSize / this.disparityRadius;
}
/*
......@@ -263,8 +323,8 @@ public class GeometryCorrection {
double [][] pXY = new double [numSensors][2];
double pXcd = px - 0.5 * this.pixelCorrectionWidth;
double pYcd = py - 0.5 * this.pixelCorrectionHeight;
double rD = Math.sqrt(pXcd*pXcd + pYcd*pYcd); // distorted radius in a virtual center camera
double rND2R=getRByRDist(rD/this.distortionRadius, (debugLevel > 1));
double rD = Math.sqrt(pXcd*pXcd + pYcd*pYcd)*0.001*this.pixelSize; // distorted radius in a virtual center camera
double rND2R=getRByRDist(rD/this.distortionRadius, (debugLevel > -1));
double pXc = pXcd * rND2R; // non-distorted coordinates relative to the (0.5 * this.pixelCorrectionWidth, 0.5 * this.pixelCorrectionHeight)
double pYc = pYcd * rND2R; // in pixels
double [] a={this.distortionC,this.distortionB,this.distortionA,this.distortionA5,this.distortionA6,this.distortionA7,this.distortionA8};
......@@ -275,7 +335,7 @@ public class GeometryCorrection {
// calculate back to distorted
double rNDi = Math.sqrt(pXci*pXci + pYci*pYci); // in pixels
// Rdist/R=A8*R^7+A7*R^6+A6*R^5+A5*R^4+A*R^3+B*R^2+C*R+(1-A6-A7-A6-A5-A-B-C)");
double ri = rNDi* this.pixelSize / this.distortionRadius; // relative to distortion radius
double ri = rNDi* 0.001 * this.pixelSize / this.distortionRadius; // relative to distortion radius
// double rD2rND = (1.0 - distortionA8 - distortionA7 - distortionA6 - distortionA5 - distortionA - distortionB - distortionC);
double rD2rND = 1.0;
double rri = 1.0;
......@@ -286,8 +346,8 @@ public class GeometryCorrection {
double pXid = pXci * rD2rND;
double pYid = pYci * rD2rND;
// individual rotate (check sign)
double c_roll = Math.cos(this.roll[i] * Math.PI/180.0);
double s_roll = Math.sin(this.roll[i] * Math.PI/180.0);
double c_roll = Math.cos((this.roll[i] - this.common_roll) * Math.PI/180.0);
double s_roll = Math.sin((this.roll[i] - this.common_roll) * Math.PI/180.0);
pXY[i][0] = c_roll * pXid + s_roll* pYid + this.pXY0[i][0];
pXY[i][1] = -s_roll * pXid + c_roll* pYid + this.pXY0[i][1];
}
......
......@@ -757,6 +757,141 @@ public class ImageDtt {
}
public double [][][][][][] clt_aberrations_quad(
final double disparity,
final double [][][] imade_data, // first index - number of image in a quad
final int width,
final GeometryCorrection geometryCorrection,
final double [][][][][][] clt_kernels, // [channel_in_quad][color][tileY][tileX][band][pixel] , size should match image (have 1 tile around)
final int kernel_step,
final int transform_size,
final int window_type,
final double shiftX, // shift image horizontally (positive - right) - just for testing
final double shiftY, // shift image vertically (positive - down)
final int debug_tileX,
final int debug_tileY,
final boolean no_fract_shift,
final boolean no_deconvolution,
final boolean transpose,
final int threadsMax, // maximal number of threads to launch
final int globalDebugLevel)
{
final int quad = 4;
final int nChn = imade_data[0].length;
final int height=imade_data[0][0].length/width;
final int tilesX=width/transform_size;
final int tilesY=height/transform_size;
final int nTilesInChn=tilesX*tilesY;
final int nTiles=tilesX*tilesY*nChn;
final double [][][][][][] clt_data = new double[quad][nChn][tilesY][tilesX][4][];
final Thread[] threads = newThreadArray(threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
double [][] centersXY_dbg = geometryCorrection.getPortsCoordinates(
0.0, // centerX,
0.0, // centerY,
disparity);
if (globalDebugLevel > 0) {
System.out.println("clt_aberrations(): width="+width+" height="+height+" transform_size="+transform_size+
" debug_tileX="+debug_tileX+" debug_tileY="+debug_tileY+" globalDebugLevel="+globalDebugLevel);
}
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
DttRad2 dtt = new DttRad2(transform_size);
dtt.set_window(window_type);
int tileY,tileX, chn;
// showDoubleFloatArrays sdfa_instance = new showDoubleFloatArrays(); // just for debugging?
double centerX; // center of aberration-corrected (common model) tile, X
double centerY; //
double [][] fract_shiftsXY = new double[quad][];
for (int nTile = ai.getAndIncrement(); nTile < nTiles; nTile = ai.getAndIncrement()) {
// TODO: make all color channels to be processed here (atomically)
chn=nTile/nTilesInChn;
tileY =(nTile % nTilesInChn)/tilesX;
tileX = nTile % tilesX;
centerX = tileX * transform_size + transform_size/2 - shiftX;
centerY = tileY * transform_size + transform_size/2 - shiftY;
double [][] centersXY = geometryCorrection.getPortsCoordinates(
centerX,
centerY,
disparity);
if ((globalDebugLevel > -1) && (tileX >= debug_tileX - 2) && (tileX <= debug_tileX + 2) &&
(tileY >= debug_tileY - 2) && (tileY <= debug_tileY+2)) {
for (int i = 0; i < quad; i++) {
System.out.println("clt_aberrations_quad(): color="+chn+", tileX="+tileX+", tileY="+tileY+
" centerX="+centerX+" centerY="+centerY+" disparity="+disparity+
" centersXY["+i+"][0]="+centersXY[i][0]+" centersXY["+i+"][1]="+centersXY[i][1]);
}
}
for (int i = 0; i < quad; i++) {
fract_shiftsXY[i] = extract_correct_tile( // return a pair of resudual offsets
imade_data[i],
width, // image width
clt_kernels[i], // [color][tileY][tileX][band][pixel]
clt_data[i][chn][tileY][tileX], //double [][] clt_tile, // should be double [4][];
kernel_step,
transform_size,
dtt,
chn,
centersXY[i][0], // centerX, // center of aberration-corrected (common model) tile, X
centersXY[i][1], // centerY, //
(globalDebugLevel > 0) && (tileX == debug_tileX) && (tileY == debug_tileY) && (chn == 2), // external tile compare
no_deconvolution,
transpose);
}
if ((globalDebugLevel > 0) && (debug_tileX == tileX) && (debug_tileY == tileY) && (chn == 2)) {
showDoubleFloatArrays sdfa_instance = new showDoubleFloatArrays(); // just for debugging?
String [] titles = {"CC0","SC0","CS0","SS0","CC1","SC1","CS1","SS1","CC2","SC2","CS2","SS2","CC3","SC3","CS3","SS3"};
double [][] dbg_tile = new double [16][];
for (int i = 0; i < 16; i++) dbg_tile[i]=clt_data[i>>2][chn][tileY][tileX][i & 3];
sdfa_instance.showArrays(dbg_tile, transform_size, transform_size, true, "pre-shifted_x"+tileX+"_y"+tileY, titles);
}
if ((globalDebugLevel > -1) && (tileX >= debug_tileX - 2) && (tileX <= debug_tileX + 2) &&
(tileY >= debug_tileY - 2) && (tileY <= debug_tileY+2)) {
for (int i = 0; i < quad; i++) {
System.out.println("clt_aberrations_quad(): color="+chn+", tileX="+tileX+", tileY="+tileY+
" fract_shiftsXY["+i+"][0]="+fract_shiftsXY[i][0]+" fract_shiftsXY["+i+"][1]="+fract_shiftsXY[i][1]);
}
}
if (!no_fract_shift) {
// apply residual shift
for (int i = 0; i < quad; i++) {
fract_shift( // fractional shift in transform domain. Currently uses sin/cos - change to tables with 2? rotations
clt_data[i][chn][tileY][tileX], // double [][] clt_tile,
transform_size,
fract_shiftsXY[i][0], // double shiftX,
fract_shiftsXY[i][1], // double shiftY,
// (globalDebugLevel > 0) && (tileX == debug_tileX) && (tileY == debug_tileY)); // external tile compare
((globalDebugLevel > 0) && (chn==0) && (tileX >= debug_tileX - 2) && (tileX <= debug_tileX + 2) &&
(tileY >= debug_tileY - 2) && (tileY <= debug_tileY+2)));
}
if ((globalDebugLevel > 0) && (debug_tileX == tileX) && (debug_tileY == tileY)) {
showDoubleFloatArrays sdfa_instance = new showDoubleFloatArrays(); // just for debugging?
String [] titles = {"CC0","SC0","CS0","SS0","CC1","SC1","CS1","SS1","CC2","SC2","CS2","SS2","CC3","SC3","CS3","SS3"};
double [][] dbg_tile = new double [16][];
for (int i = 0; i < 16; i++) dbg_tile[i]=clt_data[i>>2][chn][tileY][tileX][i & 3];
sdfa_instance.showArrays(dbg_tile, transform_size, transform_size, true, "shifted_x"+tileX+"_y"+tileY, titles);
}
}
}
}
};
}
startAndJoin(threads);
return clt_data;
}
......
......@@ -15584,7 +15584,13 @@ public class PixelMapping {
public int subcamera= -1;
public int subchannel=-1;
public int sensor_port=-1;
// TODO: add serial# (and temperature?)
// Following 4 parameters are not included in the vector, names, descriptions
public boolean cartesian = false; // cartesian coordinates mode (false - cylindrical)
public double right; // distance to the right (radius*sin(azimuth))
public double forward; // distance forward (radius*cos(azimuth))
public double heading; // absolute heading in degrees (used in cartesian mode)
public double azimuth; // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
public double radius; // mm, distance from the rotation axis
public double height; // mm, up - from the origin point
......@@ -16266,8 +16272,33 @@ public class PixelMapping {
if (imp.getProperty("r_od_"+i+"_o") !=null) this.r_od[i][0]= Double.parseDouble((String) imp.getProperty("r_od_"+i+"_o"));
if (imp.getProperty("r_od_"+i+"_d") !=null) this.r_od[i][1]= Double.parseDouble((String) imp.getProperty("r_od_"+i+"_d"));
}
if (imp.getProperty("forward") !=null) this.forward= Double.parseDouble((String) imp.getProperty("forward"));
if (imp.getProperty("right") !=null) this.right= Double.parseDouble((String) imp.getProperty("right"));
if (imp.getProperty("aheading") !=null) this.heading= Double.parseDouble((String) imp.getProperty("aheading"));
if (imp.getProperty("cartesian") !=null) {
this.cartesian= Boolean.parseBoolean((String) imp.getProperty("cartesian"));
updateCartesian(); // recalculate other parameters (they may or may nort be provided
} else {
this.cartesian = false;
}
}
public void updateCartesian(){ // set alternative parameters
if (cartesian) {
this.azimuth = Math.atan2(this.right, this.forward)*180.0/Math.PI;
this.radius = Math.sqrt(this.forward*this.forward + this.right*this.right);
this.phi = this.heading - this.azimuth;
} else {
this.forward = this.radius * Math.cos(Math.PI*this.azimuth/180.0);
this.right = this.radius * Math.sin(Math.PI*this.azimuth/180.0);
this.heading = this.phi + this.azimuth;
}
}
/**
* Calculate rotation matrix that converts sensor coordinates to world coordinates
* @return 3x3 rotation matrix
......
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