# Camera calibration using C++ and OpenCV

## September 4, 2016

# Introduction

Often for complicated tasks in computer vision it is required that a camera be **calibrated**. Camera calibration is a necessary step in 3D computer vision in order to
extract metric information from 2D images. If you’re just looking for the code, you can find the full code here:

# What is meant by calibrating a camera?

There are many lens models but for this tutorial we will assume the most commonly used **pinhole model**. The model is described by the two images below:

The task of camera calibration is to determine the parameters of the transformation between an object in 3D space and the 2D image observed by the camera from visual information (images).

Let $\mathbf{X} = (X,Y,Z,1)^T$ be the coordinate of the point in 3D world coordinates. Then the 3D coordinate of the same point in camera frame $ \mathbf{X}_{cam} $ is transformed as:

where $\mathbf{R}$ is 3x3 rotation matrix and $\mathbf{t}$ is 3x1 translation matrix. Now, let $\mathbf{x}=(x,y,1)^T$ be the image coordinate of that 3D point, then the 3D to 2D mapping becomes:

where $\mathbf{K}$ is a 3x3 matrix containing the intrinsic parameters of the camera.

$f_x$ and $f_y$ are the focal length of the camera in the x-axis and the y-axis respectively. $(c_x, c_y)$ is coordinate of the principal point.

**Intrinsic parameters**: The $\mathbf{K}$ matrix consists of all the intrinsic parameters of the camera.**Extrinsic parameters**: The $\mathbf{R}$ and $\mathbf{t}$ matrices constitutes the extrinsic parameters of the camera.

Finding out these unknown parameters is known as camera calibration. We will not delve into the complicated linear algebra involved in finding out these parameters. Here is a gist of what we’ll do to calibrate - we will take multiple images of a checkerboard with a fixed square size and find all the corner points in each image. These corner points in the image correspond to some 3D point in the world (which is easy to calculate, since the checkerboard has a very well defined geometry). We’ll store these point to point correspondences and let OpenCV use it’s non-linear algorithm to give us the calibration parameters.

# Dependencies and Datasets

You must have `OpenCV 2.4.8+`

and `libpopt`

(command line args) to run the code. Also, you should have a dataset of calibration images beforehand of a fixed image resolution. Here are two sample images of the checkerboard.

It is recommended to get at least 30 images of the checkerboard in all possible orientations of the checkerboard to get good calibration results.

**Note**: In this example, a standard 9x6 calibration board is used. The size of the square is 24.23 mm.

# Code Explained

I will only explain the important parts of the code, and you can find the full source here: https://github.com/sourishg/stereo-calibration/blob/master/calib_intrinsic.cpp

Declare all the necessary vectors to store the image points and the object points. Image points are the checkerboard corner coordinates in the image whereas object points are the actual 3D coordinate of those checkerboard points.

We create a function called `setup_calibration`

to find all the corner points of each image and their corresponding 3D world points and prepare the `object_points`

and `image_points`

vectors. `board_n`

is the total number of corner points in the checkerboard. In our example it is $9\times 6=54$. Note that we also take a bunch of args, but I hope the variable names are self explanatory.

We loop through all the images in our directory and convert them to grayscale images using the function `cv::cvtColor`

.

Next we use the `findChessboardCorners`

function to find all the checkerboard corners. I would suggest you go through the OpenCV documentation for more details about the arguments of this function. If the corners are found then `found`

is set to `true`

and the corners are further refined by the `cornerSubPix`

function. The `drawChessboardCorners`

function is optional, it only helps you visualize the checkerboard corners found.

Next we store the object points. Ideally we should keep the origin at the camera centre and measure the 3D points of the checkerboard corners manually but you can image how difficult it would be. So we introduce a small but beautiful hack - we keep the world origin as the top left corner point. Mathematically this doesn’t change anything (think how). Now the geometry of the checkerboard helps us find the other 3D coordinates of the corners very easily. The $Z$ coordinate is always $0$ since all the points lie on a plane. Since the square size for this example is 24.23 mm (units are important!) then the other points become $(24.23, 0, 0)$, $(48.46, 0, 0)$ and so on.

We get all the necessary user input using `libpopt`

and call the `setup_calibration`

function.

Now we do the actual calibration using the `calibrateCamera`

function. `K`

is in the matrix containing the intrinsics as described before. `D`

contains the distortion coefficients. The distortion coefficients are used to remove any sort of distortion in the images. You can read more about the distortion coefficients here. `rvecs`

and `tvecs`

are the rotation and translation vectors. We also set `flag`

to ignore higher order distortion coefficients $k_4$ and $k_5$.

It is good practice to save the camera matrix `K`

and the distortion coefficients `D`

in a file so that you can reuse these parameters later on without having to recalibrate. `FileStorage`

writes the data in a `YAML`

file.

# Building the Code

The following repository contains the full source. The file you are looking for is `calib_intrinsic.cpp`

I have used `cmake`

to build the source and the README should help you build and run the program on your machine.