Loading src/main/java/com/elphel/imagej/calibration/Aberration_Calibration.java +137 −61 Original line number Diff line number Diff line Loading @@ -1019,6 +1019,7 @@ if (MORE_BUTTONS) { addButton("LWIR grids", panelLWIR,color_process); addButton("Import Subsystem", panelLWIR,color_configure); addButton("Select LWIR grids", panelLWIR,color_configure); addButton("Grid offset", panelLWIR,color_process); addButton("Manual hint", panelLWIR,color_configure); add(panelLWIR); Loading Loading @@ -5921,7 +5922,7 @@ if (MORE_BUTTONS) { return; } GenericDialog gd=new GenericDialog ("Select list mode"); gd.addNumericField("Mode 0 - old, 1 - shift/Rots", 0, 0); gd.addNumericField("Mode 0 - pointers, 1 - shift/Rots, 2 - points/extra, 3 - rms", 0, 0); gd.showDialog(); if (gd.wasCanceled()) return; int listMode= (int) gd.getNextNumber(); Loading Loading @@ -9466,7 +9467,11 @@ if (MORE_BUTTONS) { return; } if (label.equals("Grid offset")) { DEBUG_LEVEL=MASTER_DEBUG_LEVEL; offsetGrids(0, 0, null); return; } /* ======================================================================== */ IJ.showMessage("Not yet implemented"); Loading @@ -9475,6 +9480,136 @@ if (MORE_BUTTONS) { } /* ===== Other methods ==================================================== */ public boolean offsetGrids(int ichoice, int inum, int [] uv_shift_rot) { 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; } boolean auto = false; if (uv_shift_rot == null) { uv_shift_rot = new int[3]; auto = true; } if (ichoice == 0) { auto = true; } boolean has_lwir = dcd.hasSmallSensors(); String [] choices_nolwir = {"-- please select --","Image number","Image set number"}; String [] choices_lwir = {"-- please select --","Image number","Image set number (all images)", "Image set (EO only)","Image set (LWIR only)"}; String [] choices = has_lwir ? choices_lwir : choices_nolwir; GenericDialog gd = new GenericDialog("Manually offset single grid or multiple grids in a set"); gd. addChoice("Next number is: ", choices, choices[ichoice]); gd.addNumericField("Image/set number", inum, 0); gd.addCheckbox ("Auto calculate UV", auto); if (has_lwir) { gd.addCheckbox ("Auto from EO grid", true); } gd.addNumericField("Grid offset U", uv_shift_rot[0], 0); gd.addNumericField("Grid offset V", uv_shift_rot[1], 0); gd.addNumericField("Grid offset Rot", uv_shift_rot[2], 0); gd.showDialog(); if (gd.wasCanceled()) return false; ichoice = gd.getNextChoiceIndex(); inum = (int) gd.getNextNumber(); auto = gd.getNextBoolean(); boolean auto_from_EO=false; if (has_lwir) { auto_from_EO = gd.getNextBoolean(); } uv_shift_rot[0] = (int) gd.getNextNumber(); uv_shift_rot[1] = (int) gd.getNextNumber(); uv_shift_rot[2] = (int) gd.getNextNumber(); if (ichoice == 0) { return offsetGrids(ichoice, inum, uv_shift_rot); } int ichoicemod = ichoice; if (auto && auto_from_EO) { if (ichoicemod > 1) { ichoicemod = 3; // adjust from high-res sensors } } int [] img_nums = null; switch (ichoicemod) { case 1: img_nums = new int [1]; img_nums[0] = inum; break; case 2: img_nums = new int [dcd.getNumChannels()]; for (int i = 0; i < img_nums.length; i++) { img_nums[i] = dcd.getImageNumber(inum, i); } break; case 3: img_nums = new int [dcd.getNumChannels()]; for (int i = 0; i < img_nums.length; i++) { img_nums[i] = dcd.getImageNumber(inum, i); if (dcd.isSmallSensor(img_nums[i])) { img_nums[i] = -1; } } break; case 4: img_nums = new int [dcd.getNumChannels()]; for (int i = 0; i < img_nums.length; i++) { img_nums[i] = dcd.getImageNumber(inum, i); if (!dcd.isSmallSensor(img_nums[i])) { img_nums[i] = -1; } } break; } if (auto) { // calculate suggested offset, re-run this method // 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) return offsetGrids(ichoice, inum, auto_uvr); } } } int [][] new_uv_shift_rots = new int [img_nums.length][]; for (int i = 0; i < img_nums.length; i++) if (img_nums[i] >=0) { new_uv_shift_rots[i] = dcd.offsetGrid( img_nums[i], // int img_num, uv_shift_rot, PATTERN_PARAMETERS); // PatternParameters patternParameters) } for (int i = 0; i < img_nums.length; i++) if (img_nums[i] >=0) { System.out.print(i+":"+img_nums[i]+" ("+dcd.getImageSet(img_nums[i])+")"); if (new_uv_shift_rots[i] != null) { System.out.println("U="+new_uv_shift_rots[i][0]+", V="+new_uv_shift_rots[i][1]+" (rot="+new_uv_shift_rots[i][2]+")"); } else { System.out.println("<null>"); } } return true; } public boolean selectLwirGrids(LwirReaderParameters lwirReaderParameters) { //DistortionProcessConfiguration DEBUG_LEVEL=MASTER_DEBUG_LEVEL; Loading Loading @@ -9571,20 +9706,6 @@ if (MORE_BUTTONS) { true, // boolean read_grids MASTER_DEBUG_LEVEL); /// if (MASTER_DEBUG_LEVEL <100) return true; // patterns are not yet read here! /* PATTERN_PARAMETERS.debugLevel=MASTER_DEBUG_LEVEL; EYESIS_CAMERA_PARAMETERS.updateNumstations (numStations); //if (MASTER_DEBUG_LEVEL==0) return; //TODO: Remove - just debugging DISTORTION_CALIBRATION_DATA=new DistortionCalibrationData( gridFileDirs, PATTERN_PARAMETERS, EYESIS_CAMERA_PARAMETERS, MASTER_DEBUG_LEVEL); */ LENS_DISTORTIONS.initImageSet( DISTORTION_CALIBRATION_DATA, EYESIS_CAMERA_PARAMETERS Loading @@ -9597,51 +9718,6 @@ if (MORE_BUTTONS) { } /* ======================================================================== */ /* if (label.equals("Select Grid Files")) { DEBUG_LEVEL=MASTER_DEBUG_LEVEL; LENS_DISTORTIONS=new Distortions(LENS_DISTORTION_PARAMETERS,PATTERN_PARAMETERS,REFINE_PARAMETERS,this.SYNC_COMMAND.stopRequested); String [] extensions={".tif",".tiff"}; CalibrationFileManagement.MultipleExtensionsFileFilter gridFilter = new CalibrationFileManagement.MultipleExtensionsFileFilter("grid",extensions,"Calibrated grid files"); 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", 1,0); gd.showDialog(); if (gd.wasCanceled()) return; int numStations= (int) gd.getNextNumber(); String [][] gridFiles= new String [numStations][]; for (int numStation=0;numStation<numStations;numStation++){ gridFiles[numStation]=CalibrationFileManagement.selectFiles(false, "Select Calibrated Grid Files for Station "+numStation+ "("+(numStation+1)+" of "+numStations+")", "Select", gridFilter, null); // String [] defaultPaths); if ((gridFiles[numStation]==null) || (gridFiles[numStation].length==0)) { if (!IJ.showMessageWithCancel("No files selected","Retry? (Cancel will abort the command)")) return; numStation--; } } PATTERN_PARAMETERS.debugLevel=MASTER_DEBUG_LEVEL; EYESIS_CAMERA_PARAMETERS.updateNumstations (numStations); //if (MASTER_DEBUG_LEVEL==0) return; //TODO: Remove - just debugging DISTORTION_CALIBRATION_DATA=new DistortionCalibrationData( gridFiles, PATTERN_PARAMETERS, EYESIS_CAMERA_PARAMETERS, MASTER_DEBUG_LEVEL); LENS_DISTORTIONS.initImageSet( DISTORTION_CALIBRATION_DATA, EYESIS_CAMERA_PARAMETERS ); // set initial orientation of the cameras from the sensors that see mpst of the matching pointers // just for the LMA to start DISTORTION_CALIBRATION_DATA.setInitialOrientation(true); return; } */ /* ======================================================================== */ // Add subcamera to the current system as a subsystem public boolean importSystem(String path, String prefix) { // use null to ask src/main/java/com/elphel/imagej/calibration/DistortionCalibrationData.java +186 −12 Original line number Diff line number Diff line Loading @@ -68,7 +68,7 @@ import ij.text.TextWindow; public static final int INDEX_R = 5; public static final int INDEX_G = 6; public static final int INDEX_B = 7; public static final double SMALL_FRACTION = 0.8; // consider sesnor to be a "small" if average grid period < this fraction of the large public static final double SMALL_FRACTION = 0.8; // consider sensor to be a "small" if average grid period < this fraction of the large public String pathName=null; public EyesisCameraParameters eyesisCameraParameters; // has "cartesian" Loading Loading @@ -247,7 +247,7 @@ import ij.text.TextWindow; double minContrast, double shrinkBlurSigma, double shrinkBlurLevel){ if (this.pixelsMask!=null) return; // need to reset ro re-calculate if (this.pixelsMask!=null) return; // need to reset to re-calculate if (this.pixelsUV==null) {this.pixelsMask=null; return; } if (this.pixelsUV.length==0){ this.pixelsMask=new double[0]; return; } Loading Loading @@ -316,7 +316,7 @@ import ij.text.TextWindow; public double [] GXYZ=new double [3]; //14 (12) coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system // this.GXYZ[stationNumber][1], //15 (13) y // this.GXYZ[stationNumber][2], //16 (14) z public boolean orientationEstimated=true; // orientation is estimated from other stes, notr adjusted by LMA public boolean orientationEstimated=true; // orientation is estimated from other stes, not adjusted by LMA public double setWeight=0.0; // weight of this set when calculating errors public void setEstimatedFromNonNaN(){ this.orientationEstimated= Double.isNaN(this.goniometerTilt) || Double.isNaN(this.goniometerAxial); Loading Loading @@ -733,7 +733,9 @@ import ij.text.TextWindow; this.gIS=null; // so it will be initialized in readAllGrids() readAllGrids( patternParameters, laserPointers); // prepare grid parameters for LMA laserPointers, // prepare grid parameters for LMA true); // boolean keep_images make it configurable parameter? // no orientation } Loading Loading @@ -1124,6 +1126,135 @@ if (sfiles == null) { } // 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) { int station = this.gIS[num_set].stationNumber; for (int ns = 0; ns < this.gIS.length; ns++) { if ( (this.gIS[ns].stationNumber == station) && (!non_estimated || !this.gIS[ns].orientationEstimated)) { for (int n=0;n<this.gIS[ns].imageSet.length;n++){ if ((this.gIS[ns].imageSet[n]!=null) && (this.gIS[ns].imageSet[n].matchedPointers > 0)){ return ns; } } } } return -1; // none found } // get XYZ for this set's station from marked grid public double [] getXYZFromMarked(int num_set, boolean non_estimated) { int ns = getMarkedSet(num_set, non_estimated); if (ns < 0) return null; 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 ( int num_img, boolean non_estimated, boolean even, PatternParameters patternParameters) { int num_set = this.gIP[num_img].setNumber; int station = this.gIS[num_set].stationNumber; 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); return 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]; 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])}; 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]}; if (parity !=0) { if (UV_err[1] > UV_err[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]--; } UV_err[0] = dUV[0] - idUV[0]; UV_err[1] = dUV[1] - idUV[1]; } System.out.println(String.format("Errors U/V = %.3f:%.3f",UV_err[0],UV_err[1])); return idUV; } public int [] offsetGrid( int img_num, int [] uv_shift_rot, PatternParameters patternParameters) { ImagePlus imp_grid = null; if (this.gIP[img_num].gridImage!=null){ // use in-memory grid images instead of the files int numGridImg=img_num; if (numGridImg>=this.gIP.length) numGridImg=this.gIP.length-1; imp_grid=this.gIP[numGridImg].gridImage; }else if (this.gIP[img_num].path != null) { imp_grid=(new Opener()).openImage("", this.gIP[img_num].path); if (imp_grid==null) { String msg="Failed to read grid file "+this.gIP[img_num].path; IJ.showMessage("Error",msg); throw new IllegalArgumentException (msg); } (new JP46_Reader_camera()).decodeProperiesFromInfo(imp_grid); } else { System.out.println("Grid is not in memory, file path is not specified"); return null; } 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 [] combinedUVShiftRot=MatchSimulatedPattern.combineUVShiftRot( this.gIP[img_num].getUVShiftRot(), uv_shift_rot); this.gIP[img_num].setUVShiftRot(combinedUVShiftRot); // uv_shift_rot); int [][] shiftRotMatrix= MatchSimulatedPattern.getRemapMatrix(this.gIP[img_num].getUVShiftRot()); setGridsWithRemap( // null immediately img_num, shiftRotMatrix, // int [][] reMap, pixels, patternParameters); calcGridPeriod(img_num, false); // centered, can skip _extra return this.gIP[img_num].getUVShiftRot(); } public static int getImagePlusProperty(ImagePlus imp, String name, int dflt) { try { dflt = Integer.parseInt((String) (imp.getProperty(name))); Loading Loading @@ -1480,19 +1611,23 @@ if (sfiles == null) { this.gIS=null; // so it will be created in readAllGrids() readAllGrids( patternParameters, // prepare grid parameters for LMA laserPointers); // laserPointers, // prepare grid parameters for LMA true); // boolean keep_images make it configurable parameter? // no orientation } public void listImageSet(){ listImageSet(0, null,null, null); listImageSet(0, null,null, null,null,null); } public void listImageSet( int mode, int [] numPoints, // All arrays may be twice long, then 1 - EO, second - LWIR double [] setRMS, boolean [] hasNaNInSet){ boolean [] hasNaNInSet, int [][] numImgPoints, double [][] rmsPerImg ){ if ((this.gIS==null) || (this.gIS.length==0)){ return; } Loading Loading @@ -1646,7 +1781,8 @@ if (sfiles == null) { if (this.gIS[i].imageSet[n]!=null){ int [] uvrot = this.gIS[i].imageSet[n].getUVShiftRot(); sb.append(uvrot[0]+":"+uvrot[1]+"("+uvrot[2]+")"); } else { sb.append("\t---"); } } break; Loading @@ -1655,7 +1791,22 @@ if (sfiles == null) { sb.append("\t"); if (this.gIS[i].imageSet[n]!=null){ sb.append(this.gIS[i].imageSet[n].pixelsXY.length+"+"+this.gIS[i].imageSet[n].pixelsXY_extra.length); } else { sb.append("\t---"); } } break; case 3: for (int n=0;n<this.gIS[i].imageSet.length;n++){ sb.append("\t"); if ((this.gIS[i].imageSet[n]!=null) && (numImgPoints!=null) && (rmsPerImg !=null)){ if (Double.isNaN(rmsPerImg[i][n])) { sb.append("NaN ("+numImgPoints[i][n]+")"); } else { sb.append(String.format("%.3f (%d)",rmsPerImg[i][n],numImgPoints[i][n])); } } else { sb.append("---"); } } break; Loading @@ -1664,6 +1815,8 @@ if (sfiles == null) { } new TextWindow("Image calibration state (pointers/hinted state)", header, sb.toString(), 900,1400); } /** * create list of image indices per image set * @return array of image indices for each image set Loading Loading @@ -2560,7 +2713,8 @@ if (sfiles == null) { } readAllGrids( patternParameters, // prepare grid parameters for LMA laserPointers); laserPointers, // prepare grid parameters for LMA true); // boolean keep_images make it configurable parameter? updateSetOrientation(null); // update orientation of image sets (built in readAllGrids() UPDATE - not anymore) } Loading Loading @@ -2912,7 +3066,8 @@ if (sfiles == null) { public boolean readAllGrids( PatternParameters patternParameters, LaserPointer laserPointers // as a backup if data is not available in the file LaserPointer laserPointers, // as a backup if data is not available in the file boolean keep_images ){ boolean disableNoFlatfield=false; // true only for processing transitional images - mixture of ff/ no-ff System.out.println("readAllGrids(), this.debugLevel="+this.debugLevel+" this.gIS is "+((this.gIS==null)?"null":"not null")); Loading Loading @@ -2942,6 +3097,9 @@ if (sfiles == null) { } // TODO: here - need to decode properties jp4_reader.decodeProperiesFromInfo(imp_grid); if (keep_images) { this.gIP[fileNumber].gridImage = imp_grid; } } this.gIP[fileNumber].laserPixelCoordinates=MatchSimulatedPattern.getPointersXYUV(imp_grid, laserPointers); this.gIP[fileNumber].motors=getMotorPositions(imp_grid, this.numMotors); Loading Loading @@ -3364,11 +3522,13 @@ if (sfiles == null) { return small_sensors; } public boolean isSmallSensor(int numImg) { if ((this.gIP != null) && (numImg < this.gIP.length) && (small_sensors != null)){ if ((this.gIP != null) && (numImg >= 0) && (numImg < this.gIP.length) && (small_sensors != null)){ return small_sensors[this.gIP[numImg].getChannel()]; } return false; } public double getSmallPeriodFrac() { return small_period_frac; } Loading Loading @@ -3766,6 +3926,19 @@ if (sfiles == null) { return len; } public int getImageNumber(int set_number, int sub_number) { if ((this.gIS== null) || (this.gIS.length <= set_number) || (this.gIS[set_number] == null)) return -1; if (sub_number >= getNumChannels()) return -1; if ((this.gIS[set_number].imageSet == null) || (this.gIS[set_number].imageSet[sub_number] == null)) return -1; return this.gIS[set_number].imageSet[sub_number].imgNumber; } public int getImageSet(int img_number) { if ((this.gIP== null) || (this.gIP.length <= img_number) || (img_number < 0) ||(this.gIP[img_number] == null)) return -1; return this.gIP[img_number].setNumber; } /** * * @param imgNumber number of grid image to edit parameters (location, distortion) for Loading Loading @@ -3831,6 +4004,7 @@ if (sfiles == null) { return nChn+1; } public double getMask(int chnNum, double px, double py){ int width= eyesisCameraParameters.getSensorWidth(chnNum)/eyesisCameraParameters.getDecimateMasks(chnNum); int height=eyesisCameraParameters.getSensorHeight(chnNum)/eyesisCameraParameters.getDecimateMasks(chnNum); Loading src/main/java/com/elphel/imagej/calibration/Distortions.java +18 −3 Original line number Diff line number Diff line Loading @@ -237,6 +237,10 @@ public class Distortions { } */ public DistortionCalibrationData getDistortionCalibrationData() { return (fittingStrategy == null)?null:fittingStrategy.distortionCalibrationData; } public void resetGridImageMasks(){ int numImg=fittingStrategy.distortionCalibrationData.getNumImages(); System.out.println("resetGridImageMasks()"); Loading Loading @@ -601,7 +605,7 @@ public class Distortions { } this.imageStartIndex[numImg]=index; // one after last if ((pass==1) && (numSeries>=0) && !skipMinVal){ // count non-zero weight nodes for each image, disable image if this number uis less than // count non-zero weight nodes for each image, disable image if this number is less than int needReCalc=0; for (int imgNum=0;imgNum<numImg;imgNum++) if (selectedImages[imgNum]) { index=this.imageStartIndex[imgNum]; Loading Loading @@ -784,6 +788,10 @@ public class Distortions { int [] numSetPoints=new int [imageSets.length*(hasLWIR?2:1)]; double [] rmsPerSet=new double[imageSets.length*(hasLWIR?2:1)]; int [][] numImgPoints=new int [imageSets.length][this.fittingStrategy.distortionCalibrationData.getNumSubCameras()]; double [][] rmsPerImg=new double[imageSets.length][this.fittingStrategy.distortionCalibrationData.getNumSubCameras()]; boolean [] hasNaNInSet=new boolean[imageSets.length*(hasLWIR?2:1)]; if (hasLWIR) { for (int setNum=0;setNum<imageSets.length;setNum++){ Loading @@ -795,6 +803,8 @@ public class Distortions { int imgNum=imageSets[setNum][imgInSet]; int isLwir = this.fittingStrategy.distortionCalibrationData.isSmallSensor(imgNum)?1:0; int num=numPairs[imgNum]; rmsPerImg[setNum][imgInSet] = errors[imgNum]; numImgPoints[setNum][imgInSet] = num; if (Double.isNaN(errors[imgNum])){ hasNaNInSet[2 * setNum + isLwir]=true; } else { Loading @@ -816,6 +826,8 @@ public class Distortions { for (int imgInSet=0;imgInSet<imageSets[setNum].length;imgInSet++) { int imgNum=imageSets[setNum][imgInSet]; int num=numPairs[imgNum]; rmsPerImg[setNum][imgInSet] = errors[imgNum]; numImgPoints[setNum][imgInSet] = num; if (Double.isNaN(errors[imgNum])){ hasNaNInSet[setNum]=true; } else { Loading @@ -831,7 +843,10 @@ public class Distortions { mode, numSetPoints, rmsPerSet, hasNaNInSet ); hasNaNInSet, numImgPoints, rmsPerImg ); // this.fittingStrategy.setImageSelection(0, oldSelection); // restore original selection in series 0 } Loading Loading @@ -4310,7 +4325,7 @@ List calibration if (this.debugLevel>0) System.out.println(" Removing imgages in image set "+numSet); for (int i=0;i<imageSets[numSet].length;i++){ int numImg=imageSets[numSet][i]; if (this.debugLevel>0) System.out.println(n+":"+i+" "+IJ.d2s(errors[numImg],3)+" "+ if (this.debugLevel>0) System.out.println(n+":"+i+"("+numImg+")"+IJ.d2s(errors[numImg],3)+" "+ this.fittingStrategy.distortionCalibrationData.gIP[numImg].path); this.fittingStrategy.distortionCalibrationData.gIP[numImg].enabled=false; this.fittingStrategy.distortionCalibrationData.gIP[numImg].hintedMatch=-1; // so can be re-calibrated again w/o others Loading Loading
src/main/java/com/elphel/imagej/calibration/Aberration_Calibration.java +137 −61 Original line number Diff line number Diff line Loading @@ -1019,6 +1019,7 @@ if (MORE_BUTTONS) { addButton("LWIR grids", panelLWIR,color_process); addButton("Import Subsystem", panelLWIR,color_configure); addButton("Select LWIR grids", panelLWIR,color_configure); addButton("Grid offset", panelLWIR,color_process); addButton("Manual hint", panelLWIR,color_configure); add(panelLWIR); Loading Loading @@ -5921,7 +5922,7 @@ if (MORE_BUTTONS) { return; } GenericDialog gd=new GenericDialog ("Select list mode"); gd.addNumericField("Mode 0 - old, 1 - shift/Rots", 0, 0); gd.addNumericField("Mode 0 - pointers, 1 - shift/Rots, 2 - points/extra, 3 - rms", 0, 0); gd.showDialog(); if (gd.wasCanceled()) return; int listMode= (int) gd.getNextNumber(); Loading Loading @@ -9466,7 +9467,11 @@ if (MORE_BUTTONS) { return; } if (label.equals("Grid offset")) { DEBUG_LEVEL=MASTER_DEBUG_LEVEL; offsetGrids(0, 0, null); return; } /* ======================================================================== */ IJ.showMessage("Not yet implemented"); Loading @@ -9475,6 +9480,136 @@ if (MORE_BUTTONS) { } /* ===== Other methods ==================================================== */ public boolean offsetGrids(int ichoice, int inum, int [] uv_shift_rot) { 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; } boolean auto = false; if (uv_shift_rot == null) { uv_shift_rot = new int[3]; auto = true; } if (ichoice == 0) { auto = true; } boolean has_lwir = dcd.hasSmallSensors(); String [] choices_nolwir = {"-- please select --","Image number","Image set number"}; String [] choices_lwir = {"-- please select --","Image number","Image set number (all images)", "Image set (EO only)","Image set (LWIR only)"}; String [] choices = has_lwir ? choices_lwir : choices_nolwir; GenericDialog gd = new GenericDialog("Manually offset single grid or multiple grids in a set"); gd. addChoice("Next number is: ", choices, choices[ichoice]); gd.addNumericField("Image/set number", inum, 0); gd.addCheckbox ("Auto calculate UV", auto); if (has_lwir) { gd.addCheckbox ("Auto from EO grid", true); } gd.addNumericField("Grid offset U", uv_shift_rot[0], 0); gd.addNumericField("Grid offset V", uv_shift_rot[1], 0); gd.addNumericField("Grid offset Rot", uv_shift_rot[2], 0); gd.showDialog(); if (gd.wasCanceled()) return false; ichoice = gd.getNextChoiceIndex(); inum = (int) gd.getNextNumber(); auto = gd.getNextBoolean(); boolean auto_from_EO=false; if (has_lwir) { auto_from_EO = gd.getNextBoolean(); } uv_shift_rot[0] = (int) gd.getNextNumber(); uv_shift_rot[1] = (int) gd.getNextNumber(); uv_shift_rot[2] = (int) gd.getNextNumber(); if (ichoice == 0) { return offsetGrids(ichoice, inum, uv_shift_rot); } int ichoicemod = ichoice; if (auto && auto_from_EO) { if (ichoicemod > 1) { ichoicemod = 3; // adjust from high-res sensors } } int [] img_nums = null; switch (ichoicemod) { case 1: img_nums = new int [1]; img_nums[0] = inum; break; case 2: img_nums = new int [dcd.getNumChannels()]; for (int i = 0; i < img_nums.length; i++) { img_nums[i] = dcd.getImageNumber(inum, i); } break; case 3: img_nums = new int [dcd.getNumChannels()]; for (int i = 0; i < img_nums.length; i++) { img_nums[i] = dcd.getImageNumber(inum, i); if (dcd.isSmallSensor(img_nums[i])) { img_nums[i] = -1; } } break; case 4: img_nums = new int [dcd.getNumChannels()]; for (int i = 0; i < img_nums.length; i++) { img_nums[i] = dcd.getImageNumber(inum, i); if (!dcd.isSmallSensor(img_nums[i])) { img_nums[i] = -1; } } break; } if (auto) { // calculate suggested offset, re-run this method // 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) return offsetGrids(ichoice, inum, auto_uvr); } } } int [][] new_uv_shift_rots = new int [img_nums.length][]; for (int i = 0; i < img_nums.length; i++) if (img_nums[i] >=0) { new_uv_shift_rots[i] = dcd.offsetGrid( img_nums[i], // int img_num, uv_shift_rot, PATTERN_PARAMETERS); // PatternParameters patternParameters) } for (int i = 0; i < img_nums.length; i++) if (img_nums[i] >=0) { System.out.print(i+":"+img_nums[i]+" ("+dcd.getImageSet(img_nums[i])+")"); if (new_uv_shift_rots[i] != null) { System.out.println("U="+new_uv_shift_rots[i][0]+", V="+new_uv_shift_rots[i][1]+" (rot="+new_uv_shift_rots[i][2]+")"); } else { System.out.println("<null>"); } } return true; } public boolean selectLwirGrids(LwirReaderParameters lwirReaderParameters) { //DistortionProcessConfiguration DEBUG_LEVEL=MASTER_DEBUG_LEVEL; Loading Loading @@ -9571,20 +9706,6 @@ if (MORE_BUTTONS) { true, // boolean read_grids MASTER_DEBUG_LEVEL); /// if (MASTER_DEBUG_LEVEL <100) return true; // patterns are not yet read here! /* PATTERN_PARAMETERS.debugLevel=MASTER_DEBUG_LEVEL; EYESIS_CAMERA_PARAMETERS.updateNumstations (numStations); //if (MASTER_DEBUG_LEVEL==0) return; //TODO: Remove - just debugging DISTORTION_CALIBRATION_DATA=new DistortionCalibrationData( gridFileDirs, PATTERN_PARAMETERS, EYESIS_CAMERA_PARAMETERS, MASTER_DEBUG_LEVEL); */ LENS_DISTORTIONS.initImageSet( DISTORTION_CALIBRATION_DATA, EYESIS_CAMERA_PARAMETERS Loading @@ -9597,51 +9718,6 @@ if (MORE_BUTTONS) { } /* ======================================================================== */ /* if (label.equals("Select Grid Files")) { DEBUG_LEVEL=MASTER_DEBUG_LEVEL; LENS_DISTORTIONS=new Distortions(LENS_DISTORTION_PARAMETERS,PATTERN_PARAMETERS,REFINE_PARAMETERS,this.SYNC_COMMAND.stopRequested); String [] extensions={".tif",".tiff"}; CalibrationFileManagement.MultipleExtensionsFileFilter gridFilter = new CalibrationFileManagement.MultipleExtensionsFileFilter("grid",extensions,"Calibrated grid files"); 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", 1,0); gd.showDialog(); if (gd.wasCanceled()) return; int numStations= (int) gd.getNextNumber(); String [][] gridFiles= new String [numStations][]; for (int numStation=0;numStation<numStations;numStation++){ gridFiles[numStation]=CalibrationFileManagement.selectFiles(false, "Select Calibrated Grid Files for Station "+numStation+ "("+(numStation+1)+" of "+numStations+")", "Select", gridFilter, null); // String [] defaultPaths); if ((gridFiles[numStation]==null) || (gridFiles[numStation].length==0)) { if (!IJ.showMessageWithCancel("No files selected","Retry? (Cancel will abort the command)")) return; numStation--; } } PATTERN_PARAMETERS.debugLevel=MASTER_DEBUG_LEVEL; EYESIS_CAMERA_PARAMETERS.updateNumstations (numStations); //if (MASTER_DEBUG_LEVEL==0) return; //TODO: Remove - just debugging DISTORTION_CALIBRATION_DATA=new DistortionCalibrationData( gridFiles, PATTERN_PARAMETERS, EYESIS_CAMERA_PARAMETERS, MASTER_DEBUG_LEVEL); LENS_DISTORTIONS.initImageSet( DISTORTION_CALIBRATION_DATA, EYESIS_CAMERA_PARAMETERS ); // set initial orientation of the cameras from the sensors that see mpst of the matching pointers // just for the LMA to start DISTORTION_CALIBRATION_DATA.setInitialOrientation(true); return; } */ /* ======================================================================== */ // Add subcamera to the current system as a subsystem public boolean importSystem(String path, String prefix) { // use null to ask
src/main/java/com/elphel/imagej/calibration/DistortionCalibrationData.java +186 −12 Original line number Diff line number Diff line Loading @@ -68,7 +68,7 @@ import ij.text.TextWindow; public static final int INDEX_R = 5; public static final int INDEX_G = 6; public static final int INDEX_B = 7; public static final double SMALL_FRACTION = 0.8; // consider sesnor to be a "small" if average grid period < this fraction of the large public static final double SMALL_FRACTION = 0.8; // consider sensor to be a "small" if average grid period < this fraction of the large public String pathName=null; public EyesisCameraParameters eyesisCameraParameters; // has "cartesian" Loading Loading @@ -247,7 +247,7 @@ import ij.text.TextWindow; double minContrast, double shrinkBlurSigma, double shrinkBlurLevel){ if (this.pixelsMask!=null) return; // need to reset ro re-calculate if (this.pixelsMask!=null) return; // need to reset to re-calculate if (this.pixelsUV==null) {this.pixelsMask=null; return; } if (this.pixelsUV.length==0){ this.pixelsMask=new double[0]; return; } Loading Loading @@ -316,7 +316,7 @@ import ij.text.TextWindow; public double [] GXYZ=new double [3]; //14 (12) coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system // this.GXYZ[stationNumber][1], //15 (13) y // this.GXYZ[stationNumber][2], //16 (14) z public boolean orientationEstimated=true; // orientation is estimated from other stes, notr adjusted by LMA public boolean orientationEstimated=true; // orientation is estimated from other stes, not adjusted by LMA public double setWeight=0.0; // weight of this set when calculating errors public void setEstimatedFromNonNaN(){ this.orientationEstimated= Double.isNaN(this.goniometerTilt) || Double.isNaN(this.goniometerAxial); Loading Loading @@ -733,7 +733,9 @@ import ij.text.TextWindow; this.gIS=null; // so it will be initialized in readAllGrids() readAllGrids( patternParameters, laserPointers); // prepare grid parameters for LMA laserPointers, // prepare grid parameters for LMA true); // boolean keep_images make it configurable parameter? // no orientation } Loading Loading @@ -1124,6 +1126,135 @@ if (sfiles == null) { } // 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) { int station = this.gIS[num_set].stationNumber; for (int ns = 0; ns < this.gIS.length; ns++) { if ( (this.gIS[ns].stationNumber == station) && (!non_estimated || !this.gIS[ns].orientationEstimated)) { for (int n=0;n<this.gIS[ns].imageSet.length;n++){ if ((this.gIS[ns].imageSet[n]!=null) && (this.gIS[ns].imageSet[n].matchedPointers > 0)){ return ns; } } } } return -1; // none found } // get XYZ for this set's station from marked grid public double [] getXYZFromMarked(int num_set, boolean non_estimated) { int ns = getMarkedSet(num_set, non_estimated); if (ns < 0) return null; 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 ( int num_img, boolean non_estimated, boolean even, PatternParameters patternParameters) { int num_set = this.gIP[num_img].setNumber; int station = this.gIS[num_set].stationNumber; 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); return 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]; 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])}; 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]}; if (parity !=0) { if (UV_err[1] > UV_err[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]--; } UV_err[0] = dUV[0] - idUV[0]; UV_err[1] = dUV[1] - idUV[1]; } System.out.println(String.format("Errors U/V = %.3f:%.3f",UV_err[0],UV_err[1])); return idUV; } public int [] offsetGrid( int img_num, int [] uv_shift_rot, PatternParameters patternParameters) { ImagePlus imp_grid = null; if (this.gIP[img_num].gridImage!=null){ // use in-memory grid images instead of the files int numGridImg=img_num; if (numGridImg>=this.gIP.length) numGridImg=this.gIP.length-1; imp_grid=this.gIP[numGridImg].gridImage; }else if (this.gIP[img_num].path != null) { imp_grid=(new Opener()).openImage("", this.gIP[img_num].path); if (imp_grid==null) { String msg="Failed to read grid file "+this.gIP[img_num].path; IJ.showMessage("Error",msg); throw new IllegalArgumentException (msg); } (new JP46_Reader_camera()).decodeProperiesFromInfo(imp_grid); } else { System.out.println("Grid is not in memory, file path is not specified"); return null; } 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 [] combinedUVShiftRot=MatchSimulatedPattern.combineUVShiftRot( this.gIP[img_num].getUVShiftRot(), uv_shift_rot); this.gIP[img_num].setUVShiftRot(combinedUVShiftRot); // uv_shift_rot); int [][] shiftRotMatrix= MatchSimulatedPattern.getRemapMatrix(this.gIP[img_num].getUVShiftRot()); setGridsWithRemap( // null immediately img_num, shiftRotMatrix, // int [][] reMap, pixels, patternParameters); calcGridPeriod(img_num, false); // centered, can skip _extra return this.gIP[img_num].getUVShiftRot(); } public static int getImagePlusProperty(ImagePlus imp, String name, int dflt) { try { dflt = Integer.parseInt((String) (imp.getProperty(name))); Loading Loading @@ -1480,19 +1611,23 @@ if (sfiles == null) { this.gIS=null; // so it will be created in readAllGrids() readAllGrids( patternParameters, // prepare grid parameters for LMA laserPointers); // laserPointers, // prepare grid parameters for LMA true); // boolean keep_images make it configurable parameter? // no orientation } public void listImageSet(){ listImageSet(0, null,null, null); listImageSet(0, null,null, null,null,null); } public void listImageSet( int mode, int [] numPoints, // All arrays may be twice long, then 1 - EO, second - LWIR double [] setRMS, boolean [] hasNaNInSet){ boolean [] hasNaNInSet, int [][] numImgPoints, double [][] rmsPerImg ){ if ((this.gIS==null) || (this.gIS.length==0)){ return; } Loading Loading @@ -1646,7 +1781,8 @@ if (sfiles == null) { if (this.gIS[i].imageSet[n]!=null){ int [] uvrot = this.gIS[i].imageSet[n].getUVShiftRot(); sb.append(uvrot[0]+":"+uvrot[1]+"("+uvrot[2]+")"); } else { sb.append("\t---"); } } break; Loading @@ -1655,7 +1791,22 @@ if (sfiles == null) { sb.append("\t"); if (this.gIS[i].imageSet[n]!=null){ sb.append(this.gIS[i].imageSet[n].pixelsXY.length+"+"+this.gIS[i].imageSet[n].pixelsXY_extra.length); } else { sb.append("\t---"); } } break; case 3: for (int n=0;n<this.gIS[i].imageSet.length;n++){ sb.append("\t"); if ((this.gIS[i].imageSet[n]!=null) && (numImgPoints!=null) && (rmsPerImg !=null)){ if (Double.isNaN(rmsPerImg[i][n])) { sb.append("NaN ("+numImgPoints[i][n]+")"); } else { sb.append(String.format("%.3f (%d)",rmsPerImg[i][n],numImgPoints[i][n])); } } else { sb.append("---"); } } break; Loading @@ -1664,6 +1815,8 @@ if (sfiles == null) { } new TextWindow("Image calibration state (pointers/hinted state)", header, sb.toString(), 900,1400); } /** * create list of image indices per image set * @return array of image indices for each image set Loading Loading @@ -2560,7 +2713,8 @@ if (sfiles == null) { } readAllGrids( patternParameters, // prepare grid parameters for LMA laserPointers); laserPointers, // prepare grid parameters for LMA true); // boolean keep_images make it configurable parameter? updateSetOrientation(null); // update orientation of image sets (built in readAllGrids() UPDATE - not anymore) } Loading Loading @@ -2912,7 +3066,8 @@ if (sfiles == null) { public boolean readAllGrids( PatternParameters patternParameters, LaserPointer laserPointers // as a backup if data is not available in the file LaserPointer laserPointers, // as a backup if data is not available in the file boolean keep_images ){ boolean disableNoFlatfield=false; // true only for processing transitional images - mixture of ff/ no-ff System.out.println("readAllGrids(), this.debugLevel="+this.debugLevel+" this.gIS is "+((this.gIS==null)?"null":"not null")); Loading Loading @@ -2942,6 +3097,9 @@ if (sfiles == null) { } // TODO: here - need to decode properties jp4_reader.decodeProperiesFromInfo(imp_grid); if (keep_images) { this.gIP[fileNumber].gridImage = imp_grid; } } this.gIP[fileNumber].laserPixelCoordinates=MatchSimulatedPattern.getPointersXYUV(imp_grid, laserPointers); this.gIP[fileNumber].motors=getMotorPositions(imp_grid, this.numMotors); Loading Loading @@ -3364,11 +3522,13 @@ if (sfiles == null) { return small_sensors; } public boolean isSmallSensor(int numImg) { if ((this.gIP != null) && (numImg < this.gIP.length) && (small_sensors != null)){ if ((this.gIP != null) && (numImg >= 0) && (numImg < this.gIP.length) && (small_sensors != null)){ return small_sensors[this.gIP[numImg].getChannel()]; } return false; } public double getSmallPeriodFrac() { return small_period_frac; } Loading Loading @@ -3766,6 +3926,19 @@ if (sfiles == null) { return len; } public int getImageNumber(int set_number, int sub_number) { if ((this.gIS== null) || (this.gIS.length <= set_number) || (this.gIS[set_number] == null)) return -1; if (sub_number >= getNumChannels()) return -1; if ((this.gIS[set_number].imageSet == null) || (this.gIS[set_number].imageSet[sub_number] == null)) return -1; return this.gIS[set_number].imageSet[sub_number].imgNumber; } public int getImageSet(int img_number) { if ((this.gIP== null) || (this.gIP.length <= img_number) || (img_number < 0) ||(this.gIP[img_number] == null)) return -1; return this.gIP[img_number].setNumber; } /** * * @param imgNumber number of grid image to edit parameters (location, distortion) for Loading Loading @@ -3831,6 +4004,7 @@ if (sfiles == null) { return nChn+1; } public double getMask(int chnNum, double px, double py){ int width= eyesisCameraParameters.getSensorWidth(chnNum)/eyesisCameraParameters.getDecimateMasks(chnNum); int height=eyesisCameraParameters.getSensorHeight(chnNum)/eyesisCameraParameters.getDecimateMasks(chnNum); Loading
src/main/java/com/elphel/imagej/calibration/Distortions.java +18 −3 Original line number Diff line number Diff line Loading @@ -237,6 +237,10 @@ public class Distortions { } */ public DistortionCalibrationData getDistortionCalibrationData() { return (fittingStrategy == null)?null:fittingStrategy.distortionCalibrationData; } public void resetGridImageMasks(){ int numImg=fittingStrategy.distortionCalibrationData.getNumImages(); System.out.println("resetGridImageMasks()"); Loading Loading @@ -601,7 +605,7 @@ public class Distortions { } this.imageStartIndex[numImg]=index; // one after last if ((pass==1) && (numSeries>=0) && !skipMinVal){ // count non-zero weight nodes for each image, disable image if this number uis less than // count non-zero weight nodes for each image, disable image if this number is less than int needReCalc=0; for (int imgNum=0;imgNum<numImg;imgNum++) if (selectedImages[imgNum]) { index=this.imageStartIndex[imgNum]; Loading Loading @@ -784,6 +788,10 @@ public class Distortions { int [] numSetPoints=new int [imageSets.length*(hasLWIR?2:1)]; double [] rmsPerSet=new double[imageSets.length*(hasLWIR?2:1)]; int [][] numImgPoints=new int [imageSets.length][this.fittingStrategy.distortionCalibrationData.getNumSubCameras()]; double [][] rmsPerImg=new double[imageSets.length][this.fittingStrategy.distortionCalibrationData.getNumSubCameras()]; boolean [] hasNaNInSet=new boolean[imageSets.length*(hasLWIR?2:1)]; if (hasLWIR) { for (int setNum=0;setNum<imageSets.length;setNum++){ Loading @@ -795,6 +803,8 @@ public class Distortions { int imgNum=imageSets[setNum][imgInSet]; int isLwir = this.fittingStrategy.distortionCalibrationData.isSmallSensor(imgNum)?1:0; int num=numPairs[imgNum]; rmsPerImg[setNum][imgInSet] = errors[imgNum]; numImgPoints[setNum][imgInSet] = num; if (Double.isNaN(errors[imgNum])){ hasNaNInSet[2 * setNum + isLwir]=true; } else { Loading @@ -816,6 +826,8 @@ public class Distortions { for (int imgInSet=0;imgInSet<imageSets[setNum].length;imgInSet++) { int imgNum=imageSets[setNum][imgInSet]; int num=numPairs[imgNum]; rmsPerImg[setNum][imgInSet] = errors[imgNum]; numImgPoints[setNum][imgInSet] = num; if (Double.isNaN(errors[imgNum])){ hasNaNInSet[setNum]=true; } else { Loading @@ -831,7 +843,10 @@ public class Distortions { mode, numSetPoints, rmsPerSet, hasNaNInSet ); hasNaNInSet, numImgPoints, rmsPerImg ); // this.fittingStrategy.setImageSelection(0, oldSelection); // restore original selection in series 0 } Loading Loading @@ -4310,7 +4325,7 @@ List calibration if (this.debugLevel>0) System.out.println(" Removing imgages in image set "+numSet); for (int i=0;i<imageSets[numSet].length;i++){ int numImg=imageSets[numSet][i]; if (this.debugLevel>0) System.out.println(n+":"+i+" "+IJ.d2s(errors[numImg],3)+" "+ if (this.debugLevel>0) System.out.println(n+":"+i+"("+numImg+")"+IJ.d2s(errors[numImg],3)+" "+ this.fittingStrategy.distortionCalibrationData.gIP[numImg].path); this.fittingStrategy.distortionCalibrationData.gIP[numImg].enabled=false; this.fittingStrategy.distortionCalibrationData.gIP[numImg].hintedMatch=-1; // so can be re-calibrated again w/o others Loading