Commit d811fafa authored by Andrey Filippov's avatar Andrey Filippov

implemented distorrtion model selection, image selection editor, different...

implemented distorrtion model selection, image selection editor, different maximal radius for grid match and adjustment
parent ae245e9a
......@@ -404,6 +404,7 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
1296.0, // double px0 // lens axis from sensor, horizontal, from left (pixels)
968.0, // double py0 // lens axis from sensor, vertical, from top (pixels)
true, // boolean flipVertical // acquired image is mirrored vertically (mirror used)
-1, // lensDistortionModel (use default)
null, // double [][] r_xy,
null // double [][] r_od
);
......@@ -1169,7 +1170,8 @@ if (MORE_BUTTONS) {
System.out.println("Number of enabled grid images: "+numImages[0]+
", of them new: "+numImages[1]+
", disabled without vignetting info: "+numImages[2]+
", disabled having less than "+minGridsNoPointer+" nodes and no matched pointers: "+numImages[3]);
", disabled having less than "+minGridsNoPointer+" nodes and no matched pointers: "+numImages[3]+
", disabled with no lasers and enableNoLaser==false (like 2 bottom cameras):" +numImages[4]);
if (DISTORTION_CALIBRATION_DATA.gIS==null) {
int numImageSets=DISTORTION_CALIBRATION_DATA.buildImageSets(false); // from scratch
......@@ -6062,7 +6064,7 @@ if (MORE_BUTTONS) {
gd.addNumericField("Minimal registered grid period as a fraction of maximal (to filter reflections)", 0.4,2); //was 0.7
gd.addCheckbox ("Reset orientation from the image with most pointers (false - only if it was not set yet)", overwriteAll);
gd.addCheckbox ("Disable (old) images without vignetting information", true);
gd.addNumericField("Minimal number of grids in no-pointer images and estimated orientation", 1000,0);
gd.addNumericField("Minimal number of grid nodes in no-pointer images and estimated orientation", 1000,0);
gd.showDialog();
if (gd.wasCanceled()) return;
boolean resetHinted= gd.getNextBoolean();
......@@ -6081,7 +6083,8 @@ if (MORE_BUTTONS) {
System.out.println("Number of enabled grid images: "+numImages[0]+
", of them new: "+numImages[1]+
", disabled without vignetting info: "+numImages[2]+
", disabled having less than "+minGridsNoPointer+" nodes and no matched pointers: "+numImages[3]);
", disabled having less than "+minGridsNoPointer+" nodes and no matched pointers: "+numImages[3]+
", disabled with no lasers and enableNoLaser==false (like 2 bottom cameras):" +numImages[4]);
if (DISTORTION_CALIBRATION_DATA.gIS==null) {
int numImageSets=DISTORTION_CALIBRATION_DATA.buildImageSets(false); // from scratch
if (DEBUG_LEVEL>0) System.out.println("Image set was empty, built a new one with "+numImageSets+" image sets (\"panoramas\"): ");
......
......@@ -38,6 +38,7 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.configuration.ConfigurationException;
......@@ -679,7 +680,14 @@ import org.apache.commons.configuration.XMLConfiguration;
if (this.eyesisCameraParameters.numStations>1){
sb.append("Station "+stationNumber+" W="+(100*this.eyesisCameraParameters.stationWeight[stationNumber])+"%"); for (int i=-1;i<numSubCameras;i++) sb.append("\t==="); sb.append("\n");
}
int [] lensDistortionModels=new int [numSubCameras];
for (int i=0;i<numSubCameras;i++) lensDistortionModels[i]=eyesisCameraParameters.getLensDistortionModel(stationNumber,i);
sb.append("Lens Distortion Model\t");
for (int i=0;i<numSubCameras;i++) sb.append("\t"+lensDistortionModels[i]);
sb.append("\n");
double [][] cameraPars=new double [numSubCameras][];
for (int i=0;i<numSubCameras;i++) cameraPars[i]=eyesisCameraParameters.getParametersVector(stationNumber,i);
// parameters same order as in this
for (int n=0;n<cameraPars[0].length;n++) if (isSubcameraParameter(n) && isIntrinsicParameter(n)){
......@@ -935,8 +943,10 @@ import org.apache.commons.configuration.XMLConfiguration;
}
}
int numNoVignetting=0;
int disabledNoLaser=0;
for (int i=0;i<this.gIP.length;i++){
int stationNumber=this.gIP[i].getStationNumber();
boolean enableNoLaser=this.eyesisCameraParameters.getEnableNoLaser(stationNumber,this.gIP[i].channel);
boolean wasEnabled=this.gIP[i].enabled;
if (resetHinted) this.gIP[i].hintedMatch=-1; // undefined
if (Double.isNaN(this.gIP[i].gridPeriod) ||
......@@ -949,15 +959,17 @@ import org.apache.commons.configuration.XMLConfiguration;
if (
(this.gIP[i].matchedPointers>=minPointers) ||
((this.gIP[i].matchedPointers>0) && (this.gIP[i].hintedMatch>0)) || // orientation and one pointer
(this.gIP[i].hintedMatch>1)) {
((this.gIP[i].hintedMatch>1) && enableNoLaser)) { // do not use bottom images w/o matched pointers
// before enabling - copy orientation from gIS
if (!this.gIP[i].enabled && (gIS_index[i]>=0)){
if (!Double.isNaN(this.gIS[gIS_index[i]].goniometerTilt)) setGH(i,this.gIS[gIS_index[i]].goniometerTilt );
if (!Double.isNaN(this.gIS[gIS_index[i]].goniometerAxial)) setGA(i,this.gIS[gIS_index[i]].goniometerAxial );
}
this.gIP[i].enabled=true;
} else this.gIP[i].enabled=false;
if ((this.gIP[i].hintedMatch>1) && !enableNoLaser && (this.gIP[i].matchedPointers==0)){
disabledNoLaser++;
}
else this.gIP[i].enabled=false;
}
if (disableNoVignetting) {
......@@ -977,7 +989,7 @@ import org.apache.commons.configuration.XMLConfiguration;
if (this.gIP[i].newEnabled) newEnabled++;
}
// may need buildImageSets
int [] result={numEnabled,newEnabled,numNoVignetting,notEnoughNodes};
int [] result={numEnabled,newEnabled,numNoVignetting,notEnoughNodes,disabledNoLaser};
return result;
}
// TODO:
......@@ -1277,7 +1289,26 @@ import org.apache.commons.configuration.XMLConfiguration;
return numEnabled;
}
int [] getStations(){
int [] result = new int [this.gIP.length];
for (int i=0;i<result.length;i++) result[i]=(this.gIP[i]!=null)?this.gIP[i].stationNumber:-1;
return result;
}
int [] getChannels(){
int [] result = new int [this.gIP.length];
for (int i=0;i<result.length;i++) result[i]=(this.gIP[i]!=null)?this.gIP[i].channel:-1;
return result;
}
int [] getMatchedPointers(){
int [] result = new int [this.gIP.length];
for (int i=0;i<result.length;i++) result[i]=(this.gIP[i]!=null)?this.gIP[i].matchedPointers:0;
return result;
}
int [] getHintedMatch(){
int [] result = new int [this.gIP.length];
for (int i=0;i<result.length;i++) result[i]=(this.gIP[i]!=null)?this.gIP[i].hintedMatch:-1;
return result;
}
boolean [] selectNewEnabled () {
boolean [] newEnabled=new boolean [this.gIP.length] ;
......@@ -1285,14 +1316,22 @@ import org.apache.commons.configuration.XMLConfiguration;
return newEnabled;
}
boolean [] selectEnabled () {
boolean [] enabled=new boolean [this.gIP.length] ;
for (int i=0;i<this.gIP.length;i++) enabled[i]= (this.gIP[i]!=null) && this.gIP[i].enabled;
return enabled;
}
boolean [] selectEstimated (boolean enabledOnly) {
boolean [] estimated=new boolean [getNumImages()];
if (this.gIS==null) {
String msg="Image sets are not initialized";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
// throw new IllegalArgumentException (msg);
Arrays.fill(estimated, true);
return estimated;
}
boolean [] estimated=new boolean [getNumImages()];
for (int i=0;i<estimated.length;i++) estimated[i]=false;
for (int i=0;i<this.gIS.length;i++) if (this.gIS[i].imageSet!=null){
for (int j=0;j<this.gIS[i].imageSet.length;j++) if (this.gIS[i].imageSet[j]!=null) {
......
......@@ -50,6 +50,7 @@ import Jama.Matrix;
// 1 - put commons-configuration-1.7.jar under ImageJ plugins directory (I used ImageJ-Elphel)
// 2 - in Eclipse project properties -> Build Path -> Libraries -> Add External jar
public class Distortions {
final public double hintedMaxRelativeRadius=1.2; // make adjustable?
private showDoubleFloatArrays SDFA_INSTANCE=new showDoubleFloatArrays(); // just for debugging?
// int numInputs=27; // with A8...// 24; // parameters in subcamera+...
// int numOutputs=16; // with A8...//13; // parameters in a single camera
......@@ -3010,12 +3011,25 @@ For each point in the image
* @param v grid V (signed, 0 in the center)
* @return [7] {pX,pY,grid mask (binary), grid R, grid G, grid B, alpha}
*/
public double [] reprojectGridNode(
LensDistortionParameters lensDistortionParameters,
int numImg,
int u, // grid signed u,v
int v
int v){
double maxRelativeRadius=this.hintedMaxRelativeRadius; // make adjustable
return reprojectGridNode(
lensDistortionParameters,
numImg,
u, // grid signed u,v
v,
maxRelativeRadius);
}
public double [] reprojectGridNode(
LensDistortionParameters lensDistortionParameters,
int numImg,
int u, // grid signed u,v
int v,
double maxRelativeRadius //=2.0;
){
int debugThreshold=1;
int nChn= this.fittingStrategy.distortionCalibrationData.gIP[numImg].channel;
......@@ -3035,6 +3049,7 @@ For each point in the image
XYZMP[0], // target point horizontal, positive - right, mm
XYZMP[1], // target point vertical, positive - down, mm
XYZMP[2], // target point horizontal, positive - away from camera, mm
maxRelativeRadius, //
false); // calculate derivatives, false - values only (NaN for behind points - only when false here)
if (Double.isNaN(pXY[0][0])) {
if (this.debugLevel>debugThreshold){
......@@ -3094,6 +3109,7 @@ For each point in the image
double goniometerAxial, // Axial
int imageSet,
boolean filterBorder){
double maxRelativeRadius=this.hintedMaxRelativeRadius; // make adjustable
int debugThreshold=2;
// Get parameter vector (22) for the selected sensor, current Eyesisparameters and specified orientation angles
double [] parVector=fittingStrategy.distortionCalibrationData.eyesisCameraParameters.getParametersVector(stationNumber,subCamera);
......@@ -3155,6 +3171,7 @@ For each point in the image
XYZM[0], // target point horizontal, positive - right, mm
XYZM[1], // target point vertical, positive - down, mm
XYZM[2], // target point horizontal, positive - away from camera, mm
maxRelativeRadius,
false); // calculate derivatives, false - values only (NaN for behind points - only when false here)
// verify the grid is inside the sensor area (may use sensor mask later too? probably not needed)
// Now NaN if point is behind the sensor
......@@ -5963,6 +5980,10 @@ List calibration
imp.setProperty("comment_entrancePupilForward", "entrance pupil distance from the azimuth/radius/height, outwards in mm");
imp.setProperty("entrancePupilForward", ""+entrancePupilForward); // currently global, decoders will use per-sensor
imp.setProperty("comment_defects", "Sensor hot/cold pixels list as x:y:difference");
imp.setProperty("comment_lensDistortionModel", "Integer specifying lens distrotion model (0 - radial)");
imp.setProperty("lensDistortionModel", ""+subCam.lensDistortionModel);
for (int i=0;i<subCam.r_xy.length;i++){
imp.setProperty("r_xy_"+i+"_x",subCam.r_xy[i][0]+"");
imp.setProperty("r_xy_"+i+"_y",subCam.r_xy[i][1]+"");
......@@ -6144,6 +6165,7 @@ List calibration
subCam.defectsDiff=null;
}
// non-radial
if (imp.getProperty("lensDistortionModel") !=null) subCam.lensDistortionModel= Integer.parseInt((String) imp.getProperty("lensDistortionModel"));
subCam.setDefaultNonRadial();
for (int i=0;i<subCam.r_xy.length;i++) {
if (imp.getProperty("r_xy_"+i+"_x") !=null) subCam.r_xy[i][0]= Double.parseDouble((String) imp.getProperty("r_xy_"+i+"_x"));
......@@ -9555,6 +9577,7 @@ M * V = B
System.out.println("this.lensDistortionParameters.distortionA="+IJ.d2s(this.lensDistortionParameters.distortionA, 5));
System.out.println("this.lensDistortionParameters.distortionB="+IJ.d2s(this.lensDistortionParameters.distortionB, 5));
System.out.println("this.lensDistortionParameters.distortionC="+IJ.d2s(this.lensDistortionParameters.distortionC, 5));
System.out.println("this.lensDistortionParameters.lensDistortionModel="+this.lensDistortionParameters.lensDistortionModel);
for (int i=0;i<this.lensDistortionParameters.r_xy.length;i++){
System.out.println("this.lensDistortionParameters.r_xy["+i+"][0]="+IJ.d2s(this.lensDistortionParameters.r_xy[i][0], 5));
System.out.println("this.lensDistortionParameters.r_xy["+i+"][1]="+IJ.d2s(this.lensDistortionParameters.r_xy[i][1], 5));
......@@ -9760,6 +9783,7 @@ M * V = B
if (reCenterVertically){
eyesisCameraParameters.recenterVertically(channelMask, stationMask);
for (int i=0;i<channelMask.length;i++) channelMask[i]= true;
parameterMask[distortionCalibrationData.getParameterIndexByName("subcamHeight")] = true;
}
......
This diff is collapsed.
......@@ -25,6 +25,8 @@ import java.util.Properties;
public class EyesisSubCameraParameters{
// origin is on the rotation axis of the tube body closest to the goniometer horizontal axis
public int lensDistortionModel=0;
public boolean enableNoLaser=true; // enable images for this channel w/o matched laser pointer
public double azimuth; // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
public double radius; // mm, distance from the rotation axis
public double height; // mm, up - from the origin point
......@@ -66,6 +68,8 @@ import java.util.Properties;
*/
public EyesisSubCameraParameters(
int lensDistortionModel,
boolean enableNoLaser,
double azimuth, // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
double radius, // mm, distance from the rotation axis
double height, // mm, up from the origin point
......@@ -88,6 +92,8 @@ import java.util.Properties;
double [][] r_od, // elongation for c,b,a,a5,a6,a7,a8
double channelWeightDefault
){
this.lensDistortionModel=lensDistortionModel;
this.enableNoLaser=enableNoLaser;
this.azimuth=azimuth;
this.radius=radius;
this.height=height;
......@@ -121,6 +127,8 @@ import java.util.Properties;
// defects are not cloned!
public EyesisSubCameraParameters clone() {
return new EyesisSubCameraParameters(
this.lensDistortionModel,
this.enableNoLaser,
this.azimuth,
this.radius,
this.height,
......@@ -152,6 +160,8 @@ import java.util.Properties;
}
// TODO: add/restore new properties
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"lensDistortionModel",this.lensDistortionModel+"");
properties.setProperty(prefix+"enableNoLaser",this.enableNoLaser+"");
properties.setProperty(prefix+"azimuth",this.azimuth+"");
properties.setProperty(prefix+"radius",this.radius+"");
properties.setProperty(prefix+"height",this.height+"");
......@@ -181,6 +191,11 @@ import java.util.Properties;
properties.setProperty(prefix+"channelWeightDefault",this.channelWeightDefault+"");
}
public void getProperties(String prefix,Properties properties){
getProperties(prefix,properties, -1);
}
public void getProperties(String prefix,Properties properties, int channel){
if (properties.getProperty(prefix+"lensDistortionModel")!=null)
this.lensDistortionModel=Integer.parseInt(properties.getProperty(prefix+"lensDistortionModel"));
if (properties.getProperty(prefix+"azimuth")!=null)
this.azimuth=Double.parseDouble(properties.getProperty(prefix+"azimuth"));
if (properties.getProperty(prefix+"radius")!=null)
......@@ -231,6 +246,13 @@ import java.util.Properties;
this.channelWeightDefault=Double.parseDouble(properties.getProperty(prefix+"channelWeightDefault"));
this.channelWeightCurrent=this.channelWeightDefault;
}
// /enableNoLaser
if (properties.getProperty(prefix+"enableNoLaser")!=null) {
this.enableNoLaser=Boolean.parseBoolean(properties.getProperty(prefix+"enableNoLaser"));
} else {
this.enableNoLaser=(channel<24);
}
}
public void setChannelWeightCurrent(
double weight){
......
This diff is collapsed.
......@@ -22,6 +22,9 @@ import Jama.Matrix;
final int numOutputs=42; //16; // with A8...//13; // parameters in a single camera
// final
// 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
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
......@@ -73,7 +76,22 @@ import Jama.Matrix;
// 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)
public void setDistortionModelParameters(){
if (lensDistortionModel<0){
System.out.println("BUG:setDistortionModelParameters() - lensDistortionModel<0");
lensDistortionModel=defaultLensDistortionModel;
}
this.cummulativeCorrection= (lensDistortionModel==101);
if (lensDistortionModel<100){
lensDistortionModelType=0;
} else if (lensDistortionModel<200){
lensDistortionModelType=1;
} else if (lensDistortionModel<300){
lensDistortionModelType=2;
} else {
lensDistortionModelType=0;
}
}
public LensDistortionParameters(
// LensDistortionParameters lensDistortionParameters,
boolean isTripod,
......@@ -116,6 +134,7 @@ import Jama.Matrix;
double px0, // center of the lens on the sensor, pixels
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_od
){
......@@ -140,6 +159,7 @@ import Jama.Matrix;
px0,
py0,
flipVertical,
lensDistortionModel,
r_xy,
r_od);
}
......@@ -166,6 +186,7 @@ import Jama.Matrix;
1296, // px0,
698, // py0,
true, // flipVertical,
-1, // lensDistortionModel
null, // r_xy,
null // r_od,
);
......@@ -192,6 +213,7 @@ import Jama.Matrix;
this.px0,
this.py0,
this.flipVertical,
this.lensDistortionModel,
this.r_xy,
this.r_od
);
......@@ -218,6 +240,7 @@ import Jama.Matrix;
double px0, // center of the lens on the sensor, pixels
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_od // per polynomial term orthogonal+diagonal elongation
){
......@@ -241,6 +264,7 @@ import Jama.Matrix;
this.px0=px0;
this.py0=py0;
this.flipVertical=flipVertical;
this.lensDistortionModel=(lensDistortionModel>=0)?lensDistortionModel:defaultLensDistortionModel;
if (r_xy==null) r_xy=r_xy_dflt;
if (r_od==null) r_od=r_od_dflt;
this.r_xy=new double [r_xy.length][2];
......@@ -273,6 +297,7 @@ import Jama.Matrix;
pars.px0, // center of the lens on the sensor, pixels
pars.py0, // center of the lens on the sensor, pixels
this.flipVertical, // (keep) acquired image is mirrored vertically (mirror used)
pars.lensDistortionModel,
pars.r_xy, // do not exist yet!
pars.r_od // do not exist yet!
);
......@@ -301,6 +326,7 @@ import Jama.Matrix;
ldp.px0,
ldp.py0,
ldp.flipVertical,
ldp.lensDistortionModel,
ldp.r_xy,
ldp.r_od);
}
......@@ -427,6 +453,7 @@ dPXmmc/dphi=
this.r_xyod[0][1]=0.0; // this.py0;
this.r_xyod[0][2]=this.r_od[0][0];
this.r_xyod[0][3]=this.r_od[0][1];
setDistortionModelParameters();
if (cummulativeCorrection){
for (int i=1;i<this.r_xyod.length;i++){
this.r_xyod[i][0]=this.r_xyod[i-1][0]+this.r_xy[i-1][0];
......@@ -911,13 +938,39 @@ dPXmmc/dphi=
}
}
}
public double [][] calcPartialDerivatives_old(
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
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?
boolean calculateAll){ // calculate derivatives, false - values only
switch (this.lensDistortionModelType){
case 0:
case 1:
return calcPartialDerivatives_type1(xp,yp,zp,maxRelativeRadius,calculateAll);
case 2:
return calcPartialDerivatives_type2(xp,yp,zp,maxRelativeRadius,calculateAll);
default:
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
double zp, // target point horizontal, positive - away from camera, mm
double maxRelativeRadius,
boolean calculateAll){ // calculate derivatives, false - values only
// this.cummulativeCorrection=false; // just debugging
final double maxRelativeRadius=2.0; // make configurable?
// 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
......@@ -1261,15 +1314,13 @@ dPXmmc/dphi=
return partDeriv;
}
public double [][] calcPartialDerivatives(
public double [][] calcPartialDerivatives_type2(
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,
boolean calculateAll){ // calculate derivatives, false - values only
// this.cummulativeCorrection=false; // just debugging
final double maxRelativeRadius=2.0; // make configurable?
// 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
......
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