Commit 5e90425c authored by Andrey Filippov's avatar Andrey Filippov

Grid matching for secondary (LWIR) sensors

parent 726f3d95
......@@ -501,7 +501,7 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
4, // int decimateMasks
0.1, // double badNodeThreshold=0.1; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
1, // int maxBadNeighb; // maximal number of bad nodes around the corrected one to fix
50, // int minimalValidNodes
10, // int minimalValidNodes
1, // int weightMultiImageMode=1; // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set)
1.0, // public double weightMultiExponent= 1.0; // if( >0) use grid diameter to scale weights of this image
1.0, // public double weightDiameterExponent=1.0;
......@@ -511,7 +511,8 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
0.5, // public double shrinkBlurLevel = 0.5;
-1.0, // double balanceChannelWeightsMode
2.0, // public double removeOverRMS=2.0; // error is multiplied by weight function before comparison (more permissive on the borders
4.0 //public double removeOverRMSNonweighted=4.0; // error is not multiplied (no more permissions on tyhe borders
4.0, //public double removeOverRMSNonweighted=4.0; // error is not multiplied (no more permissions on tyhe borders
true // boolean invertUnmarkedLwirGrid
);
//
......@@ -1020,6 +1021,7 @@ if (MORE_BUTTONS) {
addButton("Import Subsystem", panelLWIR,color_configure);
addButton("Select LWIR grids", panelLWIR,color_configure);
addButton("Grid offset", panelLWIR,color_process);
addButton("LWIR to EO", panelLWIR,color_process);
addButton("Manual hint", panelLWIR,color_configure);
add(panelLWIR);
......@@ -2080,6 +2082,8 @@ if (MORE_BUTTONS) {
double[][] gridDisplay=LENS_DISTORTIONS.prepareDisplayGrid();
SDFA_INSTANCE.showArrays(gridDisplay,LENS_DISTORTIONS.getGridWidth(),LENS_DISTORTIONS.getGridHeight(), true, "Grid",
LENS_DISTORTIONS.displayGridTitles());
// Does not update pixelSize and DistortionRadius !!
LENS_DISTORTIONS.calcGridOnSensor(0.0);
double[][] gridDisplayOnSensor=LENS_DISTORTIONS.prepareDisplayGridOnSensor(false);
SDFA_INSTANCE.showArrays(gridDisplayOnSensor,LENS_DISTORTIONS.getGridWidth(),LENS_DISTORTIONS.getGridHeight(), true, "GridOnSensor",
......@@ -2297,7 +2301,9 @@ if (MORE_BUTTONS) {
if (LENS_DISTORTIONS.fittingStrategy==null) return;
LENS_DISTORTIONS.fittingStrategy.debugLevel=DEBUG_LEVEL;
LENS_DISTORTIONS.LevenbergMarquardt(true); // open dialog
LENS_DISTORTIONS.LevenbergMarquardt(true, // open dialog
false); // dry_run
return;
}
/* ======================================================================== */
......@@ -3610,7 +3616,9 @@ if (MORE_BUTTONS) {
LENS_DISTORTIONS.thresholdFinish=FOCUS_MEASUREMENT_PARAMETERS.thresholdFinish;
LENS_DISTORTIONS.numIterations=FOCUS_MEASUREMENT_PARAMETERS.numIterations;
LENS_DISTORTIONS.LevenbergMarquardt(false); // skip dialog
LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
if (DEBUG_LEVEL>0) System.out.println("Finished LMA at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
int stationNumber=0;
// Read camera parameters
......@@ -3635,7 +3643,9 @@ if (MORE_BUTTONS) {
LENS_DISTORTIONS.thresholdFinish=FOCUS_MEASUREMENT_PARAMETERS.thresholdFinish;
LENS_DISTORTIONS.numIterations=FOCUS_MEASUREMENT_PARAMETERS.numIterations;
LENS_DISTORTIONS.LevenbergMarquardt(false); // skip dialog
LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
if (DEBUG_LEVEL>0) System.out.println("Finished second LMA at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
if (!FOCUS_MEASUREMENT_PARAMETERS.keepCircularMask) {
DISTORTION_CALIBRATION_DATA.calculateSensorMasks(); // TODO: save/restore original mask for channel 0
......@@ -5922,7 +5932,7 @@ if (MORE_BUTTONS) {
return;
}
GenericDialog gd=new GenericDialog ("Select list mode");
gd.addNumericField("Mode 0 - pointers, 1 - shift/Rots, 2 - points/extra, 3 - rms", 0, 0);
gd.addNumericField("Mode 0 - pointers, 1 - shift/Rots, 2 - points/extra, 3 - rms", 3, 0);
gd.showDialog();
if (gd.wasCanceled()) return;
int listMode= (int) gd.getNextNumber();
......@@ -6100,7 +6110,9 @@ if (MORE_BUTTONS) {
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.stopOnFailure=false;
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0]; // 0.001; // why it does not use fitting series lambda?
boolean LMA_OK=LENS_DISTORTIONS.LevenbergMarquardt(false); // skip dialog
boolean LMA_OK=LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
if (LMA_OK) {
finalTilt[tiltIndex][axialIndex]=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerTilt;
finalAxial[tiltIndex][axialIndex]=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData.gIS[imageSetNumber].goniometerAxial;
......@@ -6177,7 +6189,9 @@ if (MORE_BUTTONS) {
LENS_DISTORTIONS.stopEachStep= false;
LENS_DISTORTIONS.stopEachSeries= false; // will not ask for confirmation after done
LENS_DISTORTIONS.lambda=LENS_DISTORTIONS.fittingStrategy.lambdas[0];
LENS_DISTORTIONS.LevenbergMarquardt(false); // skip dialog
LENS_DISTORTIONS.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
// save safe settings to run LMA manually
LENS_DISTORTIONS.seriesNumber= 0; // start from 0;
......@@ -9435,16 +9449,17 @@ if (MORE_BUTTONS) {
calculateLwirGrids();
return;
}
/* ======================================================================== */
if (label.equals("Import Subsystem")) {
importSystem(null, "EYESIS_CAMERA_PARAMETERS.");
return;
}
/* ======================================================================== */
if (label.equals("Select LWIR grids")) {
selectLwirGrids(LWIR_PARAMETERS);
return;
}
/* ======================================================================== */
if (label.equals("Manual hint")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
if (LENS_DISTORTIONS==null) {
......@@ -9466,12 +9481,19 @@ if (MORE_BUTTONS) {
LENS_DISTORTIONS.manualGridHint(numGridImage);
return;
}
/* ======================================================================== */
if (label.equals("Grid offset")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
offsetGrids(0, 0, null);
return;
}
/* ======================================================================== */
if (label.equals("LWIR to EO")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
lwirToEo();
return;
}
/* ======================================================================== */
IJ.showMessage("Not yet implemented");
......@@ -9480,6 +9502,108 @@ if (MORE_BUTTONS) {
}
/* ===== Other methods ==================================================== */
public boolean lwirToEo() {
if (LENS_DISTORTIONS == null) {
System.out.println("LENS_DISTORTIONS is null");
return false;
}
if (PATTERN_PARAMETERS == null) {
System.out.println("PATTERN_PARAMETERS is null");
return false;
}
DistortionCalibrationData dcd = LENS_DISTORTIONS.getDistortionCalibrationData();
if (dcd == null) {
dcd = DISTORTION_CALIBRATION_DATA;
}
if (dcd == null) {
System.out.println("dcd is null");
return false;
}
int min_set = 0;
int max_set = dcd.getNumSets()-1;
boolean adjust_eo = false;
boolean adjust_lwir = true;
boolean use_lma = true;
GenericDialog gd = new GenericDialog("Initial alignment of the secondary camera to the reference one");
gd.addMessage("This command used Fitting Strategy[0] that should be set with all parameters but\n"+
"GXYZ0 and GXYZ1 are set to 'fixed', and GXYZ0 and GXYZ1 are set to 'individual'.\n"+
"Each selected set should already have GXYZ set correctly (e.g. by reference cameras)");
gd.addNumericField("Image set start", min_set, 0);
gd.addNumericField("Image set last", max_set, 0);
gd.addCheckbox("Adjust EO (reference) sensors", adjust_eo);
gd.addCheckbox("Adjust LWIR (target) sensors", adjust_lwir);
gd.addCheckbox("Use LMA (unchecked - initial approximate grid setum by correlation)", use_lma);
gd.showDialog();
if (gd.wasCanceled()) return false;
min_set = (int) gd.getNextNumber();
max_set = (int) gd.getNextNumber();
adjust_eo = gd.getNextBoolean();
adjust_lwir = gd.getNextBoolean();
use_lma = gd.getNextBoolean();
if (!dcd.hasSmallSensors()) {
String msg="This system does not have any LWIR or other dependent sub-cameras";
IJ.showMessage("Error",msg);
return false;
}
if (use_lma) {
for (int num_set = min_set; num_set <=max_set; num_set++) if
((dcd.gIS[num_set] != null) && (dcd.gIS[num_set].imageSet != null)) {
for (int nc = 0; nc < dcd.getNumChannels(); nc++) {
if (dcd.gIS[num_set].imageSet[nc]!= null) {
int num_img = dcd.gIS[num_set].imageSet[nc].imgNumber;
if (dcd.isSmallSensor(num_img)) {
if (!adjust_lwir) {
continue;
}
} else {
if (!adjust_eo) {
continue;
}
}
int [] uvr = LENS_DISTORTIONS. findImageGridOffset(
num_img,
true, // boolean even, For first time - use parameter and parity of uv_rot
PATTERN_PARAMETERS);
if ((uvr != null) && ((uvr[0] != 0) || (uvr[1] != 0))) {
int [] uv_shift_rot = {uvr[0],uvr[1],0};
// int [] new_uv_shift_rots =
dcd.offsetGrid(
num_img, // int img_num,
uv_shift_rot,
PATTERN_PARAMETERS);
if (DEBUG_LEVEL > 0) {
System.out.println(num_img+ "("+num_set+"."+nc+"): uv_shift = "+uvr[0]+":"+uvr[1]);
}
}
}
}
}
} else {
for (int num_set = min_set; num_set <=max_set; num_set++) {
int extra_search =2;
double sigma = 5;
dcd.initialSetLwirFromEO( //
num_set,
EYESIS_CAMERA_PARAMETERS.invertUnmarkedLwirGrid, // boolean invert_unmarked_grid,
extra_search, // 2
sigma, //5.0
PATTERN_PARAMETERS,
true); // debug
}
}
return true;
}
public boolean offsetGrids(int ichoice, int inum, int [] uv_shift_rot) {
if (LENS_DISTORTIONS == null) {
System.out.println("LENS_DISTORTIONS is null");
......@@ -9517,7 +9641,7 @@ if (MORE_BUTTONS) {
gd.addNumericField("Image/set number", inum, 0);
gd.addCheckbox ("Auto calculate UV", auto);
if (has_lwir) {
gd.addCheckbox ("Auto from EO grid", true);
gd.addCheckbox ("Auto from EO grid (calculatre from EO even if the requested image is LWIR)", false); //true
}
gd.addNumericField("Grid offset U", uv_shift_rot[0], 0);
gd.addNumericField("Grid offset V", uv_shift_rot[1], 0);
......@@ -9580,11 +9704,17 @@ if (MORE_BUTTONS) {
// find first enabled image
for (int n:img_nums) {
if (n >= 0) {
int [] auto_uvr = dcd. suggestOffset (
n, // int num_img,
true, // boolean non_estimated,
true, // boolean even,
PATTERN_PARAMETERS); // PatternParameters patternParameters)
int [] auto_uvr = LENS_DISTORTIONS.findImageGridOffset( // null for now
n,
true, // boolean even,
PATTERN_PARAMETERS); // PatternParameters patternParameters)
// int [] auto_uvr = dcd. suggestOffset (
// n, // int num_img,
// true, // boolean non_estimated,
// true, // boolean even,
// PATTERN_PARAMETERS); // PatternParameters patternParameters)
return offsetGrids(ichoice, inum, auto_uvr);
}
}
......@@ -9616,14 +9746,14 @@ if (MORE_BUTTONS) {
LENS_DISTORTIONS=new Distortions(LENS_DISTORTION_PARAMETERS,PATTERN_PARAMETERS,REFINE_PARAMETERS,this.SYNC_COMMAND.stopRequested);
int min_files = 8; // use folders that have all 8 files
int lwir_chn0 = lwirReaderParameters.getLwirChn0();
int vnir_chn0 = lwirReaderParameters.getVnirChn0();
int eo_chn0 = lwirReaderParameters.getEoChn0();
int numStations = 3;
GenericDialog gd = new GenericDialog("Setup Goniometer/Camera Stations");
gd.addMessage("Setting up calibration that includes multiple camera tripod or goniometer positions.");
gd.addMessage("File selection dialog will open for each station separateley.");
gd.addNumericField("Number of goniometer/camera stations", numStations,0);
gd.addMessage("lwir_chn0 = "+lwir_chn0);
gd.addMessage("vnir_chn0 = "+vnir_chn0);
gd.addMessage("eo_chn0 = "+eo_chn0);
gd.addMessage("min_files = "+min_files);
gd.showDialog();
......@@ -9757,7 +9887,6 @@ if (MORE_BUTTONS) {
matchSimulatedPattern.debugLevel=MASTER_DEBUG_LEVEL;
String [] sourceSetList = DISTORTION_PROCESS_CONFIGURATION.selectSourceSets();
LWIR_PARAMETERS.selectSourceChannels();
// boolean [] sel_chn = LWIR_PARAMETERS.getSelectedVnir(); // start with regular cameras only
boolean [] sel_chn = LWIR_PARAMETERS.getSelected();
int numFiles = LWIR_PARAMETERS.getSourceFilesFlat(sourceSetList, sel_chn).length; // just the number
String [][] sourceFilesList=LWIR_PARAMETERS.getSourceFiles(sourceSetList, sel_chn);
......@@ -91,6 +91,27 @@ import ij.text.TextWindow;
return (eyesisCameraParameters==null)?0:eyesisCameraParameters.getNumStations();
}
public double getPixelSize(int station, int channel) {
return this.eyesisCameraParameters.eyesisSubCameras[station][channel].getPixelSize();
}
public double getDistortionRadius(int station, int channel) {
return this.eyesisCameraParameters.eyesisSubCameras[station][channel].getDistortionRadius();
}
public double getPixelSize(int imgNumber) {
return getPixelSize(this.gIP[imgNumber].stationNumber, this.gIP[imgNumber].channel);
}
public double getDistortionRadius(int imgNumber) {
return getDistortionRadius(this.gIP[imgNumber].stationNumber, this.gIP[imgNumber].channel);
}
public boolean isTripod() {
return (eyesisCameraParameters !=null) && this.eyesisCameraParameters.isTripod();
}
public boolean isCartesian() {
return (eyesisCameraParameters !=null) && this.eyesisCameraParameters.isCartesian();
}
public class GridImageParameters{
public int imgNumber=-1; // index of this image (for pars[][])
private int setNumber=-1; // long overdue - will be some inconsistency
......@@ -127,8 +148,9 @@ import ij.text.TextWindow;
final int contrastIndex=2;
public double getGridPeriod() { return gridPeriod;}
public void setGfridPeriod(double v) {gridPeriod = v;}
public void setGridPeriod(double v) {gridPeriod = v;}
public int getSetNumber(){return this.setNumber;}
public GridImageParameters(int index){
this.imgNumber=index;
......@@ -145,7 +167,7 @@ import ij.text.TextWindow;
public void setStationNumber(int stationNumber){ // TODO: make only a single station number - in GridImageSet?
this.stationNumber=stationNumber;
}
public double []getGridWeight(){
public double [] getGridWeight(){
return this.pixelsMask;
}
public void resetMask(){
......@@ -553,6 +575,11 @@ import ij.text.TextWindow;
"10","11","12","13","14","15","16","17","18","19",
"20","21","22","23","24","25","26","27","28","29"};
public int getNumSets() {
return gIS.length;
}
public void setupIndices(){ // should be always called during initialization !
this.index_right = getParameterIndexByName("subcamRight"); // 0 may be -1 if !cartesian
this.index_forward = getParameterIndexByName("subcamForward"); // 1 may be -1 if !cartesian
......@@ -563,13 +590,10 @@ import ij.text.TextWindow;
this.index_ga= getParameterIndexByName("goniometerAxial"); // 7
}
public boolean isCartesian(){
return (eyesisCameraParameters !=null) && eyesisCameraParameters.cartesian;
}
public String descrField(int i,int j){
if (
(eyesisCameraParameters !=null) &&
eyesisCameraParameters.cartesian &&
eyesisCameraParameters.isCartesian() &&
(i < this.parameterDescriptionsCartesian.length) &&
(this.parameterDescriptionsCartesian[i]!=null) &&
(j<this.parameterDescriptionsCartesian[i].length)){
......@@ -795,9 +819,9 @@ import ij.text.TextWindow;
String set_name = (new File(dir)).getName();
File set_dir = new File(sdir, set_name );
String [] sfiles = set_dir.list(sourceFilter);
if (sfiles == null) {
System.out.println("sfiles == null");
}
if (sfiles == null) {
System.out.println("sfiles == null");
}
for (String spath:sfiles) {
int last_dash = spath.lastIndexOf('-');
int last = spath.lastIndexOf('_');
......@@ -812,6 +836,8 @@ if (sfiles == null) {
}
}
}
boolean ignore_LWIR_pointers = true; // skip LWIR absolute marks, use them later
int max_lwir_width = 1023; // use LWIR class
setupIndices();
this.eyesisCameraParameters=eyesisCameraParameters;
int numSubCameras=(eyesisCameraParameters==null)?1:eyesisCameraParameters.eyesisSubCameras[0].length;
......@@ -906,7 +932,10 @@ if (sfiles == null) {
this.gIS[nis].motors= this.gIP[numFile].motors.clone();
this.gIP[numFile].matchedPointers = getUsedPonters(imp_grid);
if (this.gIP[numFile].matchedPointers > 0) {
with_pointers = numFile;
// Not using LWIR pointers here!
if (!ignore_LWIR_pointers || (getImagePlusProperty(imp_grid,"WOI_TOP",0) > max_lwir_width)) {
with_pointers = numFile;
}
}
double [] saturations=new double [4];
for (int i=0;i<saturations.length;i++) {
......@@ -981,8 +1010,8 @@ if (sfiles == null) {
}
}
if (with_pointers < 0) { // no matching pointers, will try to match selected channel with the pattern
int main_channel = 4; // one of the VNIR channels to match with the pattern
// boolean [] sensor_mask = null; // later may be used to limit scope to VNIR-only
int main_channel = 4; // one of the EO channels to match with the pattern
// boolean [] sensor_mask = null; // later may be used to limit scope to EO-only
int extra_search = 2;
// int base_channel = this.gIP[with_pointers].channel;
if (this.gIS[nis].imageSet[main_channel] != null) {
......@@ -1030,7 +1059,7 @@ if (sfiles == null) {
}
if (with_pointers >= 0) { // set initial grids offset from the grid files in the same image set that do not have absolute calibration
boolean [] sensor_mask = null; // later may be used to limit scope to VNIR-only
boolean [] sensor_mask = null; // later may be used to limit scope to EO-only
int extra_search = 1;
int base_channel = this.gIP[with_pointers].channel;
for (int nc = 0; nc < this.gIS[nis].imageSet.length; nc++) if ((sensor_mask == null) || sensor_mask[nc]) {
......@@ -1041,14 +1070,6 @@ if (sfiles == null) {
if (this.debugLevel>-1) System.out.print(imgNum+"*("+this.gIP[imgNum].getStationNumber()+
":"+this.gIP[imgNum].setNumber+":"+this.gIP[imgNum].channel+"): "+this.gIP[imgNum].path);
int [] uv_shift_rot0 = correlateGrids(
set_widths[base_channel], // int base_width,
set_pixels[base_channel], // float [][] base_pixels,
set_widths[nc], // int test_width,
set_pixels[nc], // float [][] test_pixels,
invert_color,
extra_search);
double [] sensor_wh = {
this.gIP[imgNum].woi.width + this.gIP[imgNum].woi.x,
this.gIP[imgNum].woi.height + this.gIP[imgNum].woi.y};
......@@ -1063,8 +1084,7 @@ if (sfiles == null) {
5.0, // 2.0, // sigma
sensor_wh,
false); // true);
System.out.print(" {"+uv_shift_rot0[0]+":"+uv_shift_rot0[1]+"->"+uv_shift_rot[0]+":"+uv_shift_rot[1]+"->");
System.out.print(" {"+uv_shift_rot[0]+":"+uv_shift_rot[1]+"->");
int [] combinedUVShiftRot=MatchSimulatedPattern.combineUVShiftRot(
this.gIS[nis].imageSet[base_channel].getUVShiftRot(),
uv_shift_rot);
......@@ -1126,6 +1146,155 @@ if (sfiles == null) {
}
public boolean initialSetLwirFromEO( //
int num_set,
boolean invert_unmarked_grid,
int extra_search, // 2
double sigma, //5.0
PatternParameters patternParameters,
boolean bdebug
) {
// see if there is any LWIR in the system is sensor and throw if there is none
if (!hasSmallSensors()) {
String msg="This system does not have any LWIR or other dependent sub-cameras";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
if ((this.gIS[num_set] == null) || (this.gIS[num_set].imageSet == null)) {
return false;
}
// See if any of the LWIR subcameras has a mark (absolute grid) in this set
int lwir_mark = -1;
for (int ns = 0; ns < this.gIS[num_set].imageSet.length; ns++) {
if (this.gIS[num_set].imageSet[ns]!=null) {
int imgNum = this.gIS[num_set].imageSet[ns].imgNumber;
if (isSmallSensor(imgNum) && (this.gIP[imgNum].matchedPointers > 0)) {
lwir_mark = ns;
break;
}
}
}
int master_sub = getEo0(); // lowest number EO channel, use as a reference
if (lwir_mark >=0) { // some LWIR grid already has mark
master_sub = lwir_mark;
if (bdebug) {
System.out.println ("Aligning to marked LWIR grid image rather than to EO one");
}
// return false;
}
if (this.gIS[num_set].imageSet[master_sub] == null) {
return false; // master EO is not available // may try to search other channels
}
int imgMaster = this.gIS[num_set].imageSet[master_sub].imgNumber;
// get EO image and pixels
ImagePlus imp_master_grid = null;
if (this.gIP[imgMaster].gridImage!=null){ // use in-memory grid images instead of the files
imp_master_grid=this.gIP[imgMaster].gridImage;
} else if (this.gIP[imgMaster].path != null) {
imp_master_grid=(new Opener()).openImage("", this.gIP[imgMaster].path);
if (imp_master_grid==null) {
String msg="Failed to read grid file "+this.gIP[imgMaster].path;
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
(new JP46_Reader_camera()).decodeProperiesFromInfo(imp_master_grid);
} else {
System.out.println("EO grid is not in memory, file path is not specified");
return false;
}
ImageStack stack_master=imp_master_grid.getStack();
if ((stack_master==null) || (stack_master.getSize()<4)) {
String msg="Expected a 8-slice stack";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
float [][] pixels_master =new float[stack_master.getSize()][]; // now - 8 (x,y,u,v,contrast, vignR,vignG,vignB
for (int i=0;i<pixels_master.length;i++) pixels_master[i]= (float[]) stack_master.getPixels(i+1); // pixel X : negative - no grid here
int width_master = imp_master_grid.getWidth();
// If master is LWIR - reset it's shift to zero
if (lwir_mark >=0) {
// reset master sub UV shift
int [] zero_uvr = {0,0,0};
this.gIS[num_set].imageSet[master_sub].setUVShiftRot(zero_uvr); // uv_shift_rot);
int [][] shiftRotMatrix= MatchSimulatedPattern.getRemapMatrix(this.gIS[num_set].imageSet[master_sub].getUVShiftRot());
setGridsWithRemap( // null immediately
imgMaster,
shiftRotMatrix, // int [][] reMap,
pixels_master,
patternParameters);
}
for (int ns = 0; ns < this.gIS[num_set].imageSet.length; ns++) {
if ((this.gIS[num_set].imageSet[ns]!=null) &&(ns != lwir_mark)) {
int imgNum = this.gIS[num_set].imageSet[ns].imgNumber;
if (isSmallSensor(imgNum)) { // repeat for all target grid images in the image set
// get target EO image and pixels
ImagePlus imp_grid = null;
if (this.gIP[imgNum].gridImage!=null){ // use in-memory grid images instead of the files
imp_grid=this.gIP[imgNum].gridImage;
} else if (this.gIP[imgNum].path != null) {
imp_grid=(new Opener()).openImage("", this.gIP[imgNum].path);
if (imp_grid==null) {
String msg="Failed to read grid file "+this.gIP[imgNum].path;
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
(new JP46_Reader_camera()).decodeProperiesFromInfo(imp_grid);
} else {
System.out.println("EO grid is not in memory, file path is not specified");
return false;
}
ImageStack stack = imp_grid.getStack();
if ((stack==null) || (stack.getSize()<4)) {
String msg="Expected a 8-slice stack";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
float [][] pixels =new float[stack.getSize()][]; // now - 8 (x,y,u,v,contrast, vignR,vignG,vignB
for (int i=0;i<pixels.length;i++) pixels[i]= (float[]) stack.getPixels(i+1); // pixel X : negative - no grid here
int width_lwir = imp_grid.getWidth();
double [] sensor_wh = {
this.gIP[imgNum].woi.width + this.gIP[imgNum].woi.x,
this.gIP[imgNum].woi.height + this.gIP[imgNum].woi.y};
int [] uv_shift_rot = correlateGrids(
width_master, // int base_width,
pixels_master, // float [][] base_pixels,
width_lwir, // int test_width,
pixels, // float [][] test_pixels,
invert_unmarked_grid,
extra_search,
sigma,
sensor_wh,
false); // true); //bdebug
// combined rotation - first this, next what is applied to EO channel
int [] combinedUVShiftRot=MatchSimulatedPattern.combineUVShiftRot(
uv_shift_rot,
this.gIS[num_set].imageSet[master_sub].getUVShiftRot()
);
if (bdebug) {
System.out.print(imgNum+": calculated uv_shift_rot= ["+uv_shift_rot[0]+":"+uv_shift_rot[1]+"], ");
System.out.print(imgNum+": EO uv_shift_rot= ["+this.gIS[num_set].imageSet[master_sub].getUVShiftRot()[0]+
":"+this.gIS[num_set].imageSet[master_sub].getUVShiftRot()[1]+"], ");
System.out.println(imgNum+": combined uv_shift_rot= ["+combinedUVShiftRot[0]+":"+combinedUVShiftRot[1]+"]");
}
this.gIS[num_set].imageSet[ns].setUVShiftRot(combinedUVShiftRot); // uv_shift_rot);
int [][] shiftRotMatrix= MatchSimulatedPattern.getRemapMatrix(this.gIS[num_set].imageSet[ns].getUVShiftRot());
setGridsWithRemap( // null immediately
imgNum,
shiftRotMatrix, // int [][] reMap,
pixels,
patternParameters);
}
}
}
return true; // OK
}
// provide image set index for the same station that has at least one marked image
// non_estimated - disregard images with estimated orientation
public int getMarkedSet(int num_set, boolean non_estimated) {
......@@ -1151,6 +1320,12 @@ if (sfiles == null) {
return this.gIS[ns].GXYZ;
}
public double [] getXYZ(int num_img) {
int ns = gIP[num_img].getSetNumber();
return this.gIS[ns].GXYZ;
}
// suggest set grid offset by comparing with known (by mark) set.
// Wrong Grid UV should cause parallel shift - same Z, different XY
public int [] suggestOffset (
......@@ -1158,8 +1333,7 @@ if (sfiles == null) {
boolean non_estimated,
boolean even,
PatternParameters patternParameters) {
int num_set = this.gIP[num_img].setNumber;
int station = this.gIS[num_set].stationNumber;
int num_set = this.gIP[num_img].getSetNumber();
double [] ref_xyz = getXYZFromMarked(num_set, non_estimated);
if (ref_xyz == null) {
System.out.println("Error: Could not find reference goniometer XYZ for set "+num_set);
......@@ -1167,41 +1341,55 @@ if (sfiles == null) {
}
double [] diff_xyz = this.gIS[num_set].GXYZ.clone();
for (int i = 0; i < diff_xyz.length; i++) diff_xyz[i]-=ref_xyz[i];
return suggestOffset (
num_img,
diff_xyz, // z is not used, may ne just[2]
even,
patternParameters);
}
public int [] suggestOffset (
int num_img,
double [] diff_xyz, // This XYZ minus reference XYZ z is not used, may be just[2]
boolean even,
PatternParameters patternParameters) {
int num_set = this.gIP[num_img].setNumber;
int station = this.gIS[num_set].stationNumber;
int [][] pixelsUV = this.gIP[num_img].pixelsUV ; // null; // for each image, each grid node - a pair of {gridU, gridV}
if ((pixelsUV == null) || ((pixelsUV.length <3 ))) {
System.out.println("No/too few pixelsUV data for image "+num_img);
return null;
}
double [][][] data =new double [pixelsUV.length][3][];
for (int i=0; i < pixelsUV.length; i++){
data[i][0]=new double[2];
data[i][1]=new double[2];
data[i][2]=new double[1];
double [] xyzm = patternParameters.getXYZM(
pixelsUV[i][0],
pixelsUV[i][1],
false, // boolean verbose,
station); // int station)
data[i][0][0]=xyzm[0];// pixelsXY[i][0];
data[i][0][1]=xyzm[1];// pixelsXY[i][1];
data[i][1][0]=pixelsUV[i][0];
data[i][1][1]=pixelsUV[i][1];
data[i][2][0]=xyzm[3];// mask
}
double [][] coeff=new PolynomialApproximation(this.debugLevel).quadraticApproximation(data, true); // force linear
double [] dUV = {
-(coeff[0][0]* diff_xyz[0] + coeff[0][1]* diff_xyz[1]),
-(coeff[1][0]* diff_xyz[0] + coeff[1][1]* diff_xyz[1])};
for (int i=0; i < pixelsUV.length; i++){
data[i][0]=new double[2];
data[i][1]=new double[2];
data[i][2]=new double[1];
double [] xyzm = patternParameters.getXYZM(
pixelsUV[i][0],
pixelsUV[i][1],
false, // boolean verbose,
station); // int station)
data[i][0][0]=xyzm[0];// pixelsXY[i][0];
data[i][0][1]=xyzm[1];// pixelsXY[i][1];
data[i][1][0]=pixelsUV[i][0];
data[i][1][1]=pixelsUV[i][1];
data[i][2][0]=xyzm[3];// mask
}
double [][] coeff=new PolynomialApproximation(this.debugLevel).quadraticApproximation(data, true); // force linear
double [] dUV = {
-(coeff[0][0]* diff_xyz[0] + coeff[0][1]* diff_xyz[1]),
-(coeff[1][0]* diff_xyz[0] + coeff[1][1]* diff_xyz[1])};
int [] idUV = {(int) Math.round(dUV[0]), (int) Math.round(dUV[1]), 0}; // 0 - no rot
int parity = (idUV[0]+idUV[1] + (even?0:1)) & 1;
double [] UV_err = {dUV[0]-idUV[0], dUV[1]-idUV[1]};
double [] UV_err = {dUV[0]-idUV[0], dUV[1]-idUV[1]};
if (parity !=0) {
if (UV_err[1] > UV_err[0]) {
if (UV_err[1] > -UV_err[0]) idUV[1]++;
else idUV[0]--;
if (UV_err[1] > -UV_err[0]) idUV[1]++;
else idUV[0]--;
} else {
if (UV_err[1] > -UV_err[0]) idUV[0]++;
else idUV[1]--;
if (UV_err[1] > -UV_err[0]) idUV[0]++;
else idUV[1]--;
}
UV_err[0] = dUV[0] - idUV[0];
UV_err[1] = dUV[1] - idUV[1];
......@@ -3101,6 +3289,11 @@ if (sfiles == null) {
this.gIP[fileNumber].gridImage = imp_grid;
}
}
this.gIP[fileNumber].woi = new Rectangle(
getImagePlusProperty(imp_grid,"WOI_LEFT",0),
getImagePlusProperty(imp_grid,"WOI_TOP",0),
getImagePlusProperty(imp_grid,"WOI_WIDTH", eyesisCameraParameters.getSensorWidth(this.gIP[fileNumber].getChannel())),
getImagePlusProperty(imp_grid,"WOI_HEIGHT", eyesisCameraParameters.getSensorHeight(this.gIP[fileNumber].getChannel())));
this.gIP[fileNumber].laserPixelCoordinates=MatchSimulatedPattern.getPointersXYUV(imp_grid, laserPointers);
this.gIP[fileNumber].motors=getMotorPositions(imp_grid, this.numMotors);
this.gIP[fileNumber].matchedPointers=getUsedPonters(imp_grid);
......@@ -3536,7 +3729,7 @@ if (sfiles == null) {
// public double small_period_frac = 0; // set by filter grids - ratio of small sensor period to large sensor period
// depending on camera type, return group, groups, group name
// camera type: eyesis26, lwir/vnir (2 resolutions) , single, other
// camera type: eyesis26, lwir/eo (2 resolutions) , single, other
//getNumSubCameras()
public int getNumLwir() {
if (hasSmallSensors()) {
......@@ -3547,10 +3740,10 @@ if (sfiles == null) {
return 0;
}
}
public int getNumVnir() {
public int getNumEo() {
return getNumSubCameras() - getNumLwir();
}
public int getVnir0() {
public int getEo0() {
if (hasSmallSensors()) {
for (int i = 0; i < small_sensors.length; i++) if (!small_sensors[i]) return i;
return -1; // should not happen
......@@ -3574,7 +3767,7 @@ if (sfiles == null) {
int n = 2;
if (hasSmallSensors()) {
if (getNumLwir() > 1) n++;
if (getNumVnir() > 1) n++;
if (getNumEo() > 1) n++;
}
return n;
}
......@@ -3594,11 +3787,11 @@ if (sfiles == null) {
if (hasSmallSensors()) {
if (small_sensors[chn]) { // current is LWIR
n = 1;
if (getNumVnir() > 1) n = 2;
if (getNumEo() > 1) n = 2;
if (chn != getLwir0()) n++;
} else { // current is VNIR
} else { // current is EO
n = 0;
if (chn != getVnir0()) n++;
if (chn != getEo0()) n++;
}
}
return n;
......@@ -3606,7 +3799,7 @@ if (sfiles == null) {
// check if the channel is the first in group
public boolean firstInGroup(int chn) {
if (chn >= 24) return (chn == 24);
if ((chn == getVnir0()) || (chn == getLwir0())) return true;
if ((chn == getEo0()) || (chn == getLwir0())) return true;
int [] num = {0,0};
for (int i = 0; i < chn; i++) {
if ((small_sensors != null) && small_sensors[i]) num[1]++;
......@@ -3631,13 +3824,13 @@ if (sfiles == null) {
if (chn != getLwir0()) return full?"Subcamera LWIR other":"sub-lwir-other";
if (getNumLwir() > 1) return full?"Subcamera LWIR 0":"sub-lwir0";
return full?"Subcamera LWIR":"sub-lwir";
} else { // current is VNIR
if (chn != getVnir0()) return full?"Subcamera VNIR other":"sub-vnir-other";
if (getNumVnir() > 1) return full?"Subcamera VNIR 0":"sub-vnir0";
return full?"Subcamera VNIR":"sub-vnir";
} else { // current is EO
if (chn != getEo0()) return full?"Subcamera EO other":"sub-eo-other";
if (getNumEo() > 1) return full?"Subcamera EO 0":"sub-eo0";
return full?"Subcamera EO":"sub-eo";
}
}
if (chn != getVnir0()) return full?"Subcamera other":"sub-other";
if (chn != getEo0()) return full?"Subcamera other":"sub-other";
return full?"Subcamera 0":"sub0";
}
......
......@@ -521,42 +521,70 @@ public class Distortions {
// Individual image mask is needed as some parts can be obscured by moving parts - not present on all images.
// grid "contrast" may be far from 1.0 but probably should work OK
/// double gridContrast= fittingStrategy.distortionCalibrationData.gIP[imgNum].pixelsXY[pointNumber][2]-minimalGridContrast;//minimalGridContrast\
double dbg;
// if (weight > 0) {
if ((weight > 0) && (imgNum == 244)) {
dbg = weight;
}
if ((filter & this.filterContrast)!=0) {
double gridContrast= gridWeight[pointNumber];
weight*=gridContrast;
if (Double.isNaN(gridContrast) && (this.debugLevel>1)) System.out.println("gridContrast=NaN, imgNum="+imgNum);
}
// if (weight > 0) {
if ((weight > 0) && (imgNum == 244)) {
dbg = weight;
}
if ((filter & this.filterTargetMask)!=0) {
weight*=XYZMP[patternMaskIndex];//DONE: Use grid mask also (fade out outer grid nodes?)
if (Double.isNaN(XYZMP[patternMaskIndex]) && (this.debugLevel>1)) System.out.println("XYZMP["+patternMaskIndex+"]=NaN, imgNum="+imgNum);
}
// if (weight > 0) {
if ((weight > 0) && (imgNum == 244)) {
dbg = weight;
}
if ((filter & this.filterTargetAlpha)!=0) {
weight*=XYZMP[patternAlphaIndex];//DONE: Use grid mask also (fade out outer grid nodes?)
if (Double.isNaN(XYZMP[patternAlphaIndex]) && (this.debugLevel>1)) System.out.println("XYZMP["+patternAlphaIndex+"]=NaN, imgNum="+imgNum);
}
// if (weight > 0) {
if ((weight > 0) && (imgNum == 244)) {
dbg = weight;
}
if ((filter & this.filterTargetErrors)!=0) {
weight*=XYZMP[patternErrorMaskIndex];//DONE: Use grid mask also (fade out outer grid nodes?)
if (Double.isNaN(XYZMP[patternErrorMaskIndex]) && (this.debugLevel>1)) System.out.println("XYZMP["+patternErrorMaskIndex+"]=NaN, imgNum="+imgNum);
}
// if (weight > 0) {
if ((weight > 0) && (imgNum == 244)) {
dbg = weight;
}
if ((filter & this.filterMulti)!=0) {
weight*=multiWeight[imgNum];
if (Double.isNaN(multiWeight[imgNum]) && (this.debugLevel>1)) System.out.println("multiWeight["+imgNum+"]=NaN, imgNum="+imgNum);
}
// if (weight > 0) {
if ((weight > 0) && (imgNum == 244)) {
dbg = weight;
}
if ((filter & this.filterMaskBadNodes)!=0) {
if (fittingStrategy.distortionCalibrationData.gIP[imgNum].isNodeBad(pointNumber)) weight=0.0;
}
// if (weight > 0) {
if ((weight > 0) && (imgNum == 244)) {
dbg = weight; // got here
}
//fittingStrategy.distortionCalibrationData.eyesisCameraParameters.weightMultiExponent)
if (((filter & this.filterDiameter)!=0) && (fittingStrategy.distortionCalibrationData.eyesisCameraParameters.weightDiameterExponent>0.0)) {
weight*=gridImageWeight;
if (Double.isNaN(gridImageWeight) && (this.debugLevel>1)) System.out.println("gridImageWeight=NaN, imgNum="+imgNum);
}
// if (weight > 0) {
if ((weight > 0) && (imgNum == 244)) {
dbg = weight;
}
if (Double.isNaN(weight)) {
weight=0.0; // find who makes it NaN
if (Double.isNaN(multiWeight[imgNum])) System.out.println("weight is null, imgNum="+imgNum);
......@@ -619,7 +647,9 @@ public class Distortions {
continue;
}
if (this.weightFunction[2*(index+pointNumber)]>0.0) numValidNodes++; //OOB 5064
if (this.weightFunction[2*(index+pointNumber)]>0.0) {
numValidNodes++; //OOB 5064
}
}
if (numValidNodes<this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.minimalValidNodes){
this.fittingStrategy.invalidateSelectedImage(numSeries,imgNum);
......@@ -3269,19 +3299,14 @@ For each point in the image
public LensDistortionParameters setupLensDistortionParameters(
int numImg,
// int stationNumber,
// int subCamera,
int debugLevel){ // Axial - may be Double.NaN
// double [] parVector=fittingStrategy.distortionCalibrationData.eyesisCameraParameters.getParametersVector(stationNumber,subCamera);
// System.out.println("setupLensDistortionParameters(): subCamera="+subCamera+", goniometerHorizontal="+goniometerHorizontal+", goniometerAxial="+goniometerAxial);
boolean isTripod=this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod;
boolean cartesian=this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian;
LensDistortionParameters lensDistortionParameters = new LensDistortionParameters (
isTripod,
cartesian,
this.fittingStrategy.distortionCalibrationData.isTripod(),
this.fittingStrategy.distortionCalibrationData.isCartesian(),
this.fittingStrategy.distortionCalibrationData.getPixelSize(numImg),
this.fittingStrategy.distortionCalibrationData.getDistortionRadius(numImg),
null, //double [][] interParameterDerivatives, //partial derivative matrix from subcamera-camera-goniometer to single camera (12x21) if null - just values, no derivatives
// this.fittingStrategy.distortionCalibrationData.pars[numImg], //parVector,
this.fittingStrategy.distortionCalibrationData.getParameters(numImg), //parVector,
null, //boolean [] mask, // calculate only selected derivatives (all parVect values are still
debugLevel
......@@ -3298,16 +3323,13 @@ For each point in the image
double [] parVector=fittingStrategy.distortionCalibrationData.eyesisCameraParameters.getParametersVector(stationNumber,subCamera);
int goniometerHorizontalIndex=fittingStrategy.distortionCalibrationData.eyesisCameraParameters.getGoniometerHorizontalIndex();
int goniometerAxialIndex=fittingStrategy.distortionCalibrationData.eyesisCameraParameters.getGoniometerAxialIndex();
// int sensorWidth=fittingStrategy.distortionCalibrationData.eyesisCameraParameters.getSensorWidth(subCamera);
// int sensorHeight=fittingStrategy.distortionCalibrationData.eyesisCameraParameters.getSensorHeight(subCamera);
if (!Double.isNaN(goniometerHorizontal))parVector[goniometerHorizontalIndex]=goniometerHorizontal;
if (!Double.isNaN(goniometerAxial))parVector[goniometerAxialIndex]=goniometerAxial;
// System.out.println("setupLensDistortionParameters(): subCamera="+subCamera+", goniometerHorizontal="+goniometerHorizontal+", goniometerAxial="+goniometerAxial);
boolean isTripod=this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod;
boolean cartesian=this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian;
LensDistortionParameters lensDistortionParameters = new LensDistortionParameters (
isTripod,
cartesian,
this.fittingStrategy.distortionCalibrationData.isTripod(),
this.fittingStrategy.distortionCalibrationData.isCartesian(),
this.fittingStrategy.distortionCalibrationData.getPixelSize(stationNumber, subCamera),
this.fittingStrategy.distortionCalibrationData.getDistortionRadius(stationNumber, subCamera),
null, //double [][] interParameterDerivatives, //partial derivative matrix from subcamera-camera-goniometer to single camera (12x21) if null - just values, no derivatives
parVector,
null, //boolean [] mask, // calculate only selected derivatives (all parVect values are still
......@@ -3450,8 +3472,10 @@ For each point in the image
System.out.println("estimateGridOnSensor(): subCamera="+subCamera+", goniometerHorizontal="+goniometerHorizontal+", goniometerAxial="+goniometerAxial);
this.lensDistortionParameters.lensCalcInterParamers(
this.lensDistortionParameters, // 22-long parameter vector for the image
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian,
this.fittingStrategy.distortionCalibrationData.isTripod(),
this.fittingStrategy.distortionCalibrationData.isCartesian(),
this.fittingStrategy.distortionCalibrationData.getPixelSize(stationNumber, subCamera),
this.fittingStrategy.distortionCalibrationData.getDistortionRadius(stationNumber, subCamera),
null, // this.interParameterDerivatives, // [22][]
parVector,
null); // if no derivatives, null is OK
......@@ -3570,13 +3594,14 @@ For each point in the image
return; // no images found
}
double [] imgVector=fittingStrategy.getImageParametersVector(imgNum, vector); //this.currentVector);
// boolean [] imgMask= fittingStrategy.getImageParametersVectorMask(imgNum);
boolean [] imgMask= new boolean[imgVector.length];
for (int i=0;i<imgMask.length;i++) imgMask[i]=true;
this.lensDistortionParameters.lensCalcInterParamers(
this.lensDistortionParameters,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian,
this.fittingStrategy.distortionCalibrationData.isTripod(),
this.fittingStrategy.distortionCalibrationData.isCartesian(),
this.fittingStrategy.distortionCalibrationData.getPixelSize(imgNum),
this.fittingStrategy.distortionCalibrationData.getDistortionRadius(imgNum),
this.interParameterDerivatives, // [22][]
imgVector,
imgMask); // calculate only selected derivatives (all parVect values are still
......@@ -3599,8 +3624,10 @@ For each point in the image
vector_delta[i]+=delta;
this.lensDistortionParameters.lensCalcInterParamers(
this.lensDistortionParameters,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian,
this.fittingStrategy.distortionCalibrationData.isTripod(),
this.fittingStrategy.distortionCalibrationData.isCartesian(),
this.fittingStrategy.distortionCalibrationData.getPixelSize(imgNum),
this.fittingStrategy.distortionCalibrationData.getDistortionRadius(imgNum),
null, // this.interParameterDerivatives, // just values, no derivatives
vector_delta,
imgMask);
......@@ -3687,8 +3714,10 @@ For each point in the image
this.lensDistortionParameters.debugLevel=this.debugLevel;
this.lensDistortionParameters.lensCalcInterParamers(
this.lensDistortionParameters,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian,
this.fittingStrategy.distortionCalibrationData.isTripod(),
this.fittingStrategy.distortionCalibrationData.isCartesian(),
this.fittingStrategy.distortionCalibrationData.getPixelSize(imgNum),
this.fittingStrategy.distortionCalibrationData.getDistortionRadius(imgNum),
calcJacobian?this.interParameterDerivatives:null, // [22][]
imgVector,
imgMask); // imgMask may be null if no derivativescalculate only selected derivatives (all parVect values are still
......@@ -3805,8 +3834,10 @@ For each point in the image
if (this.debugLevel>3) System.out.println("calculatePartialFxAndJacobian(), numImage="+numImage+" calcInterParamers():");
lensDistortionParameters.lensCalcInterParamers(
lensDistortionParameters,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian,
this.fittingStrategy.distortionCalibrationData.isTripod(),
this.fittingStrategy.distortionCalibrationData.isCartesian(),
this.fittingStrategy.distortionCalibrationData.getPixelSize(numImage),
this.fittingStrategy.distortionCalibrationData.getDistortionRadius(numImage),
calcJacobian?interParameterDerivatives:null, // [22][]
imgVector,
imgMask); // calculate only selected derivatives (all parVect values are still
......@@ -3889,8 +3920,10 @@ For each point in the image
}
this.lensDistortionParameters.lensCalcInterParamers(
this.lensDistortionParameters,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian,
this.fittingStrategy.distortionCalibrationData.isTripod(),
this.fittingStrategy.distortionCalibrationData.isCartesian(),
this.fittingStrategy.distortionCalibrationData.getPixelSize(imgNum),
this.fittingStrategy.distortionCalibrationData.getDistortionRadius(imgNum),
null, //this.interParameterDerivatives, // [22][]
imgVector,
imgMask); // calculate only selected derivatives (all parVect values are still
......@@ -4436,8 +4469,10 @@ List calibration
}
this.lensDistortionParameters.lensCalcInterParamers(
this.lensDistortionParameters,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian,
this.fittingStrategy.distortionCalibrationData.isTripod(),
this.fittingStrategy.distortionCalibrationData.isCartesian(),
this.fittingStrategy.distortionCalibrationData.getPixelSize(imgNum),
this.fittingStrategy.distortionCalibrationData.getDistortionRadius(imgNum),
null, //this.interParameterDerivatives, // [22][]
// fittingStrategy.distortionCalibrationData.pars[imgNum], // 22-long parameter vector for the image
fittingStrategy.distortionCalibrationData.getParameters(imgNum), // 22-long parameter vector for the image
......@@ -7412,8 +7447,81 @@ List calibration
return masks;
}
// Use series0 to find grid mismatch (and set it correctly). Uses that pattern in the world coordinate system is
// approximately in XY plane, so by freezing all other parameters but GXY0 and GXY1 it is possible to find
// the pattern grid match.
public int [] findImageGridOffset(
int num_img,
boolean even,
PatternParameters patternParameters) {
// set series 0 to this set images
boolean [] selection = fittingStrategy.selectAllImages(0); // enable all images in series 0
for (int i=0;i<selection.length;i++) selection[i]=false;
selection[num_img]=true;
fittingStrategy.setImageSelection(0,selection);
seriesNumber= 0; // start from 0;
initFittingSeries(false, filterForAll,0); // will set this.currentVector
//this.stopAfterThis[numSeries]
fittingStrategy.stopAfterThis[0]=true;
stopEachStep= false;
stopEachSeries= false; // will not ask for confirmation after done
lambda = fittingStrategy.lambdas[0];
boolean LMA_OK = false;
try {
LMA_OK = LevenbergMarquardt (false, true); // skip dialog, dry run (no updates)
} catch (Exception e) {
// LMA failed - e.g. not enough points (Singular Matrix)
}
if (!LMA_OK) {
return null; // LMA did not converge
}
double [] new_XY = {this.currentVector[0],this.currentVector[1]};
DistortionCalibrationData dcd = this.fittingStrategy.distortionCalibrationData;
// int num_set = dcd.gIP[num_img].getSetNumber();
double [] ref_XYZ = dcd.getXYZ(num_img);
double [] diff_XY = {
new_XY[0] -ref_XYZ[0],
new_XY[1] -ref_XYZ[1]};
//save safe settings to run LMA manually (or save what was set)
seriesNumber= 0; // start from 0;
initFittingSeries (false,filterForAll,0); // will set this.currentVector
stopEachSeries= true; // will not ask for confirmation after done
stopOnFailure= true;
lambda= fittingStrategy.lambdas[0];
int [] grid_offset = dcd.suggestOffset (
num_img,
diff_XY, // This XYZ minus reference XYZ z is not used, may be just[2]
even,
patternParameters);
return grid_offset;
public boolean LevenbergMarquardt(boolean openDialog){
/*
*
this.currentVector[0] - GXYZ[0]
this.currentVector[1] - GXYZ[1]
dcd. public int [] suggestOffset (
int num_img,
double [] diff_xyz, // This XYZ minus reference XYZ z is not used, may be just[2]
boolean even,
PatternParameters patternParameters) {
*/
}
public boolean LevenbergMarquardt(
boolean openDialog,
boolean dry_run){ // do not save results
if (this.fittingStrategy==null) {
String msg="Fitting strategy does not exist, exiting";
IJ.showMessage("Error",msg);
......@@ -7497,7 +7605,7 @@ List calibration
") at "+ IJ.d2s(0.000000001*(System.nanoTime()-this.startTime),3));
}
if (!cont){
if (this.saveSeries) {
if (this.saveSeries && !dry_run) {
saveFittingSeries(); // will save series even if it ended in failure, vector will be only updated
updateCameraParametersFromCalculated(true); // update camera parameters from all (even disabled) images
updateCameraParametersFromCalculated(false); // update camera parameters from enabled only images (may overwrite some of the above)
......@@ -7508,11 +7616,15 @@ List calibration
//stepLevenbergMarquardtAction();
if (state[1]) {
if (!state[0]) return false; // sequence failed
saveFittingSeries();
updateCameraParametersFromCalculated(true); // update camera parameters from all (even disabled) images
updateCameraParametersFromCalculated(false); // update camera parameters from enabled only images (may overwrite some of the above)
wasLastSeries=this.fittingStrategy.isLastSeries(this.seriesNumber);
this.seriesNumber++;
if (dry_run) {
wasLastSeries= true; // always just one series
} else {
saveFittingSeries();
updateCameraParametersFromCalculated(true); // update camera parameters from all (even disabled) images
updateCameraParametersFromCalculated(false); // update camera parameters from enabled only images (may overwrite some of the above)
wasLastSeries=this.fittingStrategy.isLastSeries(this.seriesNumber);
this.seriesNumber++;
}
break; // while (true), proceed to the next series
}
}
......@@ -8024,8 +8136,8 @@ D2=
final int threadsMax,
final boolean updateStatus
){
final boolean isTripod=this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod;
final boolean cartesian=this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian;
// final boolean isTripod=this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.is_tripod;
// final boolean cartesian=this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian;
final int [][] dirs= {{0,0},{-1,0},{1,0},{0,-1},{0,1}}; // possible to make 8 directions
final double [][][] derivatives={ // for of /du, /dv 3 variants, depending on which neighbors are available
{
......@@ -8078,10 +8190,11 @@ D2=
// The following method sets this.lensDistortionParameters and invokes this.lensDistortionParameters.recalcCommons();
lensDistortionParameters.lensCalcInterParamers(
lensDistortionParameters,
isTripod,
cartesian,
fittingStrategy.distortionCalibrationData.isTripod(),
fittingStrategy.distortionCalibrationData.isCartesian(),
fittingStrategy.distortionCalibrationData.getPixelSize(imgNum),
fittingStrategy.distortionCalibrationData.getDistortionRadius(imgNum),
null, //this.interParameterDerivatives, // [22][]
// fittingStrategy.distortionCalibrationData.pars[imgNum], // 22-long parameter vector for the image
fittingStrategy.distortionCalibrationData.getParameters(imgNum), // 22-long parameter vector for the image
null); // if no derivatives, null is OK
// false); // calculate this.interParameterDerivatives -derivatives array (false - just this.values)
......@@ -8276,8 +8389,10 @@ D2=
// The following method sets this.lensDistortionParameters and invokes this.lensDistortionParameters.recalcCommons();
this.lensDistortionParameters.lensCalcInterParamers(
this.lensDistortionParameters,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.isTripod,
this.fittingStrategy.distortionCalibrationData.eyesisCameraParameters.cartesian,
fittingStrategy.distortionCalibrationData.isTripod(),
fittingStrategy.distortionCalibrationData.isCartesian(),
fittingStrategy.distortionCalibrationData.getPixelSize(imgNum),
fittingStrategy.distortionCalibrationData.getDistortionRadius(imgNum),
null, //this.interParameterDerivatives, // [22][]
// fittingStrategy.distortionCalibrationData.pars[imgNum], // 22-long parameter vector for the image
fittingStrategy.distortionCalibrationData.getParameters(imgNum), // 22-long parameter vector for the image
......@@ -9722,6 +9837,8 @@ M * V = B
}
}
LensDistortionParameters ldp=this.lensDistortionParameters.clone();
// 06/2019 - need to update distortionRadius, pixelSize)
// public void setLensDistortionParameters(LensDistortionParameters ldp
for (int v=0; v<gridHeight; v++) for (int u=0; u<gridWidth; u++) if (patternParameters.gridGeometry[v][u][3]>0) {
......
......@@ -1520,9 +1520,10 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
for (;(endIndex<enabled.length) && !allImages && !enabled[endIndex];endIndex++); // advance over disabled images
GenericDialog gd=new GenericDialog("Select images "+startIndex+"..."+(endIndex-1));
for (int i=startIndex;i<endIndex;i++) if (allImages || enabled[i]){
gd.addCheckbox (i+" - "+(this.distortionCalibrationData.gIP[i].enabled?"":"(disabled) ")+
gd.addCheckbox (i+ " ("+this.distortionCalibrationData.gIP[i].getSetNumber()+
"."+this.distortionCalibrationData.gIP[i].getChannel()+")"+
" - "+(this.distortionCalibrationData.gIP[i].enabled?"":"(disabled) ")+
IJ.d2s(this.distortionCalibrationData.gIP[i].timestamp,6)+
": "+this.distortionCalibrationData.gIP[i].channel+
" matched "+this.distortionCalibrationData.gIP[i].matchedPointers+" pointers"+
", hinted state: "+((hintedMatch[i]<0)?"undefined":((hintedMatch[i]==0)?"failed":((hintedMatch[i]==1)?"orientation":"orientation and translation"))),
selection[i]);
......@@ -1852,7 +1853,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
// gd.addCheckbox("Select images with estimated orientation", selectEstimated);
// gd.addCheckbox("Select new enabled images", selectNewEnabled);
if (this.distortionCalibrationData.hasSmallSensors()) {
gd.addMessage("=== Filter selection by High/Low resolution sensors (such as VNIR/LWIR)");
gd.addMessage("=== Filter selection by High/Low resolution sensors (such as EO/LWIR)");
gd.addCheckbox("Select high-res sensors", true);
gd.addCheckbox("Select low-res sensors", true);
}
......@@ -1977,7 +1978,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
* @param useParameters Select parameters for this series
* @param askNextSeries Ask for next series number
* @param zeroAndOther use 2 channels 0 and "other", propagate settings for channel 1 to all the rest
* For low/high res (LWIR/VNIR) - use first /other for each class
* For low/high res (LWIR/EO) - use first /other for each class
* @return -2 - cancel, -1, done, otherwise - number of step to edit
*/
......@@ -2055,7 +2056,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
// sub(other): their group number - no, 0 - later add this.definedModesAll.length to master subcamera
// not zeroAndOther:
// non-sub - -1:
// sub(>0): subCam-1 (previous index) - will suggest any with smaller index - may be useless with lwir < vnir indices
// sub(>0): subCam-1 (previous index) - will suggest any with smaller index - may be useless with lwir < eo indices
// int subMaxNum = (this.distortionCalibrationData.isSubcameraParameter(parIndex) && (subCam > 0)) ? (zeroAndOther? 0 : (subCam-1)):-1;
int subMaxNum = -1;
if (this.distortionCalibrationData.isSubcameraParameter(parIndex)) { // only for subcamera parameters
......@@ -2120,7 +2121,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
* @param useParameters Select parameters for this series
* @param askNextSeries Ask for next series number
* @param zeroAndOther use 2 channels 0 and "other", propagate settings for channel 1 to all the rest
* Updated for more groups (up to 4 in LWIR/VNIR) - use 1 channel for each group, propagate to the rest of the group
* Updated for more groups (up to 4 in LWIR/EO) - use 1 channel for each group, propagate to the rest of the group
* @return -2 - cancel, -1, done, otherwise - number of step to edit
*/
public int selectStrategyStep(
......@@ -2187,7 +2188,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
for (int i=0;i<this.distortionCalibrationData.eyesisCameraParameters.numStations;i++) gd.addCheckbox("Station "+i, constrainByStation[i]);
}
if (this.distortionCalibrationData.hasSmallSensors()) {
gd.addMessage("Constrain (select/remove all) by High/Low resolution sensors (such as VNIR/LWIR)");
gd.addMessage("Constrain (select/remove all) by High/Low resolution sensors (such as EO/LWIR)");
gd.addCheckbox("Select high-res sensors", true);
gd.addCheckbox("Select low-res sensors", true);
}
......@@ -2272,7 +2273,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
// sub(other): their group number - no, 0
// not zeroAndOther:
// non-sub - -1:
// sub(>0): subCam-1 (previous index) - will suggest any with smaller index - may be useless with lwir < vnir indices
// sub(>0): subCam-1 (previous index) - will suggest any with smaller index - may be useless with lwir < eo indices
// int subMaxNum = (this.distortionCalibrationData.isSubcameraParameter(parIndex) && (subCam > 0)) ? (zeroAndOther? 0 : (subCam-1)):-1;
int subMaxNum = -1;
if (this.distortionCalibrationData.isSubcameraParameter(parIndex)) { // only for subcamera parameters
......
......@@ -989,7 +989,9 @@ horizontal axis:
// TODO: Set initial values for the goniometer angles from the sensor
// (channel) number, average them if there are several in the list
lensDistortions.LevenbergMarquardt(false); // skip dialog
lensDistortions.LevenbergMarquardt(
false, // skip dialog
false); // new: dry_run use it here?
if (debug_level > 0)
System.out.println("Finished LMA at "
+ IJ.d2s(0.000000001 * (System.nanoTime() - startTime), 3));
......
......@@ -5,9 +5,9 @@ import java.util.Properties;
import com.elphel.imagej.cameras.EyesisSubCameraParameters;
import com.elphel.imagej.common.WindowTools;
import Jama.Matrix;
import ij.IJ;
import ij.gui.GenericDialog;
import Jama.Matrix;
//import EyesisCameraParameters;
//import Distortions.EyesisSubCameraParameters;
......@@ -28,7 +28,7 @@ import Jama.Matrix;
// boolean cummulativeCorrection=true; // r_xy, r_od for higher terms are relative to lower ones
public int defaultLensDistortionModel=200;
public int lensDistortionModel=defaultLensDistortionModel;
public int lensDistortionModelType=0; // set from lensDistortionModel
public int lensDistortionModelType=0; // set from lensDistortionModel
boolean cummulativeCorrection=false; //true; // r_xy, r_od for higher terms are relative to lower ones
public double focalLength=4.5;
public double pixelSize= 2.2; //um
......@@ -51,18 +51,18 @@ import Jama.Matrix;
public double px0=1296.0; // center of the lens on the sensor, pixels
public double py0=968.0; // center of the lens on the sensor, pixels
public boolean flipVertical; // acquired image is mirrored vertically (mirror used)
// new non-radial parameters
final private double [][] r_xy_dflt={{0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0}}; // only 6, as for the first term delta x, delta y ==0
final private double [][] r_xy_dflt={{0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0}}; // only 6, as for the first term delta x, delta y ==0
final private double [][] r_od_dflt= {{0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0}}; // ortho
public double [][] r_xy=null; // only 6, as for the first term delta x, delta y ==0
public double [][] r_xy=null; // only 6, as for the first term delta x, delta y ==0
public double [][] r_od=null; // ortho
public double [][] r_xyod=null; //{x0,y0,ortho, diagonal}
public double [][] r_xyod=null; //{x0,y0,ortho, diagonal}
// total number of new parameters = 6*2+7+7=26
public int debugLevel=1; // was 2
/*
Modifying to accommodate for eccentricity of different terms (2 parameters per term) and elliptical shape (another 2 terms). When all are
......@@ -70,13 +70,13 @@ import Jama.Matrix;
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)");
Rdist/R=A8*R6^7+A7*R5^6+A6*R4^5+A5*R3^4+A*R2^3+B*R1^2+C*R0+(1-A6-A7-A6-A5-A-B-C)");
R[i] depends on px,py and r_xy[i][], r_o[i] (positive - "landscape", negative - "portrait"), r_d (positive - along y=x, negative - along y=-x)
R[i] = r0[i]*(1+ (r_od[i][0]*(y[i]**2-x[i]**2)+ 2*r_od[i][1]*x[i]*y[i])/r0[i]**2;
r0[i]=sqrt(x[i]**2+y[2]**2)
x[i]=pixel_x-px0-((i>0)?r_xy[i-1][0]:0)
x[i]=pixel_x-px0-((i>0)?r_xy[i-1][0]:0)
y[i]=pixel_y-py0-((i>0)?r_xy[i-1][1]:0)
*/
*/
// intermediate values
public double phi, theta,psi,cPH,sPH,cTH,sTH,cPS,sPS;
public double [][] rotMatrix=new double[3][3]; // includes mirroring for Y (target coordinates y- down, camera - y up)
......@@ -97,24 +97,25 @@ import Jama.Matrix;
}
}
public LensDistortionParameters(
// LensDistortionParameters lensDistortionParameters,
boolean isTripod,
boolean cartesian,
double pixelSize,
double distortionRadius,
double [][] interParameterDerivatives, //partial derivative matrix from subcamera-camera-goniometer to single camera (12x21) if null - just values, no derivatives
double [] parVect,
boolean [] mask, // calculate only selected derivatives (all parVect values are still
int debugLevel
// boolean calculateDerivatives // calculate this.interParameterDerivatives -derivatives array (false - just this.values)
){
this.debugLevel=debugLevel;
lensCalcInterParamers( // changed name to move calcInterParamers method from enclosing class
this,
isTripod,
cartesian,
pixelSize,
distortionRadius,
interParameterDerivatives, //partial derivative matrix from subcamera-camera-goniometer to single camera (12x21) if null - just values, no derivatives
parVect,
mask // calculate only selected derivatives (all parVect values are still
// boolean calculateDerivatives // calculate this.interParameterDerivatives -derivatives array (false - just this.values)
);
}
......@@ -141,7 +142,7 @@ import Jama.Matrix;
double py0, // center of the lens on the sensor, pixels
boolean flipVertical, // acquired image is mirrored vertically (mirror used)
int lensDistortionModel,
double [][] r_xy,
double [][] r_xy,
double [][] r_od
){
setLensDistortionParameters(
......@@ -166,10 +167,10 @@ import Jama.Matrix;
py0,
flipVertical,
lensDistortionModel,
r_xy,
r_xy,
r_od);
}
public LensDistortionParameters(){
setLensDistortionParameters(
4.5, // focalLength,
......@@ -193,10 +194,11 @@ import Jama.Matrix;
698, // py0,
true, // flipVertical,
-1, // lensDistortionModel
null, // r_xy,
null, // r_xy,
null // r_od,
);
}
@Override
public LensDistortionParameters clone() {
return new LensDistortionParameters(
this.focalLength,
......@@ -247,7 +249,7 @@ import Jama.Matrix;
double py0, // center of the lens on the sensor, pixels
boolean flipVertical, // acquired image is mirrored vertically (mirror used)
int lensDistortionModel,
double [][] r_xy, // per polynomial term center x,y correction only 6, as for the first term delta x, delta y ==0
double [][] r_xy, // per polynomial term center x,y correction only 6, as for the first term delta x, delta y ==0
double [][] r_od // per polynomial term orthogonal+diagonal elongation
){
this.focalLength=focalLength;
......@@ -279,7 +281,7 @@ import Jama.Matrix;
for (int i=0;i<r_od.length;i++)this.r_od[i]=r_od[i].clone();
recalcCommons();
}
public void setIntrincicFromSubcamera(EyesisSubCameraParameters pars){
setLensDistortionParameters(
pars.focalLength,
......@@ -308,7 +310,7 @@ import Jama.Matrix;
pars.r_od // do not exist yet!
);
}
public void setLensDistortionParameters(LensDistortionParameters ldp
){
setLensDistortionParameters(
......@@ -333,20 +335,20 @@ import Jama.Matrix;
ldp.py0,
ldp.flipVertical,
ldp.lensDistortionModel,
ldp.r_xy,
ldp.r_xy,
ldp.r_od);
}
// TODO: Fix for non-radial !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// just for debugging
// TODO: Fix for non-radial !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// just for debugging
public void setLensDistortionParameters(LensDistortionParameters ldp,
int index, // parameter to add delta, 1..13->14->17
double delta
){
/*
/*
this.focalLength=ldp.focalLength+((index==7)?delta:0);
this.pixelSize=ldp.pixelSize;
this.distortionRadius=ldp.distortionRadius;
......@@ -367,12 +369,12 @@ import Jama.Matrix;
this.px0=ldp.px0+((index==16)?delta:0);
this.py0=ldp.py0+((index==17)?delta:0);
this.flipVertical=ldp.flipVertical;
*/
*/
setLensDistortionParameters(ldp);
final int index_r_xy=18;
final int index_r_od=30;
final int index_end=44;
switch (index){
case 1: this.yaw+=delta; break;
case 2: this.pitch+=delta; break; //=ldp.pitch+((index==2)?delta:0);
......@@ -400,8 +402,8 @@ import Jama.Matrix;
}
recalcCommons();
}
// recalculate common (point-invariant) intermediate values (cos, sin, rotation matrix)
// recalculate common (point-invariant) intermediate values (cos, sin, rotation matrix)
public void recalcCommons(){
// this.cummulativeCorrection=false; // just debugging
......@@ -429,16 +431,16 @@ import Jama.Matrix;
Ye = (sPS*cPH-cPS*sTH*sPH)*Xp -cPS*cTH*Yp +(-sPS*sPH-cPS*sTH*cPH)*Zp
Ze = (cTH*sPH)*Xp -sTH*Yp +( cTH*cPH)* Zp + dist
theta==0, psi==0:
Xe = (cPH)*Xp
theta==0, psi==0:
Xe = (cPH)*Xp
Ye = Yp
Ze = cPH* Zp + dist
(4) PXmmc =f/(cPH* Zp + dist)* (cPH)*Xp // mm, left from the lens axis intersection with the sensor
dPXmmc/dphi=
*/
this.rotMatrix[0][0]= cPS*cPH+sPS*sTH*sPH;
this.rotMatrix[0][1]= sPS*cTH;
......@@ -476,7 +478,7 @@ dPXmmc/dphi=
}
}
}
private String [][] descriptions=
{
{"distance", "Distance from the intersection of the lens axis with z=0 target plane to the camera lens entrance pupil", "mm", "e"},
......@@ -502,7 +504,7 @@ dPXmmc/dphi=
{"eccen_B_y", "Distortion center shift Y for r^3", "rel","i"},
{"elong_B_o", "Orthogonal elongation for r^3", "rel","i"},
{"elong_B_d", "Diagonal elongation for r^3", "rel","i"},
{"eccen_A_x", "Distortion center shift X for r^4", "rel","i"},
{"eccen_A_y", "Distortion center shift Y for r^4", "rel","i"},
{"elong_A_o", "Orthogonal elongation for r^4", "rel","i"},
......@@ -615,7 +617,7 @@ dPXmmc/dphi=
public void setAllVector(double [] vector){
if (vector.length!=(getExtrinsicVector().length+getIntrinsicVector().length)){
String msg="Parameter vector should have exactly"+(getExtrinsicVector().length+getIntrinsicVector().length)+" elements";
IJ.showMessage("Error",msg);
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
this.distance= vector[ 0];
......@@ -655,7 +657,7 @@ dPXmmc/dphi=
*/
recalcCommons();
}
public String [] getExtrinsicNames() {return getDescriptionStrings("e", 0);}
public String [] getExtrinsicDescriptions(){return getDescriptionStrings("e", 1);}
public String [] getExtrinsicUnits() {return getDescriptionStrings("e", 2);}
......@@ -673,8 +675,8 @@ dPXmmc/dphi=
for (int i=0;i<this.descriptions.length;i++) if (type.indexOf(descriptions[i][3].charAt(0))>=0) s[num++]=this.descriptions[i][var];
return s;
}
/*
* Calculate pixel value of projection from the pattern point [xp,yp,zp] using current distortion/position parameters
(1) Xe = (cPS*cPH+sPS*sTH*sPH)*(Xp-X0) +sPS*cTH*(Yp-Y0) +(-cPS*sPH+sPS*sTH*cPH)*(Zp-Z0)
......@@ -692,7 +694,7 @@ dPXmmc/dphi=
(10) PX = 1000/Psz*( xDist) + PX0 // horizontal pixel of the image (positive - right)
(11) PY = 1000/Psz*(-yDist) + PY0 // vertical pixel of the image (positive - down)
*/
public double [] patternToPixels(
double xp, // target point horizontal, positive - right, mm
......@@ -780,14 +782,14 @@ dPXmmc/dphi=
}
/*
* result = {{srcDerivatives[4][0],srcDerivatives[4][1]}, - X0
* {srcDerivatives[5][0],srcDerivatives[5][1]} - Y0
* {srcDerivatives[8][0],srcDerivatives[8][1]} - dist
* ...
* {srcDerivatives[5][0],srcDerivatives[5][1]} - Y0
* {srcDerivatives[8][0],srcDerivatives[8][1]} - dist
* ...
*/
/**
* Reorder to match the sequence of names - seems to be different :-(
* Reorder to match the sequence of names - seems to be different :-(
* @param srcDerivatives values and 15 derivatives for px, py
* @return
*/
......@@ -811,27 +813,27 @@ dPXmmc/dphi=
15, // 15 public double distortionC=0.0; // r^2
18, // 16 Orthogonal elongation for r^2"
19, // 17 Diagonal elongation for r^2"
20, // 18 Distortion center shift X for r^3"
21, // 19 Distortion center shift Y for r^3"
22, // 20 Orthogonal elongation for r^3"
23, // 21 Diagonal elongation for r^3"
24, // 22 Distortion center shift X for r^4"
25, // 23 Distortion center shift Y for r^4"
26, // 24 Orthogonal elongation for r^4"
27, // 25 Diagonal elongation for r^4"
28, // 26 Distortion center shift X for r^5"
29, // 27 Distortion center shift Y for r^5"
30, // 28 Orthogonal elongation for r^5"
31, // 29 Diagonal elongation for r^5"
32, // 30 Distortion center shift X for r^6"
33, // 31 Distortion center shift Y for r^6"
34, // 32 Orthogonal elongation for r^6"
35, // 33 Diagonal elongation for r^6"
36, // 34 Distortion center shift X for r^7"
37, // 35 Distortion center shift Y for r^7"
38, // 36 Orthogonal elongation for r^6"
......@@ -841,7 +843,7 @@ dPXmmc/dphi=
41, // 29 Distortion center shift Y for r^8"
42, // 40 Orthogonal elongation for r^8"
43 // 41 Diagonal elongation for r^8"
};
double [][] result = new double [order.length][2];
for (int i=0; i<order.length;i++){
......@@ -859,21 +861,21 @@ dPXmmc/dphi=
this.x0-this.distance*this.rotMatrix[2][0],
-this.y0-this.distance*this.rotMatrix[2][1], // this.y0 - up?
this.z0-this.distance*this.rotMatrix[2][2]};
/*
/*
Matrix MR=new Matrix(this.rotMatrix);
Matrix MRT=MR.transpose();
Matrix E=MR.times(MRT);
System.out.println("===MR=="); MR.print(8, 5);System.out.println("");
System.out.println("===MRT=="); MRT.print(8, 5);System.out.println("");
System.out.println("===E==="); E.print(8, 5);System.out.println("");
System.out.println("x0="+IJ.d2s(this.x0,1)+" y0="+IJ.d2s(this.y0,1)+" z0="+IJ.d2s(this.z0,1)+" this.distance="+IJ.d2s(this.distance,1));
System.out.println("phi="+IJ.d2s(this.phi,4)+" theta="+IJ.d2s(this.theta,4)+" psi="+IJ.d2s(this.psi,4));
System.out.println("|"+IJ.d2s(this.rotMatrix[0][0],4)+" "+IJ.d2s(this.rotMatrix[0][1],4)+" "+IJ.d2s(this.rotMatrix[0][2],4)+"|");
System.out.println("|"+IJ.d2s(this.rotMatrix[1][0],4)+" "+IJ.d2s(this.rotMatrix[1][1],4)+" "+IJ.d2s(this.rotMatrix[1][2],4)+"|");
System.out.println("|"+IJ.d2s(this.rotMatrix[2][0],4)+" "+IJ.d2s(this.rotMatrix[2][1],4)+" "+IJ.d2s(this.rotMatrix[2][2],4)+"|");
*/
*/
return p;
}
......@@ -951,12 +953,12 @@ dPXmmc/dphi=
boolean calculateAll){ // calculate derivatives, false - values only
double maxRelativeRadius=2.0;
return calcPartialDerivatives(xp,yp,zp,maxRelativeRadius,calculateAll);
}
}
public double [][] calcPartialDerivatives(
double xp, // target point horizontal, positive - right, mm
double yp, // target point vertical, positive - down, mm
double zp, // target point horizontal, positive - away from camera, mm
double maxRelativeRadius, // make configurable?
double maxRelativeRadius, // make configurable?
boolean calculateAll){ // calculate derivatives, false - values only
switch (this.lensDistortionModelType){
case 0:
......@@ -968,8 +970,8 @@ dPXmmc/dphi=
return calcPartialDerivatives_type1(xp,yp,zp,maxRelativeRadius,calculateAll);
}
}
public double [][] calcPartialDerivatives_type1(
double xp, // target point horizontal, positive - right, mm
double yp, // target point vertical, positive - down, mm
......@@ -977,7 +979,7 @@ dPXmmc/dphi=
double maxRelativeRadius,
boolean calculateAll){ // calculate derivatives, false - values only
// this.cummulativeCorrection=false; // just debugging
// TODO - add reduced calculations for less terms?
// final int numDerivatives=44; // 18+6*2+7*2; // 18 for radial and 26 more for non-radial
final int numRadialDerivatives=18;
......@@ -995,7 +997,7 @@ dPXmmc/dphi=
double [] PXYmmc={this.focalLength/XeYeZe[2]*XeYeZe[0],this.focalLength/XeYeZe[2]*XeYeZe[1]};
// now each term has individual radius
// double [] rr=new double [r_xyod.length];
// Geometric - get to pinhole coordinates on the sensor
// Geometric - get to pinhole coordinates on the sensor
double [][] dXeYeZe=null; //[14];
double [][] dPXYmmc=null;
......@@ -1007,23 +1009,23 @@ dPXmmc/dphi=
R[i] depends on px,py and r_xy[i][], r_o[i] (positive - "landscape", negative - "portrait"), r_d (positive - along y=x, negative - along y=-x)
R[i] = r0[i]*(1+ (r_od[i][0]*(y[i]**2-x[i]**2)+ 2*r_od[i][1]*x[i]*y[i])/r0[i]**2;
r0[i]=sqrt(x[i]**2+y[2]**2)
x[i]=pixel_x-px0-((i>0)?r_xy[i-1][0]:0)
x[i]=pixel_x-px0-((i>0)?r_xy[i-1][0]:0)
y[i]=pixel_y-py0-((i>0)?r_xy[i-1][1]:0)
*/
*/
double [] a={this.distortionC,this.distortionB,this.distortionA,this.distortionA5,this.distortionA6,this.distortionA7,this.distortionA8};
double deltaX=0.0,deltaY=0.0; // difference between distorted and non-distorted as a fraction of this.distortionRadius
double xmmc=PXYmmc[0]/this.distortionRadius;
double ymmc=PXYmmc[1]/this.distortionRadius;
double dDeltaX_dxmmc=0.0, dDeltaX_dymmc=0.0, dDeltaY_dxmmc=0.0, dDeltaY_dymmc=0;
double dDeltaX_dxmmc=0.0, dDeltaX_dymmc=0.0, dDeltaY_dxmmc=0.0, dDeltaY_dymmc=0;
if (calculateAll){
for (double [] r:partDeriv) Arrays.fill(r, 0.0); // will fill the [0] (value) too, should be done before calculation of these 2 values
// Geometric - get to pinhole coordinates on the sensor
// Geometric - get to pinhole coordinates on the sensor
dXeYeZe=new double[9][3]; //[14];
// Geometric - get to pinhole coordinates on the sensor
// Geometric - get to pinhole coordinates on the sensor
dXeYeZe[0][0]=XeYeZe[0];
dXeYeZe[0][1]=XeYeZe[1];
dXeYeZe[0][2]=XeYeZe[2];
// /dphi
// /dphi
dXeYeZe[1][0]=(-cPS*sPH + sPS*sTH*cPH)*XYZ[0] +(-cPS*cPH-sPS*sTH*sPH)*XYZ[2];
dXeYeZe[1][1]=(-sPS*sPH-cPS*sTH*cPH) *XYZ[0] +(-sPS*cPH+cPS*sTH*sPH)*XYZ[2];
dXeYeZe[1][2]=(cTH*cPH)*XYZ[0] -cTH*sPH* XYZ[2];
......@@ -1031,7 +1033,7 @@ dPXmmc/dphi=
dXeYeZe[2][0]=(sPS*cTH*sPH)*XYZ[0] -sPS*sTH*XYZ[1] +(sPS*cTH*cPH)*XYZ[2];
dXeYeZe[2][1]=(-cPS*cTH*sPH)*XYZ[0] +cPS*sTH*XYZ[1] +(-cPS*cTH*cPH)*XYZ[2];
dXeYeZe[2][2]=(-sTH*sPH)*XYZ[0] -cTH*XYZ[1] -sTH*cPH* XYZ[2];
// /dpsi
// /dpsi
dXeYeZe[3][0]=(-sPS*cPH+cPS*sTH*sPH)*XYZ[0] +cPS*cTH*XYZ[1] +(sPS*sPH+cPS*sTH*cPH)*XYZ[2];
dXeYeZe[3][1]=(cPS*cPH+ sPS*sTH*sPH)*XYZ[0] +sPS*cTH*XYZ[1] +(-cPS*sPH+sPS*sTH*cPH)*XYZ[2];
dXeYeZe[3][2]=0.0;
......@@ -1060,15 +1062,15 @@ dPXmmc/dphi=
dXeYeZe[8][0]=0.0;
dXeYeZe[8][1]=0.0;
dXeYeZe[8][2]=1.0;
dPXYmmc=new double[9][2]; //[14];
// TODO: move up
// TODO: move up
// double [][] dPXYmmc=new double[9][2]; //[14];
dPXYmmc[0][0]=PXYmmc[0]; // is it needed? probably not used
dPXYmmc[0][1]=PXYmmc[1];
//(4) PXmmc =f/Ze* Xe // mm, left from the lens axis intersection with the sensor
//dPXmmc/dphi = f/Ze * dXe/dphi - f*Xe/Ze^2 * dZe/dphi
dPXYmmc[1][0]=this.focalLength/dXeYeZe[0][2]*(dXeYeZe[1][0]-dXeYeZe[0][0]/dXeYeZe[0][2]*dXeYeZe[1][2]);
//dPXmmc/dtheta = f/Ze * dXe/dtheta - f*Xe/Ze^2 * dZe/dtheta
......@@ -1103,14 +1105,14 @@ dPXmmc/dphi=
dPXYmmc[7][1]=dXeYeZe[0][1]/dXeYeZe[0][2];
//dPYmmc/ddist = - f*Ye/Ze^2
dPXYmmc[8][1]=-this.focalLength*dXeYeZe[0][1]/(dXeYeZe[0][2]*dXeYeZe[0][2]);
}
// conversion coefficient from relative (to distortionRadius) to pixels
// negate for y!
double rel_to_pix=this.distortionRadius*1000.0/this.pixelSize;
//TODO: seems that rr[i] can be just a single running variable, not an array
for (int i=0;i<r_xyod.length;i++){
double x=xmmc-r_xyod[i][0]; // relative X-shift of this term center
double y=ymmc-r_xyod[i][1]; // relative X-shift of this term center
double x2=x*x; // relative squared X-shift from this term center
......@@ -1134,19 +1136,19 @@ dPXmmc/dphi=
// double dx2_dxmmc=2*x, dy2_dymmc=2*y, dr2_dxmmc=2*x, dr2_dymmc=2*y;
// double drr_dxmmc=0.5/rr*(dr2_dxmmc+ r_xyod[i][2]*(-dx2_dxmmc)+2*r_xyod[i][3]*y)=0.5/rr*(2*x - 2*x*r_xyod[i][2]+2*r_xyod[i][3]*y)=
// = (x*(1.0-r_xyod[i][2])+y*r_xyod[i][3])/rr
// = (x*(1.0-r_xyod[i][2])+y*r_xyod[i][3])/rr
// double drr_dymmc= (y*(1.0+r_xyod[i][2])+x*r_xyod[i][3])/rr
// double ki=a[i]*(rr^(i+1)-1.0);
// double dki_dxmmc=a[i]*(i+1)*rr^i*(x*(1.0-r_xyod[i][2])+y*r_xyod[i][3])/rr
// double dki_dymmc=a[i]*(i+1)*rr^i*(y*(1.0+r_xyod[i][2])+x*r_xyod[i][3])/rr
// double dki_dxmmc=a[i]*(i+1)*rr^i*(x*(1.0-r_xyod[i][2])+y*r_xyod[i][3])/rr
// double dki_dymmc=a[i]*(i+1)*rr^i*(y*(1.0+r_xyod[i][2])+x*r_xyod[i][3])/rr
// double dki_dxmmc=a[i]*(i+1)*rr_pow_i*(x*(1.0-r_xyod[i][2])+y*r_xyod[i][3])/rr
// double dki_dymmc=a[i]*(i+1)*rr_pow_i*(y*(1.0+r_xyod[i][2])+x*r_xyod[i][3])/rr
double ai_iplus1_rr_pow_i= a[i]*(i+1)*rr_pow_i;
double ai_iplus1_rr_pow_i= a[i]*(i+1)*rr_pow_i;
double dki_dxmmc= ai_iplus1_rr_pow_i*(x*(1.0-r_xyod[i][2])+y*r_xyod[i][3])/rr;
double dki_dymmc= ai_iplus1_rr_pow_i*(y*(1.0+r_xyod[i][2])+x*r_xyod[i][3])/rr;
// the following 4 shifts are "extra", on top of non-distorted (pinhole) - pinhole should be added to the per-term sum
double dDeltaXi_dxmmc = ki+x*dki_dxmmc; // here dDelta*_d*mmc are relative (both I/O are fractions of distortionRadius)
double dDeltaXi_dymmc = x*dki_dymmc;
......@@ -1168,7 +1170,7 @@ dPXmmc/dphi=
partDeriv[index+1][0]= -rel_to_pix* dDeltaXi_dymmc; // dPx_dr_xyod1
partDeriv[index+1][1]= rel_to_pix*(dDeltaYi_dymmc-0.0); // dPy_dr_xyod1
}
// d/dai
// ki=a[i]*(rr_pow_i*rr-1.0);
// double dki_dai=(rr_pow_i*rr-1.0);
......@@ -1178,7 +1180,7 @@ dPXmmc/dphi=
index= distortionCIndex-i; // reverse order, // a8->9, a7->10, a6->11, a5->12, a->13, b->14, c->15
partDeriv[index][0]= rel_to_pix*x*(rr_pow_i*rr-1.0); // OK
partDeriv[index][1]=-rel_to_pix*y*(rr_pow_i*rr-1.0); // OK
// d/dr_xyod[0] (x shift of the center
// rr=Math.sqrt(r2+ r_xyod[i][2]*(y2-x2)+ 2.0*r_xyod[i][3]*x*y );
// ki=a[i]*(rr_pow_i*rr-1.0);
......@@ -1212,7 +1214,7 @@ dPXmmc/dphi=
// dki_dri=a[i]*(i+1)*rr^i = a[i]*(i+1)*rr_pow_i
// dDeltaX_dri=x*a[i]*(i+1)*rr_pow_i
// dDeltaY_dri=y*a[i]*(i+1)*rr_pow_i
// dPx_dri= rel_to_pix*x*a[i]*(i+1)*rr_pow_i = csi*x
// dPx_dri= rel_to_pix*x*a[i]*(i+1)*rr_pow_i = csi*x
// dPy_dri=-rel_to_pix*y*a[i]*(i+1)*rr_pow_i = -csi*y
// dPx_dr_xyod0= dPx_dri*dri_dr_xyod0= csi*x*dri_dr_xyod0;
// dPx_dr_xyod1= dPx_dri*dri_dr_xyod1= csi*x*dri_dr_xyod1;
......@@ -1235,15 +1237,15 @@ dPXmmc/dphi=
partDeriv[index+2][1]=-csi*y*dri_dr_xyod2; // dPy_dr_xyod2
partDeriv[index+3][0]= csi*x*dri_dr_xyod3; // dPx_dr_xyod3
partDeriv[index+3][1]=-csi*y*dri_dr_xyod3; // dPy_dr_xyod3
}
}
}
double [] xyDist={PXYmmc[0]+this.distortionRadius*deltaX,PXYmmc[1]+this.distortionRadius*deltaY};
// convert to sensor pixels coordinates
partDeriv[0][0]= 1000.0/this.pixelSize*xyDist[0] + this.px0;
partDeriv[0][1]= -1000.0/this.pixelSize*xyDist[1] + this.py0;
if (!calculateAll) { // TODO: how to deal with it when calculating Jacobian???
// TODO: Looking away from the target, trying only with no dervatives. Do the same for derivatives too?
if ((XeYeZe[2]<0.0) || ((xmmc*xmmc+ymmc*ymmc)>maxRelativeRadius*maxRelativeRadius)){ // non-distorted too far from the axis
......@@ -1261,16 +1263,16 @@ dPXmmc/dphi=
partDeriv[index ][1]+=partDeriv[index+4][1];
partDeriv[index+1][0]+=partDeriv[index+5][0];
partDeriv[index+1][1]+=partDeriv[index+5][1];
}
}
partDeriv[index+2][0]+=partDeriv[index+6][0];
partDeriv[index+2][1]+=partDeriv[index+6][1];
partDeriv[index+3][0]+=partDeriv[index+7][0];
partDeriv[index+3][1]+=partDeriv[index+7][1];
}
}
// convert dDelta*_d*mmc from relative/relative to pix/mm (invert pixel Y direction)
// added 1.0 to account for non-distorted (pinhole) shift
// added 1.0 to account for non-distorted (pinhole) shift
double dPx_dPinholeX= (1.0+dDeltaX_dxmmc)*1000.0/this.pixelSize;
double dPx_dPinholeY= dDeltaX_dymmc*1000.0/this.pixelSize;
double dPy_dPinholeX= -dDeltaY_dxmmc*1000.0/this.pixelSize;
......@@ -1281,12 +1283,12 @@ dPXmmc/dphi=
System.out.println(" dDeltaX_dxmmc="+dDeltaX_dxmmc+" dDeltaX_dymmc="+dDeltaX_dymmc+" dDeltaY_dxmmc="+dDeltaY_dxmmc+" dDeltaY_dymmc"+dDeltaY_dymmc);
System.out.println(" dPx_dPinholeX="+dPx_dPinholeX+" dPx_dPinholeY="+dPx_dPinholeY+" dPy_dPinholeX="+dPy_dPinholeX+" dPy_dPinholeY"+dPy_dPinholeY);
}
double K=Math.PI/180; // multiply all derivatives my angles
double K=Math.PI/180; // multiply all derivatives my angles
// dPX/dphi = 1000/Psz* dxDist/dphi
partDeriv[ 1][0]= K*(dPx_dPinholeX*dPXYmmc[1][0]+dPx_dPinholeY*dPXYmmc[1][1]);
partDeriv[ 1][1]= K*(dPy_dPinholeX*dPXYmmc[1][0]+dPy_dPinholeY*dPXYmmc[1][1]);
// dPX/dtheta = 1000/Psz* dxDist/dtheta
partDeriv[ 2][0]= K*(dPx_dPinholeX*dPXYmmc[2][0]+dPx_dPinholeY*dPXYmmc[2][1]);
partDeriv[ 2][1]= K*(dPy_dPinholeX*dPXYmmc[2][0]+dPy_dPinholeY*dPXYmmc[2][1]);
......@@ -1308,7 +1310,7 @@ dPXmmc/dphi=
// dPX/ddist = 1000/Psz* dxDist/ddist
partDeriv[ 8][0]= dPx_dPinholeX*dPXYmmc[8][0]+dPx_dPinholeY*dPXYmmc[8][1];
partDeriv[ 8][1]= dPy_dPinholeX*dPXYmmc[8][0]+dPy_dPinholeY*dPXYmmc[8][1];
// dPX/dPX0 = 1
// dPY/dPX0 = 0
partDeriv[16][0]= 1.0;
......@@ -1319,7 +1321,7 @@ dPXmmc/dphi=
partDeriv[17][1]= 1.0;
return partDeriv;
}
public double [][] calcPartialDerivatives_type2(
double xp, // target point horizontal, positive - right, mm
double yp, // target point vertical, positive - down, mm
......@@ -1327,7 +1329,7 @@ dPXmmc/dphi=
double maxRelativeRadius,
boolean calculateAll){ // calculate derivatives, false - values only
// this.cummulativeCorrection=false; // just debugging
// TODO - add reduced calculations for less terms?
// final int numDerivatives=44; // 18+6*2+7*2; // 18 for radial and 26 more for non-radial
final int numRadialDerivatives=18;
......@@ -1345,7 +1347,7 @@ dPXmmc/dphi=
double [] PXYmmc={this.focalLength/XeYeZe[2]*XeYeZe[0],this.focalLength/XeYeZe[2]*XeYeZe[1]};
// now each term has individual radius
// double [] rr=new double [r_xyod.length];
// Geometric - get to pinhole coordinates on the sensor
// Geometric - get to pinhole coordinates on the sensor
double [][] dXeYeZe=null; //[14];
double [][] dPXYmmc=null;
......@@ -1357,23 +1359,23 @@ dPXmmc/dphi=
R[i] depends on px,py and r_xy[i][], r_o[i] (positive - "landscape", negative - "portrait"), r_d (positive - along y=x, negative - along y=-x)
R[i] = r0[i]*(1+ (r_od[i][0]*(y[i]**2-x[i]**2)+ 2*r_od[i][1]*x[i]*y[i])/r0[i]**2;
r0[i]=sqrt(x[i]**2+y[2]**2)
x[i]=pixel_x-px0-((i>0)?r_xy[i-1][0]:0)
x[i]=pixel_x-px0-((i>0)?r_xy[i-1][0]:0)
y[i]=pixel_y-py0-((i>0)?r_xy[i-1][1]:0)
*/
*/
double [] a={this.distortionC,this.distortionB,this.distortionA,this.distortionA5,this.distortionA6,this.distortionA7,this.distortionA8};
double deltaX=0.0,deltaY=0.0; // difference between distorted and non-distorted as a fraction of this.distortionRadius
double x=PXYmmc[0]/this.distortionRadius; // was xmmc
double y=PXYmmc[1]/this.distortionRadius; // was ymmc
double dDeltaX_dx=0.0, dDeltaX_dy=0.0, dDeltaY_dx=0.0, dDeltaY_dy=0;
double dDeltaX_dx=0.0, dDeltaX_dy=0.0, dDeltaY_dx=0.0, dDeltaY_dy=0;
if (calculateAll){
for (double [] r:partDeriv) Arrays.fill(r, 0.0); // will fill the [0] (value) too, should be done before calculation of these 2 values
// Geometric - get to pinhole coordinates on the sensor
// Geometric - get to pinhole coordinates on the sensor
dXeYeZe=new double[9][3]; //[14];
// Geometric - get to pinhole coordinates on the sensor
// Geometric - get to pinhole coordinates on the sensor
dXeYeZe[0][0]=XeYeZe[0];
dXeYeZe[0][1]=XeYeZe[1];
dXeYeZe[0][2]=XeYeZe[2];
// /dphi
// /dphi
dXeYeZe[1][0]=(-cPS*sPH + sPS*sTH*cPH)*XYZ[0] +(-cPS*cPH-sPS*sTH*sPH)*XYZ[2];
dXeYeZe[1][1]=(-sPS*sPH-cPS*sTH*cPH) *XYZ[0] +(-sPS*cPH+cPS*sTH*sPH)*XYZ[2];
dXeYeZe[1][2]=(cTH*cPH)*XYZ[0] -cTH*sPH* XYZ[2];
......@@ -1381,7 +1383,7 @@ dPXmmc/dphi=
dXeYeZe[2][0]=(sPS*cTH*sPH)*XYZ[0] -sPS*sTH*XYZ[1] +(sPS*cTH*cPH)*XYZ[2];
dXeYeZe[2][1]=(-cPS*cTH*sPH)*XYZ[0] +cPS*sTH*XYZ[1] +(-cPS*cTH*cPH)*XYZ[2];
dXeYeZe[2][2]=(-sTH*sPH)*XYZ[0] -cTH*XYZ[1] -sTH*cPH* XYZ[2];
// /dpsi
// /dpsi
dXeYeZe[3][0]=(-sPS*cPH+cPS*sTH*sPH)*XYZ[0] +cPS*cTH*XYZ[1] +(sPS*sPH+cPS*sTH*cPH)*XYZ[2];
dXeYeZe[3][1]=(cPS*cPH+ sPS*sTH*sPH)*XYZ[0] +sPS*cTH*XYZ[1] +(-cPS*sPH+sPS*sTH*cPH)*XYZ[2];
dXeYeZe[3][2]=0.0;
......@@ -1410,15 +1412,15 @@ dPXmmc/dphi=
dXeYeZe[8][0]=0.0;
dXeYeZe[8][1]=0.0;
dXeYeZe[8][2]=1.0;
dPXYmmc=new double[9][2]; //[14];
// TODO: move up
// TODO: move up
// double [][] dPXYmmc=new double[9][2]; //[14];
dPXYmmc[0][0]=PXYmmc[0]; // is it needed? probably not used
dPXYmmc[0][1]=PXYmmc[1];
//(4) PXmmc =f/Ze* Xe // mm, left from the lens axis intersection with the sensor
//dPXmmc/dphi = f/Ze * dXe/dphi - f*Xe/Ze^2 * dZe/dphi
dPXYmmc[1][0]=this.focalLength/dXeYeZe[0][2]*(dXeYeZe[1][0]-dXeYeZe[0][0]/dXeYeZe[0][2]*dXeYeZe[1][2]);
//dPXmmc/dtheta = f/Ze * dXe/dtheta - f*Xe/Ze^2 * dZe/dtheta
......@@ -1453,7 +1455,7 @@ dPXmmc/dphi=
dPXYmmc[7][1]=dXeYeZe[0][1]/dXeYeZe[0][2];
//dPYmmc/ddist = - f*Ye/Ze^2
dPXYmmc[8][1]=-this.focalLength*dXeYeZe[0][1]/(dXeYeZe[0][2]*dXeYeZe[0][2]);
}
// conversion coefficient from relative (to distortionRadius) to pixels
// negate for y!
......@@ -1509,14 +1511,14 @@ dPXmmc/dphi=
double ai_iplus1_rr_pow_i_minus_1= a[i]*(i+1)*rr_pow_i_minus_1;
double rr_pow_i_minus_2=rr_pow_i_minus_1/rr;
// double ki1_div_r_mul_i=i*ki1/rr;
double ki1_r_pow_im2_mul_i=i*ki1*rr_pow_i_minus_2; // (axi*x+ayi*y)*i*rr^(i-2)
double ki1_r_pow_im2_mul_i=i*ki1*rr_pow_i_minus_2; // (axi*x+ayi*y)*i*rr^(i-2)
// double ki2_div_r3_mul_im1=(i-1)*ki2/(rr*rr*rr);
double ki2_r_pow_im3_mul_im1=(i-1)*ki2*rr_pow_i_minus_2/rr; // (aoi*(y^2-x^2)+2*adi*x*y)* (i-1)*r^(i-3)
// double dki_dx= x*(ai_iplus1_rr_pow_i_minus_1 +
// r_xyod[i][0]*rr_pow_i_minus_1 + ki1_div_r_mul_i+ki2_div_r3_mul_im1)+
// 2*(r_xyod[i][3]*y - r_xyod[i][2]*x)/rr_pow_i_minus_1;
double dki_dx= x*(ai_iplus1_rr_pow_i_minus_1 +
ki1_r_pow_im2_mul_i + ki2_r_pow_im3_mul_im1)+ // r_xyod[i][0]*rr_pow_i_minus_1 +
ki1_r_pow_im2_mul_i + ki2_r_pow_im3_mul_im1)+ // r_xyod[i][0]*rr_pow_i_minus_1 +
r_xyod[i][0]*rr_pow_i + 2*(r_xyod[i][3]*y - r_xyod[i][2]*x)*rr_pow_i_minus_1;
// double dki_dy= y*(ai_iplus1_rr_pow_i_minus_1 +
// r_xyod[i][1]*rr_pow_i_minus_1 + ki1_div_r_mul_i + ki2_div_r3_mul_im1)+
......@@ -1524,7 +1526,7 @@ dPXmmc/dphi=
double dki_dy= y*(ai_iplus1_rr_pow_i_minus_1 +
ki1_r_pow_im2_mul_i + ki2_r_pow_im3_mul_im1)+ // r_xyod[i][1]*rr_pow_i_minus_1 +
r_xyod[i][1]*rr_pow_i + 2*(r_xyod[i][3]*x + r_xyod[i][2]*y)*rr_pow_i_minus_1;
// double ai_iplus1_rr_pow_i= a[i]*(i+1)*rr_pow_i;
// double ai_iplus1_rr_pow_i= a[i]*(i+1)*rr_pow_i;
// double dki_dxmmc= ai_iplus1_rr_pow_i*(x*(1.0-r_xyod[i][2])+y*r_xyod[i][3])/rr;
// double dki_dymmc= ai_iplus1_rr_pow_i*(y*(1.0+r_xyod[i][2])+x*r_xyod[i][3])/rr;
// the following 4 shifts are "extra", on top of non-distorted (pinhole) - pinhole should be added to the per-term sum
......@@ -1536,7 +1538,7 @@ dPXmmc/dphi=
dDeltaX_dy += dDeltaXi_dy;
dDeltaY_dx += dDeltaYi_dx;
dDeltaY_dy += dDeltaYi_dy;
//dpx_dai, dpi_dai - same as before
//dpx_dai, dpi_dai - same as before
int index= distortionCIndex-i; // reverse order, // a8->9, a7->10, a6->11, a5->12, a->13, b->14, c->15
partDeriv[index][0]= rel_to_pix*x*(rr_pow_i_plus_1-1.0); // OK
partDeriv[index][1]=-rel_to_pix*y*(rr_pow_i_plus_1-1.0); // OK
......@@ -1560,20 +1562,20 @@ dPXmmc/dphi=
// dpy_daDi=-2*y*xy*r^(i-1);
double rel_to_pix_mul_y2_minus_x2_mul_rr_pow_i_minus_1=rel_to_pix* (y2-x2)*rr_pow_i_minus_1;
double rel_to_pix_mul_2xy_mul_rr_pow_i_minus_1=rel_to_pix*2.0*xy*rr_pow_i_minus_1;
index=numRadialDerivatives-2+4*i;
partDeriv[index+2][0]= x*rel_to_pix_mul_y2_minus_x2_mul_rr_pow_i_minus_1;
partDeriv[index+2][1]=-y*rel_to_pix_mul_y2_minus_x2_mul_rr_pow_i_minus_1;
partDeriv[index+3][0]= x*rel_to_pix_mul_2xy_mul_rr_pow_i_minus_1;
partDeriv[index+3][1]=-y*rel_to_pix_mul_2xy_mul_rr_pow_i_minus_1;
}
}
}
double [] xyDist={PXYmmc[0]+this.distortionRadius*deltaX,PXYmmc[1]+this.distortionRadius*deltaY};
// convert to sensor pixels coordinates
partDeriv[0][0]= 1000.0/this.pixelSize*xyDist[0] + this.px0;
partDeriv[0][1]= -1000.0/this.pixelSize*xyDist[1] + this.py0;
if (!calculateAll) { // TODO: how to deal with it when calculating Jacobian???
// TODO: Looking away from the target, trying only with no dervatives. Do the same for derivatives too?
if ((XeYeZe[2]<0.0) || (r2>maxRelativeRadius*maxRelativeRadius)){ // non-distorted too far from the axis
......@@ -1591,16 +1593,16 @@ dPXmmc/dphi=
partDeriv[index ][1]+=partDeriv[index+4][1];
partDeriv[index+1][0]+=partDeriv[index+5][0];
partDeriv[index+1][1]+=partDeriv[index+5][1];
}
}
partDeriv[index+2][0]+=partDeriv[index+6][0];
partDeriv[index+2][1]+=partDeriv[index+6][1];
partDeriv[index+3][0]+=partDeriv[index+7][0];
partDeriv[index+3][1]+=partDeriv[index+7][1];
}
}
// convert dDelta*_d* from relative/relative to pix/mm (invert pixel Y direction)
// added 1.0 to account for non-distorted (pinhole) shift
// added 1.0 to account for non-distorted (pinhole) shift
double dPx_dPinholeX= (1.0+dDeltaX_dx)*1000.0/this.pixelSize;
double dPx_dPinholeY= dDeltaX_dy*1000.0/this.pixelSize;
double dPy_dPinholeX= -dDeltaY_dx*1000.0/this.pixelSize;
......@@ -1611,12 +1613,12 @@ dPXmmc/dphi=
System.out.println(" dDeltaX_dxmmc="+dDeltaX_dx+" dDeltaX_dymmc="+dDeltaX_dy+" dDeltaY_dxmmc="+dDeltaY_dx+" dDeltaY_dymmc"+dDeltaY_dy);
System.out.println(" dPx_dPinholeX="+dPx_dPinholeX+" dPx_dPinholeY="+dPx_dPinholeY+" dPy_dPinholeX="+dPy_dPinholeX+" dPy_dPinholeY"+dPy_dPinholeY);
}
double K=Math.PI/180; // multiply all derivatives my angles
double K=Math.PI/180; // multiply all derivatives my angles
// dPX/dphi = 1000/Psz* dxDist/dphi
partDeriv[ 1][0]= K*(dPx_dPinholeX*dPXYmmc[1][0]+dPx_dPinholeY*dPXYmmc[1][1]);
partDeriv[ 1][1]= K*(dPy_dPinholeX*dPXYmmc[1][0]+dPy_dPinholeY*dPXYmmc[1][1]);
// dPX/dtheta = 1000/Psz* dxDist/dtheta
partDeriv[ 2][0]= K*(dPx_dPinholeX*dPXYmmc[2][0]+dPx_dPinholeY*dPXYmmc[2][1]);
partDeriv[ 2][1]= K*(dPy_dPinholeX*dPXYmmc[2][0]+dPy_dPinholeY*dPXYmmc[2][1]);
......@@ -1638,7 +1640,7 @@ dPXmmc/dphi=
// dPX/ddist = 1000/Psz* dxDist/ddist
partDeriv[ 8][0]= dPx_dPinholeX*dPXYmmc[8][0]+dPx_dPinholeY*dPXYmmc[8][1];
partDeriv[ 8][1]= dPy_dPinholeX*dPXYmmc[8][0]+dPy_dPinholeY*dPXYmmc[8][1];
// dPX/dPX0 = 1
// dPY/dPX0 = 0
partDeriv[16][0]= 1.0;
......@@ -1649,9 +1651,9 @@ dPXmmc/dphi=
partDeriv[17][1]= 1.0;
return partDeriv;
}
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"focalLength",this.focalLength+"");
properties.setProperty(prefix+"pixelSize",this.pixelSize+"");
......@@ -1730,7 +1732,7 @@ dPXmmc/dphi=
this.py0=Double.parseDouble(properties.getProperty(prefix+"py0"));
if (properties.getProperty(prefix+"flipVertical")!=null)
this.flipVertical=Boolean.parseBoolean(properties.getProperty(prefix+"flipVertical"));
setDefaultNonRadial();
for (int i=0;i<this.r_xy.length;i++){
if (properties.getProperty(prefix+"r_xy_"+i+"_x")!=null) this.r_xy[i][0]=Double.parseDouble(properties.getProperty(prefix+"r_xy_"+i+"_x"));
......@@ -1817,11 +1819,11 @@ dPXmmc/dphi=
this.x0= gd.getNextNumber();
this.y0= gd.getNextNumber();
this.z0= gd.getNextNumber();
this.distance= gd.getNextNumber();
this.distance= gd.getNextNumber();
this.px0= gd.getNextNumber();
this.py0= gd.getNextNumber();
this.flipVertical= gd.getNextBoolean();
this.r_od[0][0]= 0.01*gd.getNextNumber();
this.r_od[0][1]= 0.01*gd.getNextNumber();
this.r_xy[0][0]= 0.01*gd.getNextNumber();
......@@ -1852,7 +1854,7 @@ dPXmmc/dphi=
}
/**
* Calculate/set this.lensDistortionParameters and this.interParameterDerivatives
* UPDATE - Modifies lensDistortionParameters, not "this" for multi-threaded
* UPDATE - Modifies lensDistortionParameters, not "this" for multi-threaded
* @param parVect 21-element vector for eyesis sub-camera, including common and individual parameters
* @param mask -mask - which partial derivatives are needed to be calculated (others will be null)
* @param calculateDerivatives calculate array of partial derivatives, if false - just the values
......@@ -1861,13 +1863,15 @@ dPXmmc/dphi=
LensDistortionParameters lensDistortionParameters,
boolean isTripod,
boolean cartesian,
double pixelSize,
double distortionRadius,
double [][] interParameterDerivatives, //partial derivative matrix from subcamera-camera-goniometer to single camera (12x21) if null - just values, no derivatives
double [] parVect,
boolean [] mask // calculate only selected derivatives (all parVect values are still
){
boolean calculateDerivatives=(interParameterDerivatives!=null); // calculate this.interParameterDerivatives -derivatives array (false - just this.values)
boolean calculateDerivatives=(interParameterDerivatives!=null); // calculate this.interParameterDerivatives -derivatives array (false - just this.values)
// change meaning of goniometerHorizontal (tripod vertical) and goniometerAxial (tripod horizontal)
// Alternative variables for cartesian/cylindrical modes
double azimuth_cyl= cartesian? Double.NaN: parVect[0];
double right_cart= cartesian? parVect[0] : Double.NaN;
......@@ -1889,19 +1893,19 @@ dPXmmc/dphi=
double GXYZ0=parVect[14];
double GXYZ1=parVect[15];
double GXYZ2=parVect[16];
double cPS= Math.cos(psi*Math.PI/180); // subCam.psi
double sPS= Math.sin(psi*Math.PI/180); // subCam.psi
double cTH= Math.cos(theta*Math.PI/180); // subCam.theta
double sTH= Math.sin(theta*Math.PI/180); // subCam.theta
double cAZP= Math.cos((cartesian?heading_cart:(azimuth_cyl+phi_cyl))*Math.PI/180); //subCam.azimuth+subCam.phi
double sAZP= Math.sin((cartesian?heading_cart:(azimuth_cyl+phi_cyl))*Math.PI/180); //subCam.azimuth+subCam.phi
// renaming the following 2 to be replaced for cartesian coordinates
double cAZ_cyl= Math.cos(azimuth_cyl*Math.PI/180); //subCam.azimuth
double sAZ_cyl= Math.sin(azimuth_cyl*Math.PI/180); //subCam.azimuth
double cGA= Math.cos(goniometerAxial*Math.PI/180); //eyesisCameraParameters.goniometerAxial
double sGA= Math.sin(goniometerAxial*Math.PI/180); //eyesisCameraParameters.goniometerAxial
double cGH= Math.cos(goniometerHorizontal*Math.PI/180); //eyesisCameraParameters.goniometerHorizontal
......@@ -1912,7 +1916,7 @@ dPXmmc/dphi=
double sHAEPH=Math.sin(horAxisErrPhi*Math.PI/180); //eyesisCameraParameters.horAxisErrPhi
double cHAEPS=Math.cos(horAxisErrPsi*Math.PI/180); //eyesisCameraParameters.horAxisErrPsi
double sHAEPS=Math.sin(horAxisErrPsi*Math.PI/180); //eyesisCameraParameters.horAxisErrPsi\
/*
0) Translate by distance to entrance pupil (lens center)
| Xc0 | | 0 | |Xc|
......@@ -1921,7 +1925,7 @@ dPXmmc/dphi=
*/
double [][] aT0={{0.0},{0.0},{entrancePupilForward}};
Matrix T0=new Matrix(aT0);
/*
Converting from the sub-camera coordinates to the target coordinates
1) rotate by -psi around CZ: Vc1= R1*Vc
......@@ -1931,7 +1935,7 @@ dPXmmc/dphi=
*/
double [][] aR1={{cPS,sPS,0.0},{-sPS,cPS,0.0},{0.0,0.0,1.0}};
Matrix R1=new Matrix(aR1);
/*
/*
2) rotate by - theta around C1X:Vc2= R2*Vc1
| Xc2 | | 1 0 0 | |Xc1|
| Yc2 | = | 0 cos(theta) sin(theta) | * |Yc1|
......@@ -1939,7 +1943,7 @@ dPXmmc/dphi=
*/
double [][] aR2={{1.0,0.0,0.0},{0.0,cTH,sTH},{0.0,-sTH,cTH}};
Matrix R2=new Matrix(aR2);
/*
/*
3) rotate by -(azimuth+phi) around C2Y:Vc3= R3*Vc2
| Xc3 | | cos(azimuth+phi) 0 sin(azimuth+phi) | |Xc2|
| Yc3 | = | 0 1 0 | * |Yc2|
......@@ -1947,7 +1951,7 @@ dPXmmc/dphi=
*/
double [][] aR3={{cAZP,0.0,sAZP},{0.0,1.0,0.0},{-sAZP,0.0,cAZP}};
Matrix R3=new Matrix(aR3);
/*
/*
4) Now axes are aligned, just translate to get to eyesis coordinates: Vey= T1+Vc3
| Xey | | r * sin (azimuth) | |Xc3|
| Yey | = | height+centerAboveHorizontal | + |Yc3|
......@@ -1955,10 +1959,10 @@ dPXmmc/dphi=
*/
double [][] aT1_cyl= {{radius_cyl*sAZ_cyl},{(height+centerAboveHorizontal)},{radius_cyl*cAZ_cyl}}; // {{subCam.radius*sAZ},{subCam.height},{subCam.radius*cAZ}};
double [][] aT1_cart={{right_cart}, {(height+centerAboveHorizontal)},{forward_cart}}; // {{subCam.radius*sAZ},{subCam.height},{subCam.radius*cAZ}};
double [][] aT1= cartesian ? aT1_cart : aT1_cyl;
double [][] aT1= cartesian ? aT1_cart : aT1_cyl;
Matrix T1=new Matrix(aT1);
/**
5) rotate around moving goniometer axis, by (-goniometerAxial) - same as around EY: Vgm1=R4*Vey
| Xgm1 | | 1 0 0 | |Xey|
......@@ -1966,7 +1970,7 @@ dPXmmc/dphi=
| Zgm1 | | 0 -sin(goniometerAxial) cos(goniometerAxial) | |Zey|
*/
double [][] aR4_tripod= {{1.0,0.0,0.0},{0.0,cGA,sGA},{0.0,-sGA,cGA}};
/*
/*
5) rotate around moving goniometer axis, by (-goniometerAxial) - same as around EY: Vgm1=R4*Vey
| Xgm1 | | cos(goniometerAxial) 0 sin(goniometerAxial) | |Xey|
| Ygm1 | = | 0 1 0 | * |Yey|
......@@ -1974,7 +1978,7 @@ dPXmmc/dphi=
*/
double [][] aR4_goniometer={{cGA,0.0,sGA},{0.0,1.0,0.0},{-sGA,0.0,cGA}};
Matrix R4=new Matrix(isTripod?aR4_tripod:aR4_goniometer);
/*
/*
6) move to the goniometer horizontal axis:Vgm2=T2+Vgm1
| Xgm2 | | 0 | |Xgm1|
| Ygm2 | = | 0 | + |Ygm1|
......@@ -1982,7 +1986,7 @@ dPXmmc/dphi=
*/
double [][] aT2={{0.0},{0.0},{interAxisDistance}}; //eyesisCameraParameters.interAxisDistance
Matrix T2=new Matrix(aT2);
/*
/*
7) rotate around Zgm2 by -interAxisAngle, so Xgm3 axis is the same as horizontal goniometer axis: Vgm3=R5*Vgm2
| Xgm3 | | cos(interAxisAngle) sin(interAxisAngle) 0 | |Xgm2|
| Ygm3 | = |-sin(interAxisAngle) cos(interAxisAngle) 0 | * |Ygm2|
......@@ -1997,7 +2001,7 @@ dPXmmc/dphi=
| Zgm4 | | -sin(goniometerHorizontal) 0 cos(goniometerHorizontal) | |Zgm3|
*/
double [][] aR6_tripod= {{cGH,0.0,sGH},{0.0,1.0,0.0},{-sGH,0.0,cGH}};
/*
/*
8) rotate around goniometer horizontal axis (Xgm3) by -goniometerHorizontal: Vgm4=R6*Vgm3
| Xgm4 | | 1 0 0 | |Xgm3|
| Ygm4 | = | 0 cos(goniometerHorizontal) sin(goniometerHorizontal) | * |Ygm3|
......@@ -2005,7 +2009,7 @@ dPXmmc/dphi=
*/
double [][] aR6_goniometer={{1.0,0.0,0.0},{0.0,cGH,sGH},{0.0,-sGH,cGH}};
Matrix R6=new Matrix(isTripod?aR6_tripod:aR6_goniometer);
/*
/*
9) Correct roll error of the goniometer horizontal axis - rotate by -horAxisErrPsi around Zgm4: Vgm5=R7*Vgm4
| Xgm5 | | cos(horAxisErrPsi) sin(horAxisErrPsi) 0 | |Xgm4|
| Ygm5 | = |-sin(horAxisErrPsi) cos(horAxisErrPsi) 0 | * |Ygm4|
......@@ -2013,9 +2017,9 @@ dPXmmc/dphi=
*/
double [][] aR7={{cHAEPS,sHAEPS,0.0},{-sHAEPS,cHAEPS,0.0},{0.0,0.0,1.0}};
Matrix R7=new Matrix(aR7);
/*
/*
10) Correct azimuth error of the goniometer hoirizontal axis - rotate by -horAxisErrPhi around Ygm5: Vgm6=R8*Vgm5
| Xgm6 | | cos(horAxisErrPhi) 0 sin(horAxisErrPhi) | |Xgm5|
| Ygm6 | = | 0 1 0 | * |Ygm5|
| Zgm6 | |-sin(horAxisErrPhi) 0 cos(horAxisErrPhi) | |Zgm5|
......@@ -2028,14 +2032,14 @@ dPXmmc/dphi=
double [][] aR8_tripod= {{1.0, 0.0, 0.0},{0.0,cHAEPH,sHAEPH},{0.0, -sHAEPH,cHAEPH}};
double [][] aR8_goniometer={{cHAEPH,0.0,sHAEPH},{0.0, 1.0, 0.0},{-sHAEPH, 0.0,cHAEPH}};
Matrix R8=new Matrix(isTripod?aR8_tripod:aR8_goniometer);
/*
/*
11) translate to the target zero point: Vt= T3+Vgm6
| Xt | | GXYZ[0] | |Xgm6|
| Yt | = |-GXYZ[1] | + |Ygm6| // Y - up positive
| Zt | |-GXYZ[2] | |Zgm6| // Z - away positive
*/
// double [][] aT3={{parVect[12]},{-parVect[13]},{-parVect[14]}};//{{eyesisCameraParameters.GXYZ[0]},{eyesisCameraParameters.GXYZ[1]},{eyesisCameraParameters.GXYZ[2]}};
double [][] aT3={{GXYZ0},{-GXYZ1},{-GXYZ2}};//{{eyesisCameraParameters.GXYZ[0]},{eyesisCameraParameters.GXYZ[1]},{eyesisCameraParameters.GXYZ[2]}};
// double [][] aT3={{parVect[12]},{ parVect[13]},{-parVect[14]}};//{{eyesisCameraParameters.GXYZ[0]},{eyesisCameraParameters.GXYZ[1]},{eyesisCameraParameters.GXYZ[2]}};
Matrix T3=new Matrix(aT3);
......@@ -2056,6 +2060,10 @@ dPXmmc/dphi=
// System.out.println("interParameterDerivatives[0]="+sprintfArray(interParameterDerivatives[0]));
}
double [] extrinsicParams=parametersFromMAMB(MA,MB); // all after 6 are 0;
lensDistortionParameters.pixelSize = pixelSize;
lensDistortionParameters.distortionRadius = distortionRadius;
lensDistortionParameters.distance=extrinsicParams[2];
lensDistortionParameters.x0=extrinsicParams[0];
lensDistortionParameters.y0=extrinsicParams[1];
......@@ -2074,10 +2082,10 @@ dPXmmc/dphi=
lensDistortionParameters.distortionA=parVect[24]; //subCam.distortionA;
lensDistortionParameters.distortionB=parVect[25]; //subCam.distortionB;
lensDistortionParameters.distortionC=parVect[26]; //subCam.distortionC;
lensDistortionParameters.r_xy=new double [6][2];
lensDistortionParameters.r_od=new double [7][2];
int index=27;
for (int i=0;i<lensDistortionParameters.r_od.length;i++){
if (i>0){
......@@ -2087,23 +2095,10 @@ dPXmmc/dphi=
lensDistortionParameters.r_od[i][0]=parVect[index++];
lensDistortionParameters.r_od[i][1]=parVect[index++];
}
/*
for (double [] row :lensDistortionParameters.r_xy){
row[0]=parVect[index++];
row[1]=parVect[index++];
}
for (double [] row :lensDistortionParameters.r_od){
row[0]=parVect[index++];
row[1]=parVect[index++];
}
*/
///
// public double [][] r_xy=null; // only 6, as for the first term delta x, delta y ==0
// public double [][] r_od=null; // ortho
lensDistortionParameters.recalcCommons(); // uncliding lensDistortionParameters.r_xyod
lensDistortionParameters.recalcCommons(); // uncluding lensDistortionParameters.r_xyod
if (this.debugLevel>2){
System.out.println("lensDistortionParameters.recalcCommons()");
System.out.println("lensDistortionParameters.distance="+IJ.d2s(lensDistortionParameters.distance, 3));
......@@ -2133,7 +2128,7 @@ dPXmmc/dphi=
System.out.println("lensDistortionParameters.r_od["+i+"][1]"+IJ.d2s(lensDistortionParameters.r_od[i][1], 5));
}
}
if (!calculateDerivatives) return;
if (!calculateDerivatives) return;
/* Calculate all derivativs as a matrix.
* Input parameters (columns):
0 public double azimuth; // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
......@@ -2143,15 +2138,15 @@ dPXmmc/dphi=
4 public double theta; // degrees, optical axis from the eyesis horizon, positive - up
5 public double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
6 public double goniometerHorizontal; // goniometer rotation around "horizontal" axis (tilting from the target - positive)
7 public double goniometerAxial; // goniometer rotation around Eyesis axis (clockwise in plan - positive
7 public double goniometerAxial; // goniometer rotation around Eyesis axis (clockwise in plan - positive
8 public double interAxisDistance; // distance in mm between two goniometer axes
9 public double interAxisAngle; // angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
10 public double horAxisErrPhi; // angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
11 public double horAxisErrPsi; // angle in degrees "horizontal" goniometer axis is rotated around moving X axis (up)
Two new parameters
12 public double entrancePupilForward; // common to all lenses - distance from the sensor to the lens entrance pupil
13 public double centerAboveHorizontal; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to
14(12) x public double [] GXYZ=null; // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
13 public double centerAboveHorizontal; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to
14(12) x public double [] GXYZ=null; // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
15(13) y
16(14) z
17(15) public double focalLength=4.5;
......@@ -2237,9 +2232,9 @@ dPXmmc/dphi=
41 Diagonal elongation for r^8"
*/
// interParameterDerivatives=new double[getNumInputs()][]; //partial derivative matrix from subcamera-camera-goniometer to single camera (12x21)
//calculate dMA_azimuth
//calculate dMB_azimuth
//calculate dMA_azimuth
//calculate dMB_azimuth
/*
// MA=R8*R7*R6*R5*R4*R3*R2*R1;
// MB=T3+(R8*R7*R6*R5*(T2+R4*T1)); - old
......@@ -2260,7 +2255,7 @@ dPXmmc/dphi=
double [][] aT1={{subCam.radius*sAZ},{subCam.height},{subCam.radius*cAZ}};
Matrix T1=new Matrix(aT1);
Matrix
Matrix
// Make a function MA, MB - >parameters (column) - reuse it above and for each interParameterDerivatives row
Matrix dMA_azimuth=R8*R7*R6*R5*R4*dR3_azimuth*R2*R1;
Matrix dMB_azimuth=T3+(R8*R7*R6*R5*(R4*dT1_azimuth));
......@@ -2367,7 +2362,7 @@ dPXmmc/dphi=
System.out.println("interParameterDerivatives[1]="+sprintfArray(interParameterDerivatives[1]));
}
}
} else interParameterDerivatives[1]=null;
} else interParameterDerivatives[1]=null;
//2 public double height; // mm, downwards - from the origin point
if (mask[2]) {
double [][] adT1_height={{0.0},{1.0},{0.0}};
......@@ -2382,7 +2377,7 @@ dPXmmc/dphi=
dMB_height.print(10, 5);
System.out.println("interParameterDerivatives[2]="+sprintfArray(interParameterDerivatives[2]));
}
} else interParameterDerivatives[2]=null;
} else interParameterDerivatives[2]=null;
//3 public double phi; // degrees, optical axis from azimuth/r vector, clockwise
if (mask[3]) { // here the same for cartesian
double [][] adR3_phi={{-sAZP,0.0,cAZP},{0.0,0.0,0.0},{-cAZP,0.0,-sAZP}}; // same as adR3_azimuth
......@@ -2398,7 +2393,7 @@ dPXmmc/dphi=
dMB_phi.print(10, 5);
System.out.println("interParameterDerivatives[3]="+sprintfArray(interParameterDerivatives[3]));
}
} else interParameterDerivatives[3]=null;
} else interParameterDerivatives[3]=null;
//4 public double theta; // degrees, optical axis from the eyesis horizon, positive - up
if (mask[4]) {
double [][] adR2_theta={{0.0,0.0,0.0},{0.0,-sTH,cTH},{0.0,-cTH,-sTH}};
......@@ -2414,7 +2409,7 @@ dPXmmc/dphi=
dMB_theta.print(10, 5);
System.out.println("interParameterDerivatives[4]="+sprintfArray(interParameterDerivatives[4]));
}
} else interParameterDerivatives[4]=null;
} else interParameterDerivatives[4]=null;
//5 public double psi; // degrees, rotation (of the sensor) around the optical axis. Positive if camera is rotated clockwise looking to the target
if (mask[5]) {
double [][] adR1_psi={{-sPS,cPS,0.0},{-cPS,-sPS,0.0},{0.0,0.0,0.0}};
......@@ -2424,7 +2419,7 @@ dPXmmc/dphi=
Matrix dMB_psi=dMA_psi.times(T0); // new term
interParameterDerivatives[5]=d_parametersFromMAMB(dMA_psi,dMB_psi,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) {
/*
/*
System.out.print("R1:");
R1.print(10, 5);
System.out.print("dR1_psi:");
......@@ -2439,7 +2434,7 @@ dPXmmc/dphi=
dMB_psi.print(10, 5);
System.out.println("interParameterDerivatives[5]="+sprintfArray(interParameterDerivatives[5]));
}
} else interParameterDerivatives[5]=null;
} else interParameterDerivatives[5]=null;
//6 public double goniometerHorizontal; // goniometer rotation around "horizontal" axis (tilting from the target - positive)
if (mask[6]) {
/* define for isTripod */
......@@ -2456,8 +2451,8 @@ dPXmmc/dphi=
dMB_goniometerHorizontal.print(10, 5);
System.out.println("interParameterDerivatives[6]="+sprintfArray(interParameterDerivatives[6]));
}
} else interParameterDerivatives[6]=null;
//7 public double goniometerAxial; // goniometer rotation around Eyesis axis (clockwise in plan - positive
} else interParameterDerivatives[6]=null;
//7 public double goniometerAxial; // goniometer rotation around Eyesis axis (clockwise in plan - positive
if (mask[7]) {
// define for isTripod
double [][] adR4_goniometerAxial_tripod= {{ 0.0,0.0,0.0},{0.0,-sGA,cGA},{ 0.0,-cGA,-sGA}};
......@@ -2473,7 +2468,7 @@ dPXmmc/dphi=
dMB_goniometerAxial.print(10, 5);
System.out.println("interParameterDerivatives[7]="+sprintfArray(interParameterDerivatives[7]));
}
} else interParameterDerivatives[7]=null;
} else interParameterDerivatives[7]=null;
//8 public double interAxisDistance; // distance in mm between two goniometer axes
if (mask[8]) {
double [][] adT2_interAxisDistance={{0.0},{0.0},{1.0}};
......@@ -2488,13 +2483,13 @@ dPXmmc/dphi=
dMB_interAxisDistance.print(10, 5);
System.out.println("interParameterDerivatives[8]="+sprintfArray(interParameterDerivatives[8]));
}
} else interParameterDerivatives[8]=null;
} else interParameterDerivatives[8]=null;
//9 public double interAxisAngle; // angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
if (mask[9]) {
double [][] adR5_interAxisAngle={{-sGIAA,cGIAA,0.0},{-cGIAA,-sGIAA,0.0},{0.0,0.0,0.0}};
Matrix dR5_interAxisAngle=new Matrix(adR5_interAxisAngle);
Matrix dMA_interAxisAngle=R8.times(R7.times(R6.times(dR5_interAxisAngle.times(R4.times(R3.times(R2.times(R1)))))));
Matrix dMB_interAxisAngle=R8.times(R7.times(R6.times(dR5_interAxisAngle.times(T2.plus(R4.times(T1))))));
Matrix dMB_interAxisAngle=R8.times(R7.times(R6.times(dR5_interAxisAngle.times(T2.plus(R4.times(T1))))));
interParameterDerivatives[9]=d_parametersFromMAMB(dMA_interAxisAngle,dMB_interAxisAngle,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) {
System.out.println("dMA_interAxisAngle:");
......@@ -2503,10 +2498,10 @@ dPXmmc/dphi=
dMB_interAxisAngle.print(10, 5);
System.out.println("interParameterDerivatives[9]="+sprintfArray(interParameterDerivatives[9]));
}
} else interParameterDerivatives[9]=null;
} else interParameterDerivatives[9]=null;
//10 public double horAxisErrPhi; // angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
// change sHAEPH to rotate like theta /1 0 0 /0 c s/ 0 -s c/ (derivative -/0 0 0 /0 -s c/ 0 -c -s/
// change sHAEPH to rotate like theta /1 0 0 /0 c s/ 0 -s c/ (derivative -/0 0 0 /0 -s c/ 0 -c -s/
if (mask[10]) {
double [][] adR8_horAxisErrPhi_tripod= {{0.0, 0.0, 0.0},{0.0,-sHAEPH,cHAEPH},{ 0.0,-cHAEPH,-sHAEPH}};
double [][] adR8_horAxisErrPhi_goniometer={{-sHAEPH,0.0,cHAEPH},{0.0, 0.0, 0.0},{-cHAEPH, 0.0,-sHAEPH}};
......@@ -2521,7 +2516,7 @@ dPXmmc/dphi=
dMB_horAxisErrPhi.print(10, 5);
System.out.println("interParameterDerivatives[10]="+sprintfArray(interParameterDerivatives[10]));
}
} else interParameterDerivatives[10]=null;
} else interParameterDerivatives[10]=null;
//11 public double horAxisErrPsi; // angle in degrees "horizontal" goniometer axis is rotated around moving X axis (up)
if (mask[11]) {
double [][] adR7_horAxisErrPsi={{-sHAEPS,cHAEPS,0.0},{-cHAEPS,-sHAEPS,0.0},{0.0,0.0,0.0}};
......@@ -2536,7 +2531,7 @@ dPXmmc/dphi=
dMB_horAxisErrPsi.print(10, 5);
System.out.println("interParameterDerivatives[11]="+sprintfArray(interParameterDerivatives[11]));
}
} else interParameterDerivatives[11]=null;
} else interParameterDerivatives[11]=null;
// // R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 || T0 | T1 | T2 | T3 |
//12 public double entrancePupilForward // | | | | | | | || + | | | |
//13 public double centerAboveHorizontal // | | | | | | | || | + | | |
......@@ -2554,8 +2549,8 @@ dPXmmc/dphi=
dMB_entrancePupilForward.print(10, 5);
System.out.println("interParameterDerivatives[12]="+sprintfArray(interParameterDerivatives[12]));
}
} else interParameterDerivatives[12]=null;
} else interParameterDerivatives[12]=null;
if (mask[13]) {
double [][] adT1_centerAboveHorizontal={{0.0},{1.0},{0.0}};
Matrix dT1_centerAboveHorizontal=new Matrix(adT1_centerAboveHorizontal);
......@@ -2569,9 +2564,9 @@ dPXmmc/dphi=
dMB_centerAboveHorizontal.print(10, 5);
System.out.println("interParameterDerivatives[13]="+sprintfArray(interParameterDerivatives[13]));
}
} else interParameterDerivatives[13]=null;
} else interParameterDerivatives[13]=null;
//14 x public double [] GXYZ=null; // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
if (mask[14]) {
double [][] adT3_GXYZ0={{1.0},{0.0},{0.0}};
......@@ -2585,7 +2580,7 @@ dPXmmc/dphi=
dMB_GXYZ0.print(10, 5);
System.out.println("interParameterDerivatives[14]="+sprintfArray(interParameterDerivatives[14]));
}
} else interParameterDerivatives[14]=null;
} else interParameterDerivatives[14]=null;
//13 y
if (mask[15]) {
// double [][] adT3_GXYZ1={{0.0},{1.0},{0.0}};
......@@ -2601,7 +2596,7 @@ dPXmmc/dphi=
dMB_GXYZ1.print(10, 5);
System.out.println("interParameterDerivatives[15]="+sprintfArray(interParameterDerivatives[15]));
}
} else interParameterDerivatives[15]=null;
} else interParameterDerivatives[15]=null;
//14 z
if (mask[16]) {
// double [][] adT3_GXYZ2={{0.0},{0.0},{1.0}};
......@@ -2616,7 +2611,7 @@ dPXmmc/dphi=
dMB_GXYZ2.print(10, 5);
System.out.println("interParameterDerivatives[16]="+sprintfArray(interParameterDerivatives[16]));
}
} else interParameterDerivatives[16]=null;
} else interParameterDerivatives[16]=null;
// now fill the rest, unchanged parameters
/*
int numInputs=22; //was 21 parameters in subcamera+...
......@@ -2633,10 +2628,10 @@ dPXmmc/dphi=
//24 (22) public double distortionA=0.0; // r^4 (normalized to focal length or to sensor half width?)
//25 (23) public double distortionB=0.0; // r^3
//26 (24) public double distortionC=0.0; // r^2
//27..52 - non-radial parameters
//27..52 - non-radial parameters
// for (int inpPar=15; inpPar<getNumInputs(); inpPar++){
for (int inpPar=17; inpPar<getNumInputs(); inpPar++){ // OK with A8. Should be OK with non-radial parameters ((27..52) also
for (int inpPar=17; inpPar<getNumInputs(); inpPar++){ // OK with A8. Should be OK with non-radial parameters ((27..52) also
if (mask[inpPar]){
interParameterDerivatives[inpPar]=new double[getNumOutputs()];
for (int outPar=0; outPar<getNumOutputs(); outPar++){
......@@ -2649,7 +2644,7 @@ dPXmmc/dphi=
}
}
public double [] parametersFromMAMB(Matrix MA, Matrix MB){
double [] result= new double [getNumOutputs()]; // only first 6 are used
for (int i=6; i<getNumOutputs();i++) result[i]=0.0;
......@@ -2705,7 +2700,7 @@ dPXmmc/dphi=
return result;
}
/**
*
*
* @param d_MA differential of the rotational matrix MA by some parameter
* @param d_MB differential of the translational matrix MB by some parameter
* @param MA - rotation matrix
......@@ -2812,8 +2807,7 @@ dPXmmc/dphi=
for (int i=0;i<arr.length;i++) result+= ((i>0)?", ":"")+arr[i];
return "["+result+"]";
}
public int getNumInputs(){return numInputs;}
public int getNumOutputs(){return numOutputs;}
}
\ No newline at end of file
......@@ -62,8 +62,8 @@ import ij.gui.GenericDialog;
// non-adjustable parameters, not parts of vector
public int numStations;
public double [] stationWeight; // reprojection error weights (close station - relax errors)
public boolean isTripod= false; // when true - make goniometerHorizontal rotation around "vertical" axis and "goniometerAxial" - around
public boolean cartesian=false; //
private boolean is_tripod= false; // when true - make goniometerHorizontal rotation around "vertical" axis and "goniometerAxial" - around
private boolean cartesian=false; //
// rotated horizontal.
private int defaultSensorWidth= 2592;
private int defaultSensorHeight= 1936;
......@@ -73,7 +73,7 @@ import ij.gui.GenericDialog;
public double maskBlurSigma= -3; //2.0; // blur sensor masks (>0 - pixels, <0 - in grid units)
public double badNodeThreshold=0.1; // filter out grid nodes with difference from quadratically predicted from 8 neighbors in pixels
public int maxBadNeighb= 1; // maximal number of bad nodes around the corrected one to fix
public int minimalValidNodes=50; // do not use images with less than this number of non-zero nodes (after all applicable weight masks)
public int minimalValidNodes=10; // do not use images with less than this number of non-zero nodes (after all applicable weight masks)
public int weightMultiImageMode=1; // increase weight for multi-image sets (0 - do not increase, 1 - multiply by number of images in a set to weightMultiExponent power)
public double weightMultiExponent= 1.0;
public double weightDiameterExponent=1.0; // if( >0) use grid diameter to scale weights of this image
......@@ -84,6 +84,7 @@ import ij.gui.GenericDialog;
public double balanceChannelWeightsMode=-1.0; // <0 - use defaults, 0 - keep, >0 balance by number of points to this power
public double removeOverRMS=2.0; // error is multiplied by weight function before comparison (more permissive on the borders
public double removeOverRMSNonweighted=4.0; // error is not multiplied (no more permissions on tyhe borders
public boolean invertUnmarkedLwirGrid = true; // LWIR grid currently is saved shifted (not compensating color inversion)
public int [] extrinsicIndices={6,7,8,9,10,11,12,13,14,15,16}; //support variations
public double [][] variationsDefaults={
null, // 0
......@@ -104,6 +105,19 @@ import ij.gui.GenericDialog;
{10.0,2.0,0.0,1.0}, // 15 GXYZ1
{10.0,2.0,0.0,1.0} // 16 GXYZ2
};
public boolean isTripod() {
return is_tripod;
}
public boolean isCartesian() {
return cartesian;
}
public boolean isLwirUnmarkedInverted() {
return invertUnmarkedLwirGrid;
}
public int tiltIndex=6;
private ParameterVariationCosts [] parameterVariationCosts=null;
......@@ -337,7 +351,8 @@ import ij.gui.GenericDialog;
double shrinkBlurLevel,
double balanceChannelWeightsMode,
double removeOverRMS,
double removeOverRMSNonweighted
double removeOverRMSNonweighted,
boolean invertUnmarkedLwirGrid
){
double [] GXYZ={GXYZ_0,GXYZ_1,GXYZ_2};
setSameEyesisCameraParameters (
......@@ -372,7 +387,8 @@ import ij.gui.GenericDialog;
shrinkBlurLevel,
balanceChannelWeightsMode,
removeOverRMS,
removeOverRMSNonweighted
removeOverRMSNonweighted,
invertUnmarkedLwirGrid
);
}
public EyesisCameraParameters (
......@@ -407,7 +423,8 @@ import ij.gui.GenericDialog;
double shrinkBlurLevel,
double balanceChannelWeightsMode,
double removeOverRMS,
double removeOverRMSNonweighted
double removeOverRMSNonweighted,
boolean invertUnmarkedLwirGrid
){
setSameEyesisCameraParameters (
numStations,
......@@ -441,7 +458,8 @@ import ij.gui.GenericDialog;
shrinkBlurLevel,
balanceChannelWeightsMode,
removeOverRMS,
removeOverRMSNonweighted
removeOverRMSNonweighted,
invertUnmarkedLwirGrid
);
}
void setSameEyesisCameraParameters (
......@@ -476,10 +494,11 @@ import ij.gui.GenericDialog;
double shrinkBlurLevel,
double balanceChannelWeightsMode,
double removeOverRMS,
double removeOverRMSNonweighted
double removeOverRMSNonweighted,
boolean invertUnmarkedLwirGrid
){
this.numStations=numStations;
this.isTripod=isTripod;
this.is_tripod=isTripod;
this.cartesian = cartesian; // Need to set each subcamera?
this.defaultSensorWidth=defaultSensorWidth;
this.defaultSensorHeight=defaultSensorHeight;
......@@ -543,7 +562,7 @@ import ij.gui.GenericDialog;
EyesisCameraParameters source,
EyesisCameraParameters destination) {
destination.numStations=newNumStations;
destination.isTripod=source.isTripod;
destination.is_tripod=source.is_tripod;
destination.defaultSensorWidth=source.defaultSensorWidth;
destination.defaultSensorHeight=source.defaultSensorHeight;
destination.shrinkGridForMask=source.shrinkGridForMask; //shrink detected grids by one point for/vert this number of times before calculating masks
......@@ -561,6 +580,7 @@ import ij.gui.GenericDialog;
destination.shrinkBlurLevel=source.shrinkBlurLevel;
destination.balanceChannelWeightsMode=source.balanceChannelWeightsMode;
destination.removeOverRMSNonweighted=source.removeOverRMSNonweighted;
destination.invertUnmarkedLwirGrid=source.invertUnmarkedLwirGrid;
destination.goniometerHorizontal=new double[destination.numStations];
destination.goniometerAxial=new double[destination.numStations];
destination.interAxisDistance=new double[destination.numStations];
......@@ -598,7 +618,7 @@ import ij.gui.GenericDialog;
}
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"isTripod",this.isTripod+"");
properties.setProperty(prefix+"isTripod",this.is_tripod+"");
properties.setProperty(prefix+"cartesian",this.cartesian+"");
properties.setProperty(prefix+"defaultSensorWidth",this.defaultSensorWidth+"");
properties.setProperty(prefix+"defaultSensorHeight",this.defaultSensorHeight+"");
......@@ -618,6 +638,7 @@ import ij.gui.GenericDialog;
properties.setProperty(prefix+"balanceChannelWeightsMode",this.balanceChannelWeightsMode+"");
properties.setProperty(prefix+"removeOverRMS",this.removeOverRMS+"");
properties.setProperty(prefix+"removeOverRMSNonweighted",this.removeOverRMSNonweighted+"");
properties.setProperty(prefix+"invertUnmarkedLwirGrid",this.invertUnmarkedLwirGrid+"");
properties.setProperty(prefix+"numSubCameras",this.eyesisSubCameras[0].length+"");
properties.setProperty(prefix+"numStations",this.numStations+"");
for (int numStation=0;numStation<this.numStations;numStation++){
......@@ -641,7 +662,7 @@ import ij.gui.GenericDialog;
}
public void getProperties(String prefix,Properties properties){
if (properties.getProperty(prefix+"isTripod")!=null)
this.isTripod=Boolean.parseBoolean(properties.getProperty(prefix+"isTripod"));
this.is_tripod=Boolean.parseBoolean(properties.getProperty(prefix+"isTripod"));
if (properties.getProperty(prefix+"cartesian")!=null)
this.cartesian=Boolean.parseBoolean(properties.getProperty(prefix+"cartesian"));
// For old compatibility
......@@ -690,6 +711,9 @@ import ij.gui.GenericDialog;
this.removeOverRMS=Double.parseDouble(properties.getProperty(prefix+"removeOverRMS"));
if (properties.getProperty(prefix+"removeOverRMSNonweighted")!=null)
this.removeOverRMSNonweighted=Double.parseDouble(properties.getProperty(prefix+"removeOverRMSNonweighted"));
if (properties.getProperty(prefix+"invertUnmarkedLwirGrid")!=null)
this.invertUnmarkedLwirGrid=Boolean.parseBoolean(properties.getProperty(prefix+"invertUnmarkedLwirGrid"));
boolean multiStation=true; // new default
int newNumStations=1;
int numSubCameras=0;
......@@ -799,14 +823,14 @@ import ij.gui.GenericDialog;
modelChoice[0]="--- keep current ---";
for (int i=0;i<distortionModelDescriptions.length;i++) modelChoice[i+1]=distortionModelDescriptions[i];
gd.addChoice("Change camera distortion model for all channels", modelChoice, modelChoice[0]);
gd.addCheckbox("Tripod mode (first vertical axis, then horizontal), changes meaning of the next 2 fields",this.isTripod);
gd.addCheckbox("Tripod mode (first vertical axis, then horizontal), changes meaning of the next 2 fields",this.is_tripod);
gd.addMessage("=== Camera parameters to be fitted ===");
for (int numStation=0;numStation<this.numStations;numStation++) {
if (this.numStations>1){
gd.addMessage("--- Station number "+numStation+" ---");
gd.addNumericField("Station reprojection errors weight", 100*this.stationWeight[numStation], 1,5,"%");
}
if (this.isTripod) {
if (this.is_tripod) {
gd.addNumericField("Tripod rotation around vertical axis (clockwise from top - positive)",this.goniometerHorizontal[numStation], 3,7,"degrees");
gd.addNumericField("Tripod rotation around horizontal axis (camera up - positive)", this.goniometerAxial[numStation], 3,7,"degrees");
} else {
......@@ -816,7 +840,7 @@ import ij.gui.GenericDialog;
gd.addNumericField("Distance between goniometer axes", this.interAxisDistance[numStation], 3,7,"mm");
gd.addNumericField("Angle error between goniometer axes (<0 if vertical axis rotated CW )",this.interAxisAngle[numStation], 3,7,"degrees");
if (this.isTripod) {
if (this.is_tripod) {
gd.addNumericField("Vertical tripod axis tilt from true vertical", this.horAxisErrPhi[numStation], 3,7,"degrees");
gd.addNumericField("Vertical tripod axis roll error from true vertical", this.horAxisErrPsi[numStation], 3,7,"degrees");
} else {
......@@ -852,6 +876,7 @@ import ij.gui.GenericDialog;
gd.addNumericField("Channel balace mode: <0 - use specified defaults, 0 - keep curent, >0 - exponent for correction (1.0 - precise equalization)", this.balanceChannelWeightsMode, 3,6,"");
gd.addNumericField("Remove nodes with error greater than scaled RMS in that image, weighted", this.removeOverRMS, 2,6,"xRMS");
gd.addNumericField("Same, not weghted (not more permissive near the borders with low weight)", this.removeOverRMSNonweighted, 2,6,"xRMS");
gd.addCheckbox ("Unmared grid files for LWIR is saved invereted", this.invertUnmarkedLwirGrid);
gd.addNumericField("Number of sub-camera modules", this.eyesisSubCameras[0].length, 0,2,"");
gd.addNumericField("Number of sub-camera module to edit (<=0 - none)", nextSubCamera, 0,2,"");
gd.enableYesNoCancel("OK", "Done");
......@@ -868,7 +893,7 @@ import ij.gui.GenericDialog;
}
}
this.isTripod= gd.getNextBoolean();
this.is_tripod= gd.getNextBoolean();
for (int numStation=0;numStation<this.numStations;numStation++) {
if (this.numStations>1){
this.stationWeight[numStation]=0.01*gd.getNextNumber();
......@@ -904,6 +929,7 @@ import ij.gui.GenericDialog;
this.balanceChannelWeightsMode= gd.getNextNumber();
this.removeOverRMS = gd.getNextNumber();
this.removeOverRMSNonweighted= gd.getNextNumber();
this.invertUnmarkedLwirGrid = gd.getNextBoolean();
int numSubCams= (int) gd.getNextNumber();
int numSubCam= (int) gd.getNextNumber();
if (numSubCams!=this.eyesisSubCameras[0].length){
......@@ -2504,8 +2530,8 @@ import ij.gui.GenericDialog;
public int offset_channel = 4; // 0;
public int new_subcam = 1; // new subcamera number
public double offset_height = 50.8;
public double offset_right = -35.0; //vnir -35., lwir +35.0
public double offset_forward = 15.0; //vnir +??, lwir -??
public double offset_right = -35.0; //eo -35., lwir +35.0
public double offset_forward = 15.0; //eo +??, lwir -??
public double offset_heading = 0.0;
public double offset_elevation = 0.0;
public double offset_roll = 0.0;
......
......@@ -5476,7 +5476,7 @@ public class EyesisCorrectionParameters {
gd.addMessage ("Unity up vector in camera coordinate system (x - right, y - up, z - to camera): {"+
this.vertical_xyz[0]+","+this.vertical_xyz[1]+","+this.vertical_xyz[2]+"}");
gd.addTab ("LWIR", "parameters for LWIR/VNIR 8-camera rig");
gd.addTab ("LWIR", "parameters for LWIR/EO 8-camera rig");
this.lwir.dialogQuestions(gd);
// gd.buildDialog();
......
......@@ -362,4 +362,12 @@ import java.util.Properties;
updateCartesian();
this.cartesian = cartesian;
}
public double getPixelSize() {
return this.pixelSize;
}
public double getDistortionRadius() {
return this.distortionRadius;
}
}
......@@ -496,12 +496,12 @@ public class LwirReader {
if (lrp.lwir_ffc) {
calibrate(lrp); // seems to work. test calibration duration and if any images are sent during calibration
}
int num_frames = lrp.avg_number + lrp.vnir_lag + 2 * lrp.max_frame_diff;
int num_frames = lrp.avg_number + lrp.eo_lag + 2 * lrp.max_frame_diff;
ImagePlus [][] imps = readAllMultiple(
num_frames,
// lrp.lwir_telemetry,
false, // final boolean show,
lrp.vnir_scale);
lrp.eo_scale);
if (imps == null) {
LOGGER.error("acquire(): failed to acquire images");
return null;
......@@ -521,9 +521,9 @@ public class LwirReader {
LOGGER.warn(String.format("LWIR channel %d time from FFC: %.3f", chn, after_ffc[chn]));
}
int [] lags = new int [lrp.lwir_channels.length + lrp.vnir_channels.length];
int [] lags = new int [lrp.lwir_channels.length + lrp.eo_channels.length];
for (int i = 0; i < lags.length; i++) {
lags[i] = (i >= lrp.lwir_channels.length) ? lrp.vnir_lag : 0;
lags[i] = (i >= lrp.lwir_channels.length) ? lrp.eo_lag : 0;
}
ImagePlus [][] imps_sync = matchSets(
imps,
......@@ -605,10 +605,10 @@ public class LwirReader {
public boolean programLWIRCamera(LwirReaderParameters lrp) {
int lwir_master_port = 0;
int vnir_master_port = 0;
int eo_master_port = 0;
int num_lwir = lrp.lwir_channels.length;
int num_vnir = lrp.vnir_channels.length;
final String [] urls = new String [num_lwir + num_vnir];
int num_eo = lrp.eo_channels.length;
final String [] urls = new String [num_lwir + num_eo];
for (int chn:lrp.lwir_channels) {
urls[chn] = "http://"+lrp.lwir_ip+"/parsedit.php?immediate&sensor_port="+chn+
"&BITS=16"+
......@@ -623,21 +623,21 @@ public class LwirReader {
"&XMIT_TIMESTAMP=1*0";
}
}
for (int chn:lrp.vnir_channels) {
for (int chn:lrp.eo_channels) {
int minExposure=10; // usec
int maxExposure=1000000; //usec
int minGain=(int) (0x10000*1.0);
int maxGain=(int) (0x10000*15.75);
int minScale=0;
int maxScale=(int) (0x10000*4.0);
int exposure= (int) (Math.round(1000*lrp.vnir_exposure_ms * lrp.vnir_exp_corr[chn]));
int autoExposureMax= (int) (Math.round(1000*lrp.vnir_max_autoexp_ms));
int gain= (int) (Math.round(0x10000*lrp.vnir_gain_g));
int rScale= (int) (Math.round(0x10000*lrp.vnir_gain_rg*lrp.vnir_gcorr_rbgb[3*chn+0]));
int bScale= (int) (Math.round(0x10000*lrp.vnir_gain_bg*lrp.vnir_gcorr_rbgb[3*chn+1]));
int gScale= (int) (Math.round(0x10000* lrp.vnir_gcorr_rbgb[3*chn+2]));
int autoExp= lrp.vnir_autoexp?1:0;
int autoWB= lrp.vnir_whitebal?1:0;
int exposure= (int) (Math.round(1000*lrp.eo_exposure_ms * lrp.eo_exp_corr[chn]));
int autoExposureMax= (int) (Math.round(1000*lrp.eo_max_autoexp_ms));
int gain= (int) (Math.round(0x10000*lrp.eo_gain_g));
int rScale= (int) (Math.round(0x10000*lrp.eo_gain_rg*lrp.eo_gcorr_rbgb[3*chn+0]));
int bScale= (int) (Math.round(0x10000*lrp.eo_gain_bg*lrp.eo_gcorr_rbgb[3*chn+1]));
int gScale= (int) (Math.round(0x10000* lrp.eo_gcorr_rbgb[3*chn+2]));
int autoExp= lrp.eo_autoexp?1:0;
int autoWB= lrp.eo_whitebal?1:0;
if (exposure<minExposure) exposure=minExposure; else if (exposure>maxExposure) exposure=maxExposure;
if (autoExposureMax<minExposure) autoExposureMax=minExposure; else if (autoExposureMax>maxExposure) autoExposureMax=maxExposure;
if (gain<minGain) gain= minGain ; else if (gain> maxGain) gain= maxGain;
......@@ -645,9 +645,9 @@ public class LwirReader {
if (bScale<minScale) bScale= minScale ; else if (bScale> maxScale) bScale= maxScale;
if (gScale<minScale) gScale= minScale ; else if (gScale> maxScale) gScale= maxScale;
urls[num_lwir+chn] = "http://"+lrp.vnir_ip+"/parsedit.php?immediate&sensor_port="+chn+
urls[num_lwir+chn] = "http://"+lrp.eo_ip+"/parsedit.php?immediate&sensor_port="+chn+
"&COLOR="+COLOR_JP4+ // "*1"+ // JP4 always
"&QUALITY="+lrp.vnir_quality+ // "*0"+
"&QUALITY="+lrp.eo_quality+ // "*0"+
"&EXPOS="+exposure+ // "*0"+
"&AUTOEXP_EXP_MAX="+autoExposureMax+//"*0"+
"&AUTOEXP_ON="+autoExp+//"*0"+
......@@ -659,7 +659,7 @@ public class LwirReader {
"&DAEMON_EN_TEMPERATURE=1";//"*0";
if (chn == vnir_master_port) {
if (chn == eo_master_port) {
urls[num_lwir+chn] += "&TRIG=4*0"+
"&TRIG_CONDITION=611669*0"+ // external input
"&TRIG_BITLENGTH=31*0"+
......
......@@ -41,45 +41,45 @@ public class LwirReaderParameters {
protected boolean lwir_ffc = true;
protected boolean avg_all = true;
protected String lwir_ip = "192.168.0.36";
protected String vnir_ip = "192.168.0.38";
protected String eo_ip = "192.168.0.38";
protected int [] lwir_channels = {0, 1, 2 ,3};
protected int [] vnir_channels = {0, 1, 2 ,3};
protected int [] eo_channels = {0, 1, 2 ,3};
protected boolean lwir_telemetry = true;
protected double vnir_quality = 98.0;
protected boolean vnir_scale = false; // restore sensor pixel values, undo camera white balancing
protected boolean vnir_autoexp = false;
protected double vnir_max_autoexp_ms = 20.0;
protected double vnir_exposure_ms = 5.0;
protected boolean vnir_whitebal = false;
protected double vnir_gain_g = 2.0;
protected double vnir_gain_rg = 0.7705; // 1.116; halogen/fluorescent
protected double vnir_gain_bg = 2.401; // 1.476;
protected double eo_quality = 98.0;
protected boolean eo_scale = false; // restore sensor pixel values, undo camera white balancing
protected boolean eo_autoexp = false;
protected double eo_max_autoexp_ms = 20.0;
protected double eo_exposure_ms = 5.0;
protected boolean eo_whitebal = false;
protected double eo_gain_g = 2.0;
protected double eo_gain_rg = 0.7705; // 1.116; halogen/fluorescent
protected double eo_gain_bg = 2.401; // 1.476;
protected boolean [] selected_channels = {true, true, true, true, true, true, true, true};
protected int max_lwir_width = 1024; //
/*
protected double [] vnir_exp_corr = {1.0, 1.0, 1.0, 1.0};
protected double [] vnir_gcorr_rbgb = {
protected double [] eo_exp_corr = {1.0, 1.0, 1.0, 1.0};
protected double [] eo_gcorr_rbgb = {
1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0};
*/
protected double [] vnir_exp_corr = {
protected double [] eo_exp_corr = {
1.0, 1.0026, 0.9868, 1.0211};
protected double [] vnir_gcorr_rbgb = { // example after autobalance for 192.168.0.38 with halogen lamps
protected double [] eo_gcorr_rbgb = { // example after autobalance for 192.168.0.38 with halogen lamps
1.0, 1.0, 0.9743,
1.0668, 1.1055, 1.0006,
1.1533, 1.0780, 1.0015,
0.9966, 1.0445, 1.0023};
protected int lwir_trig_dly = 9000000; //in 100MHz clock cycle, current FPGA requires >0 (used 1000)
protected int vnir_lag = 2;//1; // frames
protected int eo_lag = 2;//1; // frames
protected double max_mismatch_ms = 0.05;
protected int max_frame_diff = 2;// 1; // 2;
protected int debug_level = 0;//-3: OFF, -2:Fatal, -1:ERROR, 0:WARN, 1:INFO,2:DEBUG
protected boolean show_images = false;
protected int lwir_chn0 = 0; // not configurable
protected int vnir_chn0 = 4; // not configurable
protected int eo_chn0 = 4; // not configurable
// --- interface methods
......@@ -87,8 +87,8 @@ public class LwirReaderParameters {
return lwir_chn0;
}
public int getVnirChn0 () {
return vnir_chn0;
public int getEoChn0 () {
return eo_chn0;
}
public boolean is_LWIR(int width) {
......@@ -115,23 +115,23 @@ public class LwirReaderParameters {
properties.setProperty(prefix+"lwir_ffc", this.lwir_ffc+"");
properties.setProperty(prefix+"avg_all", this.avg_all+"");
properties.setProperty(prefix+"lwir_ip", this.lwir_ip+"");
properties.setProperty(prefix+"vnir_ip", this.vnir_ip+"");
properties.setProperty(prefix+"eo_ip", this.eo_ip+"");
properties.setProperty(prefix+"lwir_channels", arr_to_str(this.lwir_channels));
properties.setProperty(prefix+"vnir_channels", arr_to_str(this.vnir_channels));
properties.setProperty(prefix+"eo_channels", arr_to_str(this.eo_channels));
properties.setProperty(prefix+"lwir_telemetry", this.lwir_telemetry+"");
properties.setProperty(prefix+"vnir_quality", this.vnir_quality+"");
properties.setProperty(prefix+"vnir_scale", this.vnir_scale+"");
properties.setProperty(prefix+"vnir_autoexp", this.vnir_autoexp+"");
properties.setProperty(prefix+"vnir_max_autoexp_ms", this.vnir_max_autoexp_ms+"");
properties.setProperty(prefix+"vnir_exposure_ms", this.vnir_exposure_ms+"");
properties.setProperty(prefix+"vnir_whitebal", this.vnir_whitebal+"");
properties.setProperty(prefix+"vnir_gain_g", this.vnir_gain_g+"");
properties.setProperty(prefix+"vnir_gain_rg", this.vnir_gain_rg+"");
properties.setProperty(prefix+"vnir_gain_bg", this.vnir_gain_bg+"");
properties.setProperty(prefix+"vnir_exp_corr", arr_to_str(this.vnir_exp_corr));
properties.setProperty(prefix+"vnir_gcorr_rbgb", arr_to_str(this.vnir_gcorr_rbgb));
properties.setProperty(prefix+"eo_quality", this.eo_quality+"");
properties.setProperty(prefix+"eo_scale", this.eo_scale+"");
properties.setProperty(prefix+"eo_autoexp", this.eo_autoexp+"");
properties.setProperty(prefix+"eo_max_autoexp_ms", this.eo_max_autoexp_ms+"");
properties.setProperty(prefix+"eo_exposure_ms", this.eo_exposure_ms+"");
properties.setProperty(prefix+"eo_whitebal", this.eo_whitebal+"");
properties.setProperty(prefix+"eo_gain_g", this.eo_gain_g+"");
properties.setProperty(prefix+"eo_gain_rg", this.eo_gain_rg+"");
properties.setProperty(prefix+"eo_gain_bg", this.eo_gain_bg+"");
properties.setProperty(prefix+"eo_exp_corr", arr_to_str(this.eo_exp_corr));
properties.setProperty(prefix+"eo_gcorr_rbgb", arr_to_str(this.eo_gcorr_rbgb));
properties.setProperty(prefix+"lwir_trig_dly", this.lwir_trig_dly+"");
properties.setProperty(prefix+"vnir_lag", this.vnir_lag+"");
properties.setProperty(prefix+"eo_lag", this.eo_lag+"");
properties.setProperty(prefix+"max_mismatch_ms", this.max_mismatch_ms+"");
properties.setProperty(prefix+"max_frame_diff", this.max_frame_diff+"");
properties.setProperty(prefix+"debug_level", this.debug_level+"");
......@@ -141,27 +141,42 @@ public class LwirReaderParameters {
}
public void getProperties(String prefix,Properties properties){
if (properties.getProperty(prefix+"vnir_ip")!=null) this.eo_ip= properties.getProperty(prefix+"vnir_ip");
if (properties.getProperty(prefix+"vnir_channels")!=null) this.eo_channels=str_to_iarr(properties.getProperty(prefix+"vnir_channels"));
if (properties.getProperty(prefix+"vnir_quality")!=null) this.eo_quality=Double.parseDouble(properties.getProperty(prefix+"vnir_quality"));
if (properties.getProperty(prefix+"vnir_scale")!=null) this.eo_scale= Boolean.parseBoolean(properties.getProperty(prefix+"vnir_scale"));
if (properties.getProperty(prefix+"vnir_autoexp")!=null) this.eo_autoexp= Boolean.parseBoolean(properties.getProperty(prefix+"vnir_autoexp"));
if (properties.getProperty(prefix+"vnir_max_autoexp_ms")!=null) this.eo_max_autoexp_ms=Double.parseDouble(properties.getProperty(prefix+"vnir_max_autoexp_ms"));
if (properties.getProperty(prefix+"vnir_exposure_ms")!=null) this.eo_exposure_ms=Double.parseDouble(properties.getProperty(prefix+"vnir_exposure_ms"));
if (properties.getProperty(prefix+"vnir_whitebal")!=null) this.eo_whitebal= Boolean.parseBoolean(properties.getProperty(prefix+"vnir_whitebal"));
if (properties.getProperty(prefix+"vnir_gain_g")!=null) this.eo_gain_g=Double.parseDouble(properties.getProperty(prefix+"vnir_gain_g"));
if (properties.getProperty(prefix+"vnir_gain_rg")!=null) this.eo_gain_rg=Double.parseDouble(properties.getProperty(prefix+"vnir_gain_rg"));
if (properties.getProperty(prefix+"vnir_gain_bg")!=null) this.eo_gain_bg=Double.parseDouble(properties.getProperty(prefix+"vnir_gain_bg"));
if (properties.getProperty(prefix+"vnir_exp_corr")!=null) this.eo_exp_corr=str_to_darr(properties.getProperty(prefix+"vnir_exp_corr"));
if (properties.getProperty(prefix+"vnir_gcorr_rbgb")!=null) this.eo_gcorr_rbgb=str_to_darr(properties.getProperty(prefix+"vnir_gcorr_rbgb"));
if (properties.getProperty(prefix+"vnir_lag")!=null) this.eo_lag=Integer.parseInt(properties.getProperty(prefix+"vnir_lag")); // old version
if (properties.getProperty(prefix+"avg_number")!=null) this.avg_number=Integer.parseInt(properties.getProperty(prefix+"avg_number"));
if (properties.getProperty(prefix+"lwir_ffc")!=null) this.lwir_ffc= Boolean.parseBoolean(properties.getProperty(prefix+"lwir_ffc"));
if (properties.getProperty(prefix+"avg_all")!=null) this.avg_all= Boolean.parseBoolean(properties.getProperty(prefix+"avg_all"));
if (properties.getProperty(prefix+"lwir_ip")!=null) this.lwir_ip= properties.getProperty(prefix+"lwir_ip");
if (properties.getProperty(prefix+"vnir_ip")!=null) this.vnir_ip= properties.getProperty(prefix+"vnir_ip");
if (properties.getProperty(prefix+"eo_ip")!=null) this.eo_ip= properties.getProperty(prefix+"eo_ip");
if (properties.getProperty(prefix+"lwir_channels")!=null) this.lwir_channels=str_to_iarr(properties.getProperty(prefix+"lwir_channels"));
if (properties.getProperty(prefix+"vnir_channels")!=null) this.vnir_channels=str_to_iarr(properties.getProperty(prefix+"vnir_channels"));
if (properties.getProperty(prefix+"eo_channels")!=null) this.eo_channels=str_to_iarr(properties.getProperty(prefix+"eo_channels"));
if (properties.getProperty(prefix+"lwir_telemetry")!=null) this.lwir_telemetry= Boolean.parseBoolean(properties.getProperty(prefix+"lwir_telemetry"));
if (properties.getProperty(prefix+"vnir_quality")!=null) this.vnir_quality=Double.parseDouble(properties.getProperty(prefix+"vnir_quality"));
if (properties.getProperty(prefix+"vnir_scale")!=null) this.vnir_scale= Boolean.parseBoolean(properties.getProperty(prefix+"vnir_scale"));
if (properties.getProperty(prefix+"vnir_autoexp")!=null) this.vnir_autoexp= Boolean.parseBoolean(properties.getProperty(prefix+"vnir_autoexp"));
if (properties.getProperty(prefix+"vnir_max_autoexp_ms")!=null) this.vnir_max_autoexp_ms=Double.parseDouble(properties.getProperty(prefix+"vnir_max_autoexp_ms"));
if (properties.getProperty(prefix+"vnir_exposure_ms")!=null) this.vnir_exposure_ms=Double.parseDouble(properties.getProperty(prefix+"vnir_exposure_ms"));
if (properties.getProperty(prefix+"vnir_whitebal")!=null) this.vnir_whitebal= Boolean.parseBoolean(properties.getProperty(prefix+"vnir_whitebal"));
if (properties.getProperty(prefix+"vnir_gain_g")!=null) this.vnir_gain_g=Double.parseDouble(properties.getProperty(prefix+"vnir_gain_g"));
if (properties.getProperty(prefix+"vnir_gain_rg")!=null) this.vnir_gain_rg=Double.parseDouble(properties.getProperty(prefix+"vnir_gain_rg"));
if (properties.getProperty(prefix+"vnir_gain_bg")!=null) this.vnir_gain_bg=Double.parseDouble(properties.getProperty(prefix+"vnir_gain_bg"));
if (properties.getProperty(prefix+"vnir_exp_corr")!=null) this.vnir_exp_corr=str_to_darr(properties.getProperty(prefix+"vnir_exp_corr"));
if (properties.getProperty(prefix+"vnir_gcorr_rbgb")!=null) this.vnir_gcorr_rbgb=str_to_darr(properties.getProperty(prefix+"vnir_gcorr_rbgb"));
if (properties.getProperty(prefix+"eo_quality")!=null) this.eo_quality=Double.parseDouble(properties.getProperty(prefix+"eo_quality"));
if (properties.getProperty(prefix+"eo_scale")!=null) this.eo_scale= Boolean.parseBoolean(properties.getProperty(prefix+"eo_scale"));
if (properties.getProperty(prefix+"eo_autoexp")!=null) this.eo_autoexp= Boolean.parseBoolean(properties.getProperty(prefix+"eo_autoexp"));
if (properties.getProperty(prefix+"eo_max_autoexp_ms")!=null) this.eo_max_autoexp_ms=Double.parseDouble(properties.getProperty(prefix+"eo_max_autoexp_ms"));
if (properties.getProperty(prefix+"eo_exposure_ms")!=null) this.eo_exposure_ms=Double.parseDouble(properties.getProperty(prefix+"eo_exposure_ms"));
if (properties.getProperty(prefix+"eo_whitebal")!=null) this.eo_whitebal= Boolean.parseBoolean(properties.getProperty(prefix+"eo_whitebal"));
if (properties.getProperty(prefix+"eo_gain_g")!=null) this.eo_gain_g=Double.parseDouble(properties.getProperty(prefix+"eo_gain_g"));
if (properties.getProperty(prefix+"eo_gain_rg")!=null) this.eo_gain_rg=Double.parseDouble(properties.getProperty(prefix+"eo_gain_rg"));
if (properties.getProperty(prefix+"eo_gain_bg")!=null) this.eo_gain_bg=Double.parseDouble(properties.getProperty(prefix+"eo_gain_bg"));
if (properties.getProperty(prefix+"eo_exp_corr")!=null) this.eo_exp_corr=str_to_darr(properties.getProperty(prefix+"eo_exp_corr"));
if (properties.getProperty(prefix+"eo_gcorr_rbgb")!=null) this.eo_gcorr_rbgb=str_to_darr(properties.getProperty(prefix+"eo_gcorr_rbgb"));
if (properties.getProperty(prefix+"lwir_trig_dly")!=null) this.lwir_trig_dly=Integer.parseInt(properties.getProperty(prefix+"lwir_trig_dly"));
if (properties.getProperty(prefix+"vnir_lag")!=null) this.vnir_lag=Integer.parseInt(properties.getProperty(prefix+"vnir_lag"));
if (properties.getProperty(prefix+"eo_lag")!=null) this.eo_lag=Integer.parseInt(properties.getProperty(prefix+"eo_lag"));
if (properties.getProperty(prefix+"max_mismatch_ms")!=null) this.max_mismatch_ms=Double.parseDouble(properties.getProperty(prefix+"max_mismatch_ms"));
if (properties.getProperty(prefix+"max_frame_diff")!=null) this.max_frame_diff=Integer.parseInt(properties.getProperty(prefix+"max_frame_diff"));
if (properties.getProperty(prefix+"debug_level")!=null) this.debug_level=Integer.parseInt(properties.getProperty(prefix+"debug_level"));
......@@ -176,23 +191,23 @@ public class LwirReaderParameters {
lrp.lwir_ffc= this.lwir_ffc;
lrp.avg_all= this.avg_all;
lrp.lwir_ip= this.lwir_ip;
lrp.vnir_ip= this.vnir_ip;
lrp.eo_ip= this.eo_ip;
lrp.lwir_channels= this.lwir_channels.clone();
lrp.vnir_channels= this.vnir_channels.clone();
lrp.eo_channels= this.eo_channels.clone();
lrp.lwir_telemetry= this.lwir_telemetry;
lrp.vnir_quality= this.vnir_quality;
lrp.vnir_scale= this.vnir_scale;
lrp.vnir_autoexp= this.vnir_autoexp;
lrp.vnir_max_autoexp_ms= this.vnir_max_autoexp_ms;
lrp.vnir_exposure_ms= this.vnir_exposure_ms;
lrp.vnir_whitebal= this.vnir_whitebal;
lrp.vnir_gain_g= this.vnir_gain_g;
lrp.vnir_gain_rg= this.vnir_gain_rg;
lrp.vnir_gain_bg= this.vnir_gain_bg;
lrp.vnir_exp_corr= this.vnir_exp_corr.clone();
lrp.vnir_gcorr_rbgb= this.vnir_gcorr_rbgb.clone();
lrp.eo_quality= this.eo_quality;
lrp.eo_scale= this.eo_scale;
lrp.eo_autoexp= this.eo_autoexp;
lrp.eo_max_autoexp_ms= this.eo_max_autoexp_ms;
lrp.eo_exposure_ms= this.eo_exposure_ms;
lrp.eo_whitebal= this.eo_whitebal;
lrp.eo_gain_g= this.eo_gain_g;
lrp.eo_gain_rg= this.eo_gain_rg;
lrp.eo_gain_bg= this.eo_gain_bg;
lrp.eo_exp_corr= this.eo_exp_corr.clone();
lrp.eo_gcorr_rbgb= this.eo_gcorr_rbgb.clone();
lrp.lwir_trig_dly= this.lwir_trig_dly;
lrp.vnir_lag= this.vnir_lag;
lrp.eo_lag= this.eo_lag;
lrp.max_mismatch_ms= this.max_mismatch_ms;
lrp.max_frame_diff= this.max_frame_diff;
lrp.debug_level= this.debug_level;
......@@ -214,23 +229,23 @@ public class LwirReaderParameters {
(lrp.lwir_ffc == this.lwir_ffc) &&
(lrp.avg_all == this.avg_all) &&
(lrp.lwir_ip.equals(this.lwir_ip)) &&
(lrp.vnir_ip.equals(this.vnir_ip)) &&
(lrp.eo_ip.equals(this.eo_ip)) &&
(java.util.Arrays.equals(lrp.lwir_channels, this.lwir_channels)) &&
(java.util.Arrays.equals(lrp.vnir_channels, this.vnir_channels)) &&
(java.util.Arrays.equals(lrp.eo_channels, this.eo_channels)) &&
(lrp.lwir_telemetry == this.lwir_telemetry) &&
(lrp.vnir_quality == this.vnir_quality) &&
(lrp.vnir_scale == this.vnir_scale) &&
(lrp.vnir_autoexp == this.vnir_autoexp) &&
(lrp.vnir_max_autoexp_ms == this.vnir_max_autoexp_ms) &&
(lrp.vnir_exposure_ms == this.vnir_exposure_ms) &&
(lrp.vnir_whitebal == this.vnir_whitebal) &&
(lrp.vnir_gain_g == this.vnir_gain_g) &&
(lrp.vnir_gain_rg == this.vnir_gain_rg) &&
(lrp.vnir_gain_bg == this.vnir_gain_bg) &&
(java.util.Arrays.equals(lrp.vnir_exp_corr, this.vnir_exp_corr)) &&
(java.util.Arrays.equals(lrp.vnir_gcorr_rbgb, this.vnir_gcorr_rbgb)) &&
(lrp.eo_quality == this.eo_quality) &&
(lrp.eo_scale == this.eo_scale) &&
(lrp.eo_autoexp == this.eo_autoexp) &&
(lrp.eo_max_autoexp_ms == this.eo_max_autoexp_ms) &&
(lrp.eo_exposure_ms == this.eo_exposure_ms) &&
(lrp.eo_whitebal == this.eo_whitebal) &&
(lrp.eo_gain_g == this.eo_gain_g) &&
(lrp.eo_gain_rg == this.eo_gain_rg) &&
(lrp.eo_gain_bg == this.eo_gain_bg) &&
(java.util.Arrays.equals(lrp.eo_exp_corr, this.eo_exp_corr)) &&
(java.util.Arrays.equals(lrp.eo_gcorr_rbgb, this.eo_gcorr_rbgb)) &&
(lrp.lwir_trig_dly == this.lwir_trig_dly) &&
(lrp.vnir_lag == this.vnir_lag) &&
(lrp.eo_lag == this.eo_lag) &&
(lrp.max_mismatch_ms == this.max_mismatch_ms) &&
(lrp.max_frame_diff == this.max_frame_diff) &&
(lrp.debug_level == this.debug_level) &&
......@@ -246,25 +261,25 @@ public class LwirReaderParameters {
result = prime * result + (lwir_ffc?1:0);
result = prime * result + (avg_all?1:0);
result = prime * result + lwir_ip.hashCode();
result = prime * result + vnir_ip.hashCode();
result = prime * result + eo_ip.hashCode();
result = prime * result + arr_to_str(lwir_channels).hashCode();
result = prime * result + arr_to_str(vnir_channels).hashCode();
result = prime * result + arr_to_str(eo_channels).hashCode();
result = prime * result + (lwir_telemetry?1:0);
result = prime * result + (new Double(vnir_quality)).hashCode();
result = prime * result + (vnir_scale?1:0);
result = prime * result + (vnir_autoexp?1:0);
result = prime * result + (new Double(vnir_max_autoexp_ms)).hashCode();
result = prime * result + (new Double(vnir_exposure_ms)).hashCode();
result = prime * result + (vnir_whitebal?1:0);
result = prime * result + (new Double(vnir_gain_g)).hashCode();
result = prime * result + (new Double(vnir_gain_rg)).hashCode();
result = prime * result + (new Double(vnir_gain_bg)).hashCode();
result = prime * result + arr_to_str(vnir_exp_corr).hashCode();
result = prime * result + arr_to_str(vnir_gcorr_rbgb).hashCode();
result = prime * result + (new Double(eo_quality)).hashCode();
result = prime * result + (eo_scale?1:0);
result = prime * result + (eo_autoexp?1:0);
result = prime * result + (new Double(eo_max_autoexp_ms)).hashCode();
result = prime * result + (new Double(eo_exposure_ms)).hashCode();
result = prime * result + (eo_whitebal?1:0);
result = prime * result + (new Double(eo_gain_g)).hashCode();
result = prime * result + (new Double(eo_gain_rg)).hashCode();
result = prime * result + (new Double(eo_gain_bg)).hashCode();
result = prime * result + arr_to_str(eo_exp_corr).hashCode();
result = prime * result + arr_to_str(eo_gcorr_rbgb).hashCode();
result = prime * result + (new Integer(lwir_trig_dly)).hashCode();
result = prime * result + arr_to_str(selected_channels).hashCode();
// next are not needed to be programmed to the cameras
// result = prime * result + (new Integer(vnir_lag)).hashCode();
// result = prime * result + (new Integer(eo_lag)).hashCode();
// result = prime * result + (new Double(max_mismatch_ms)).hashCode();
// result = prime * result + (new Integer(max_frame_diff)).hashCode();
return 0;
......@@ -275,23 +290,23 @@ public class LwirReaderParameters {
gd.addCheckbox ("Run FFC", this.lwir_ffc, "Perform calibration before each measurements to average (takes ~1.6 sec, 15 frames)");
gd.addCheckbox ("Average all", this.avg_all, "Average all simultaneously acquired images (unchecked - only requested number to average)");
gd.addStringField ("LWIR IP", this.lwir_ip, 20, "LWIR camera IP address");
gd.addStringField ("VNIR IP", this.vnir_ip, 20, "Visible range high resolution camera IP address");
gd.addStringField ("EO IP", this.eo_ip, 20, "Visible range high resolution camera IP address");
gd.addStringField ("LWIR channels", arr_to_str(this.lwir_channels), 20, "Space-separated list of used LWIR camera channels, such as '0 1 2 3'");
gd.addStringField ("VNIR channels", arr_to_str(this.vnir_channels), 20, "Space-separated list of used visible range camera channels, such as '0 1 2 3'");
gd.addStringField ("EO channels", arr_to_str(this.eo_channels), 20, "Space-separated list of used visible range camera channels, such as '0 1 2 3'");
gd.addCheckbox ("LWIR telemetry", this.lwir_telemetry, "Set LWIR sesnors to provide telemetry data in the last 2 lines (may become mandatory later)");
gd.addNumericField("VNIR quality", this.vnir_quality, 3,6,"%", "Visible range camera JPEG compression quality (all channels)");
gd.addCheckbox ("VNIR undo white balance", this.vnir_scale, "Undo in-camera white balancing");
gd.addCheckbox ("VNIR autoexposure", this.vnir_autoexp, "Enable autoexposure for the visible range camera");
gd.addNumericField("VNIR vnir_max_autoexp_ms", this.vnir_max_autoexp_ms, 3,6,"ms", "Visible range camera maximal exposure in autoexposure mode");
gd.addNumericField("VNIR exposure", this.vnir_exposure_ms, 3,6,"ms", "Visible range camera exposure time (all channels)");
gd.addCheckbox ("VNIR white balance", this.vnir_whitebal, "Enable automatic white balancing for the visible range camera");
gd.addNumericField("VNIR gain G", this.vnir_gain_g, 3,6,"","Analog gain for green channel for all visible range camera channels (normally 2.0)");
gd.addNumericField("VNIR gain R/G", this.vnir_gain_rg, 3,6,"","Red to green gain ratio for all visible range camera channels");
gd.addNumericField("VNIR gain B/G", this.vnir_gain_bg, 3,6,"","Blue to green gain ratio for all visible range camera channels");
gd.addStringField ("VNIR exposuere corrections", arr_to_str(this.vnir_exp_corr), 50, "Fine corrections of channel exposures (4 channel relative exposures)");
gd.addStringField ("VNIR gain corrections", arr_to_str(this.vnir_gcorr_rbgb), 100, "Fine corrections to per channel, per color gains:'r0 b0 gb0 r1 b1 gb1 ...'");
gd.addNumericField("LWIR trig dly", this.lwir_trig_dly, 0,10,"x10ns","Output trigger delay, should eventually match Lepton+FPGA latency to trigger VNIR exactly 1 frame after LWIR. 0 does not work with current FPGA - usec do not match sec in transmitted timestamp");
gd.addNumericField("VNIR lag", this.vnir_lag, 0,3,"","Visible camera lag (in frames) relative to LWIR one");
gd.addNumericField("EO quality", this.eo_quality, 3,6,"%", "Visible range camera JPEG compression quality (all channels)");
gd.addCheckbox ("EO undo white balance", this.eo_scale, "Undo in-camera white balancing");
gd.addCheckbox ("EO autoexposure", this.eo_autoexp, "Enable autoexposure for the visible range camera");
gd.addNumericField("EO eo_max_autoexp_ms", this.eo_max_autoexp_ms, 3,6,"ms", "Visible range camera maximal exposure in autoexposure mode");
gd.addNumericField("EO exposure", this.eo_exposure_ms, 3,6,"ms", "Visible range camera exposure time (all channels)");
gd.addCheckbox ("EO white balance", this.eo_whitebal, "Enable automatic white balancing for the visible range camera");
gd.addNumericField("EO gain G", this.eo_gain_g, 3,6,"","Analog gain for green channel for all visible range camera channels (normally 2.0)");
gd.addNumericField("EO gain R/G", this.eo_gain_rg, 3,6,"","Red to green gain ratio for all visible range camera channels");
gd.addNumericField("EO gain B/G", this.eo_gain_bg, 3,6,"","Blue to green gain ratio for all visible range camera channels");
gd.addStringField ("EO exposuere corrections", arr_to_str(this.eo_exp_corr), 50, "Fine corrections of channel exposures (4 channel relative exposures)");
gd.addStringField ("EO gain corrections", arr_to_str(this.eo_gcorr_rbgb), 100, "Fine corrections to per channel, per color gains:'r0 b0 gb0 r1 b1 gb1 ...'");
gd.addNumericField("LWIR trig dly", this.lwir_trig_dly, 0,10,"x10ns","Output trigger delay, should eventually match Lepton+FPGA latency to trigger EO exactly 1 frame after LWIR. 0 does not work with current FPGA - usec do not match sec in transmitted timestamp");
gd.addNumericField("EO lag", this.eo_lag, 0,3,"","Visible camera lag (in frames) relative to LWIR one");
gd.addNumericField("Max mismatch", this.max_mismatch_ms, 3,6,"ms","Maximal mismatch between image timestamps. Larger mismatch requires LWIR sinsor reinitialization");
gd.addNumericField("Max frame diff",this.max_frame_diff, 0,3,"","Maximal difference in frames between simultaneously acquired channels as calculated from the timestamps");
gd.addNumericField("Debug level", this.debug_level, 0,3,"","Image acquisition log level: -3: OFF, -2:FATAL, -1:ERROR, 0:WARN, 1:INFO, 2:DEBUG");
......@@ -304,23 +319,23 @@ public class LwirReaderParameters {
this.lwir_ffc = gd.getNextBoolean();
this.avg_all = gd.getNextBoolean();
this.lwir_ip = gd.getNextString();
this.vnir_ip = gd.getNextString();
this.eo_ip = gd.getNextString();
this.lwir_channels = str_to_iarr(gd.getNextString());
this.vnir_channels = str_to_iarr(gd.getNextString());
this.eo_channels = str_to_iarr(gd.getNextString());
this.lwir_telemetry = gd.getNextBoolean();
this.vnir_quality = gd.getNextNumber();
this.vnir_scale = gd.getNextBoolean();
this.vnir_autoexp = gd.getNextBoolean();
this.vnir_max_autoexp_ms = gd.getNextNumber();
this.vnir_exposure_ms = gd.getNextNumber();
this.vnir_whitebal = gd.getNextBoolean();
this.vnir_gain_g = gd.getNextNumber();
this.vnir_gain_rg = gd.getNextNumber();
this.vnir_gain_bg = gd.getNextNumber();
this.vnir_exp_corr = str_to_darr(gd.getNextString());
this.vnir_gcorr_rbgb = str_to_darr(gd.getNextString());
this.eo_quality = gd.getNextNumber();
this.eo_scale = gd.getNextBoolean();
this.eo_autoexp = gd.getNextBoolean();
this.eo_max_autoexp_ms = gd.getNextNumber();
this.eo_exposure_ms = gd.getNextNumber();
this.eo_whitebal = gd.getNextBoolean();
this.eo_gain_g = gd.getNextNumber();
this.eo_gain_rg = gd.getNextNumber();
this.eo_gain_bg = gd.getNextNumber();
this.eo_exp_corr = str_to_darr(gd.getNextString());
this.eo_gcorr_rbgb = str_to_darr(gd.getNextString());
this.lwir_trig_dly = (int) gd.getNextNumber();
this.vnir_lag = (int) gd.getNextNumber();
this.eo_lag = (int) gd.getNextNumber();
this.max_mismatch_ms = gd.getNextNumber();
this.max_frame_diff = (int) gd.getNextNumber();
this.debug_level = (int) gd.getNextNumber();
......@@ -361,7 +376,7 @@ public class LwirReaderParameters {
return sel;
}
public boolean [] getSelectedVnir(){
public boolean [] getSelectedEo(){
boolean [] sel = selected_channels.clone();
for (int i = 0; i < lwir_channels.length; i++ ) {
sel[i] = false;
......
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