A C++ implementation of different aspects of geometric vision. This project includes following features:
- Geometric framework including transformations, rotation parametrization and quaternions
- Fast subpixel detector of calibration boards (checkerboards)
- Calibration toolbox for intrinsic, stereo and extrinsic calibration of fisheye cameras
- Image synthesis for simulated-data-based tests
- Algorithms of direct stereo correspondence
- Sparse and dense localization algorithms
Some of these features are quite mature and can be used for practical purposes. For example, calibration toolbox is automated and easy to use. The part on 3D reconstruction requires a certain degree of refactoring. The localization part is quite experimental.
Requred packages:
- ceres-solver 1.10.0+
- Eigen3
- OpenCV 2.4.9+
After you have installed the needed libraries, go to the directory visgeom in the terminal and run:
$ mkdir build
$ cd build
$ cmake ..
$ make
To run the calibration process you need to collect calibration data and describe the problem in a .json file. An example of such a file for monocular calibration is given in data/calib_example.json
First all the calibration variables have to be defined:
"transformations" : [
{
"name" : "xiCamBoard",
"global" : false,
"constant" : false,
"prior" : false
}
],
There is a single block of transformations xiCamBoard. The name is arbitrary.
- global is false because this transformation is unique for every image.
- constant is false because we have to compute it.
- prior is false because we don't have any prior estimation of these transformations.
"cameras": [
{
"name" : "camera1",
"type" : "eucm",
"constant" : false,
"value" : [0.5, 1, 300, 300, 600, 500]
}
],
In this case, we have one single camera called camera1. The following types are supported:
- ucm --- Unified Camera Model [J. Courbon et. al., A generic fisheye camera model for robotic applications. IROS 2007] intrinsics: [xi, fu, fv, u0, v0]
- eucm --- Enhanced Unified Camera Model [B. Khomutenko et. al., An enhanced unified camera model. IEEE RA-L 2016] intrinsics: [alpha, beta, fu, fv, u0, v0]
- mei --- Unified Camera Model with distortion [C. Mei and P. Rives, Single view point omnidirectional camera calibration from planar grids. ICRA 2007] intrinsics: [xi, k1, k2, k3, k4, k5, fu, fv, u0, v0]
value contains the initial guess for the parameters, or if constant is true, then it is the intrinsic parameters which will be used during the whole optimization process. In the case of monocular calibration constant must be false.
A quick overview of different values:
Type of the data used in this block. For monocular calibration is always images
Camera name, should be declared before
Describes the sequence of transformations between the camera and the calibration board. Each transformation is represented by a tuple:
- name --- transformation declared before
- direct --- true if the points must be transformed as X_cam = T(X_board).
Defines which transformation from the transformation chain has to be initialized. In the case of monocular calibration it should be always the only transformation.
Calibration object description.
- type --- the only supported type so far is checkboard,
- rows and cols --- size of the calibration patterns. Only internal corners are counted
- size --- size of one square in meters
Various flags to tweak the calibration process. If a particular flag is not in the list, then it is considered as false. Hence undersore in front of a flag disables it
- check_extraction --- show the detected grid for visual examination
- improve_detection --- use subpixel detector
- show_outliers --- show the images with reprojected pattern if some of the errors are ubnormally high
- save_outlire_images --- save these images
- do_not_solve_global --- don't solve the calibration problem, is used to see the initialization
- do_not_solve --- don't solve the optimization for transformation initialization, is used to see the computed initial pose
contains the image names
- prefix --- concatenated to every element of names, can be simply "" (an empty line)
- names --- a list of file names
In the case of stereo calibration we will use three datasets. It combines two monocular calibration datasets and one stereo calibration dataset.
In this case we have four transformations.
"transformations" : [
{
"name" : "xiCamBoard1",
"global" : false,
"constant" : false,
"prior" : false
},
{
"name" : "xiCamBoard2",
"global" : false,
"constant" : false,
"prior" : false
},
{
"name" : "xiCamBoardStereo",
"global" : false,
"constant" : false,
"prior" : false
},
{
"name" : "xiCam12",
"global" : true,
"constant" : false,
"prior" : true,
"value" : [0, -0.3, 0, 0, 0, 0]
}
],
In this example (which is a typical example of stereo calibration definition)
- xiCamBoard1 and xiCamBoard2 are used in monocular calibration subproblems. They are used exactly in the same manner as in monocular calibration.
- xiCamBoardStereo is used for either of stereo images.
- xiCam12 is the same for all the stereo images and defines the transformation between the two cameras. It is global and has a prior.
The following formats are supported to define a transformation
- 3 values [x, y, theta] --- 2D posture. z-coordinate, x- and y-rotation are 0
- 6 values [x, y, z, rx, ry, rz] --- full 3D parametrized by translation and rotation vectors (see Rodriguez' rotation formula)
- 7 values [x, y, z, qx, qy, qz, qw] --- 3D parametrized by a translation vector and a normalized quaternion
- 12 values [r11, r12, r13, t1, r21, r22, r23, t2, r31, r32, r33, t3] --- homogeneous transformation matrix, stored row-wise:
[ r11 r12 r13 t1 ]
[ r21 r22 r23 t2 ]
[ r31 r32 r33 t3 ]
[ 0 0 0 1 ]
In the case of stereo calibration, we'll have two cameras.
"cameras": [
{
"name" : "camera1",
"type" : "eucm",
"constant" : false,
"value" : [0.55, 1.2, 200, 200, 320, 240]
},
{
"name" : "camera2",
"type" : "eucm",
"constant" : false,
"value" : [0.55, 1.2, 200, 200, 320, 240]
}
],
We will have four data blocks. The two monocular calibration blocks as well as the stereo calibration block for the first camera are exactly the same as for the monocular calibration. The difference appears in the definition of the stereo calibration block for the second camera.
The first thing to note is that the images in the name list should correspond to the ones declared in the first stereo calibration block (they must be the same number and in the same order).
The second thing is that now the transformation chain includes one more transformation:
"transform_chain" : [
{"name" : "xiCam12", "direct" : false},
{"name" : "xiCamBoardStereo", "direct" : true}
]
The transformations are combined in the same order before being applied to the points of the calibration board. In this case the points in the second camera frame will be defined as (pseudo-code):
X_2[i, j] = xiCam12.inverse().compose(xiCamBoardStereo[j]).transform(X_b[i])
- X_2[i, j] is the i-th point in the camera frame for j-th image
- X_b[i] it the i-th point in the board frame
Notice that for the first camera points will be defined as (in the same pseudo-code):
X_1[i, j] = xiCamBoardStereo[j].transform(X_b[i])