This function uses the corners from a grid positioned in several different orientations within a stereo camera setup to estimate the DLT calibration coefficients that minimize reconstruction error.
dltCalibrateCameras(coor.2d, nx, grid.size, c.run = FALSE, reduce.grid.dim = 3,
fit.min.break = 1, nlm.iter.max.init = 100, objective.min.init = 10,
nlm.eval.max = 350, nlm.iter.max = 250, nlm.calls.max = 100,
min.views = 'max', objective.min = 1, grid.incl.min=2,
objective.min.break = NULL, start.param=NULL,
sx = NULL, sy = NULL, print.progress = FALSE, print.tab = '')# S3 method for dltCalibrateCameras
summary(object, ...)
a four-dimensional array of grid points. The first two dimensions correspond to each matrix of grid points, the third corresponds to each grid position/orientation and the fourth corresponds to each camera view. Can be read from file by the function readCheckerboardsToArray
.
the number of points along the first dimension (e.g. this would be the number of points in each row if points in coor.2d
are listed first by row). The number of points along the second dimension is calculated based on the total number of points per view and orientation.
the size of the grid squares in real-world units (e.g. millimeters).
a logical indicating whether a second optimization should be performed on the calibration coefficients.
a numeric indicating the number of grid points along each dimension for each grid after resampling. The total number of resampled points is reduce.grid.dim^2
. Resampling can be turned off by setting this to 0
or FALSE
. The default is recommended. reduce.grid.dim
must be greater than two.
passed to resampleGridImagePoints()
. A minimum returned by nlminb()
(indicating goodness of fit in pixel coordinates) at which resampleGridImagePoints()
will stop iterating to find a better fit for each checkerboard grid. Ignored if reduce.grid.dim
is 0
or FALSE
.
The maximum number of iterations to be performed by nlminb()
during initial coefficient optimization, passed as a control parameter to nlminb()
. These are the number of iterations for an initial determination of whether the function is likely to converge on the correct estimate.
The objective used during the initial coefficient optimization, passed as a control parameter to nlminb()
, to determine whether the function is close to convergence.
The maximum number of evaluations to be performed by nlminb()
during primary coefficient optimization, passed as a control parameter to nlminb()
. Keeping this value as low as possible without excluding actual convergence speeds performance of the function by preventing the function from stalling far from the optimal values.
The maximum number of iterations to be performed by nlminb()
during primary coefficient optimization, passed as a control parameter to nlminb()
. Keeping this value as low as possible without excluding actual convergence speeds performance of the function by preventing the function from stalling far from the optimal values.
The maximum number of different sets of random starting parameters to use during coefficient optimization. This parameter cannot exceed 576.
The minimum views in which corners must be detected in order to use in coefficient estimation. If set to 'max' (default) this will be equal to the number of input views.
The expected mean reconstruction error when optimizing the calibration coefficients (the minimum, or objective
value returned by nlminb()
). A value between 0.7 and 3 should be reasonable.
The minimum number of grids to include during coefficient optimization.
During coefficient optimization if the error (in pixels) always exceeds this value the estimation will stop estimating the position of additional checkerboards.
An set of fixed starting parameters to be used during coefficient optimization. This parameter is intended primarily for debugging.
Used for de-bugging.
Used for de-bugging.
a logical indicating whether the progress of the function should be printed while running. This includes the error in grid re-sampling, an iteration count during optimization and other outputs relating to the optimization.
Tabs preceding lines printed to console.
a list of class "dltCalibrateCameras"
(the output of dltCalibrateCameras()
).
further arguments passed to or from other methods.
a list of class "dltCalibrateCameras"
with the following elements:
a matrix of 11 optimized DLT calibration coefficients per camera view.
the optimized 3D coordinates of the input grid points in coor.2d
.
the RMS error when coor.2d
and the optimized calibration coefficients cal.coeff
are input to dltReconstruct
.
the RMS error when coor.2d
and the optimized 3D coordinates coor.3d
are input to dltCoefficients
.
the final transformation parameters reported by nlminb()
from the first optimization. 't.'
refers to the transformation optimization.
the minimum reported by nlminb()
from the first optimization. This is the mean RMS error across all camera views returned by dltCoefficients
for the downsampled grid points.
the run-time (in seconds) for the first optimization.
the initial parameters for the second optimization. 'c.'
refers to the coefficient optimization.
the final parameters reported by nlminb()
from the second optimization.
the minimum reported by nlminb()
from the second optimization. This is the mean RMS error across all camera views returned by dltReconstruct
.
the number of iterations reported by nlminb()
from the second optimization.
the run-time (in seconds) for the second optimization.
Calibration is the most challenging step in stereo camera data collection. Most fundamentally, DLT calibration requires a set of 3D coordinates and their corresponding 2D pixel coordinates in each camera view in order to derive calibration coefficients (see dltCoefficients
). These coefficients can then be used to reconstruct any point in 3D given its 2D pixel coordinates in two or more camera views. DLT calibration has traditionally been done using a "calibration object", typically a 3D box-shaped structure filled with markers at known 3D positions. Such objects require the use of high precision machining in order to achieve an accurate calibration and the calibration points are usually digitized manually.
The dltCalibrateCameras()
function provides a camera calibration routine that is easier to implement and potentially more accurate. This function uses the corners from a grid positioned in several different orientations within the calibration space to estimate the DLT calibration coefficients that minimize reconstruction error. The easiest method for obtaining these corner points is to print a checkerboard pattern (using drawCheckerboard
), attach the pattern to flat, hard surface and use findCheckerboardCorners
to automatically extract the pixel coordinates of the internal corners.
The grid pattern should be photographed in at least four different positions and orientations spanning the volume to be calibrated (the tutorial files loaded with StereoMorph include eight different positions). Using only a couple of positions will result in uneven sampling of the calibration volume causing larger errors in some regions relative to others. Additionally, using only a single orientation of the checkerboard will produce higher errors along a particular dimension relative to the others. Once the pixel coordinates of the grid points (e.g. the internal corners of the checkerboard pattern) have been extracted from all of the calibration images, they should be read into an array using readCheckerboardsToArray
. This function allows for the point order to be reversed along rows, columns or both. If one of the cameras views the pattern upside down relative to another camera or if the pattern is in a different orientation, the grid points may be extracted in a different order. This can be fixed using the row.reverse
and col.reverse
arguments in readCheckerboardsToArray
. It is essential that the grid points extracted from each camera view correspond to each other row-by-row or else the calibration will not work.
dltCalibrateCameras()
first calls resampleGridImagePoints
to downsample the number of grid points. reduce.grid.dim
is the downsample number (the default is 3, meaning 3x3 or nine points per grid). Downsampling can be turned off by setting reduce.grid.dim
to 0
, although this is not recommended as it will increase run-time substantially without increasing accuracy. A camera perspective model is fit to the full point set such that the number of points input to the coefficient optimization can be reduced (thereby reducing run-time) without losing any relevant information (see resampleGridImagePoints
). If print.progress
is set to TRUE
, the mean and maximum fit error is printed for each input grid. As the fitting does not take into account lens distortion, high fit errors may indicate large distortional effects.
Since each checkerboard grid has been photographed in an arbitrary position and orientation, the 3D coordinates of the grid points are unknown. However, if the first grid is fixed, each additional grid can be described by applying six transformation parameters relative to the first (three translational and three rotational). Using the reduced grid point set, dltCalibrateCameras()
uses nlminb()
to search for the six transformation parameters per grid that minimizes the RMS error when the 3D coordinates are input (with the corresponding 2D coordinates) to dltCoefficients
. In effect, dltCalibrateCameras()
solves for the position of each grid in 3D space using the error from dltCoefficients
as an optimality criterion. Since the first grid is fixed, the optimization will search for 6*(n-1) parameters, where n is the number of separate grid orientations. nlminb()
calls the function dltTransformationParameterRMSError
.
In order to fully explore the parameter space, dltCalibrateCameras()
calls nlminb()
several times with a different set of randomly generated starting parameters to estimate the transformation parameters for each additional grid. The number of different sets of starting parameters is determined by nlm.calls.max
. An initial optimization run is intended to quickly determine whether a particular set of starting parameters is likely to lead to convergence. The number of iterations for this initial optimization is determined by nlm.iter.max.init
and the objective used in determining likely convergence is objective.min.init
. If it is determined that the starting parameters are likely to lead to convergence below objective.min
, nlminb()
is allowed to continue optimizing. For each grid, the solution yielding the lowest error, or the first solution below the objective.min
threshold, is retained for the next grid optimization.
These optimal transformation parameters are then used to obtain the 3D coordinates of the original grid points (not downsampled). Once these 3D coordinates are known, the 3D and 2D pixel coordinates are input to dltCoefficients
to obtain the 11 calibration coefficients per camera. For this reason, the calibration coefficient RMS Error (coefficient.rmse
) returned will differ slightly from the reported final nlminb()
minimum (t.min
).
If c.run
is set to TRUE
, dltCalibrateCameras()
performs a second optimization on the calibration coefficients themselves. nlminb()
is used, this time calling dltCoefficientRMSError
, to find the 11 calibration coefficients per view that minimizes the reconstruction RMS error. Note that dltCoefficients
cannot be used as with the previous optimization because the coefficients must be an input. Running this second optimization seems to have little effect in increasing the accuracy of the calibration but is included as this may be useful for some stereo setups.
For a general overview of DLT: http://kwon3d.com/theory/dlt/dlt.html
dltTestCalibration
,
dltCoefficients
,
readCheckerboardsToArray
,
transformPlanarCalibrationCoordinates
,
dltTransformationParameterRMSError
,
# NOT RUN {
## SET NUMBER OF INTERNAL CORNERS FOR CALIBRATION GRIDS
nx <- 21
ny <- 14
## GET THE FILE DIRECTORY FOR EXTRA R PACKAGE FILES
fdir <- paste0(path.package("StereoMorph"), "/extdata/")
## SET FILE PATH TO CHECKERBOARD CORNERS FROM CALIBRATION IMAGE SET
## THE TUTORIAL INCLUDES 8 CALIBRATION IMAGES FROM TWO CAMERA VIEWS
file <- matrix(c(paste0(fdir, "cal_a", 1:8, "_v1.txt"),
paste0(fdir, "cal_a", 1:8, "_v2.txt")), ncol=2)
## READ IN CHECKERBOARD CORNERS
## NOTE THAT col.reverse IS USED TO MAKE POINTS CORRESPOND
coor.2d <- readCheckerboardsToArray(file=file, nx=nx, ny=ny, col.reverse=TRUE)
## SET GRID SIZE (IN MM)
grid.size <- 6.347889
# }
# NOT RUN {
## CALIBRATE CAMERAS
## TO REDUCE RUN-TIME, WE JUST USE CORNERS FROM TWO IMAGES (1 AND 5)
dlt_calibrate_cameras <- dltCalibrateCameras(coor.2d=coor.2d[, , c(1, 5), ], nx=nx,
grid.size=grid.size, c.run=FALSE, print.progress=TRUE)
## RUN CALIBRATION ON ALL IMAGES, ACCURACY IS GREATLY IMPROVED
dlt_calibrate_cameras <- dltCalibrateCameras(coor.2d=coor.2d, nx=nx,
grid.size=grid.size, c.run=FALSE, print.progress=TRUE)
## PRINT SUMMARY
summary(dlt_calibrate_cameras)
# }
Run the code above in your browser using DataLab