Often you a faced with the problem of determining the intrinsic calibration of a camera. For example to straighten wide-angle photos, structure from motion and 3D reconstructions, augmented reality applications etc. With OpenCV the process is fairly simple but I found that a lot of people are unsure how to do it. Here's an example of calibrating a GoPro Hero 3 camera.
If the calibration pattern was not detected in an image you will get that instead of 'ok'. This happens. As long as you have enough images where the detection works, you should be fine. Take more photos, add to the folder and run again if needed.
Note that the camera matrix is dependent on the resolution of your images. If you use another resolution from the same camera, you need to scale the focal length (the values on the diagonal). The radial distortion parameters are independent of resolution.
Here are the sample files I used if you want to reproduce (calibration_samples.zip, undist.py).
1) Install OpenCV
First, you need to have OpenCV installed. Check the OpenCV website or this older blog post if you need help.2) Print the checkered calibration pattern
You can use any chessboard like pattern but using the default one that comes with OpenCV means you don't have to change any parameters.3) Attach the pattern to a flat surface
For example a wall, door or floor. Take lots of photos of your pattern from many varying angles and distances. Like this:4) Run calibration script
Put the photos in a folder on your machine and run the OpenCV python sample file calibrate.py like this:$ python calibrate.py "calibration_samples/GOPR00*.JPG"Here you use the path pattern that matches your files as a string (note the quotes!). You should see something like this:
processing calibration_samples/GOPR0045.JPG... okAfter all the calibration images have been processed you will get the calibration parameters:
processing calibration_samples/GOPR0046.JPG... ok
processing calibration_samples/GOPR0047.JPG... ok
processing calibration_samples/GOPR0048.JPG... ok
processing calibration_samples/GOPR0049.JPG... ok
...
RMS: 0.171988082483Done!
camera matrix:
[[ 611.18384754 0. 515.31108992]
[ 0. 611.06728767 402.07541332]
[ 0. 0. 1. ]]
distortion coefficients: [-0.36824145 0.2848545 0.00079123 0.00064924 -0.16345661]
If the calibration pattern was not detected in an image you will get that instead of 'ok'. This happens. As long as you have enough images where the detection works, you should be fine. Take more photos, add to the folder and run again if needed.
Note that the camera matrix is dependent on the resolution of your images. If you use another resolution from the same camera, you need to scale the focal length (the values on the diagonal). The radial distortion parameters are independent of resolution.
5) Unwarp an image just to check
For example like this:import numpy as np
import cv2
# copy parameters to arrays
K = np.array([[611.18384754, 0, 515.31108992], [0, 611.06728767, 402.07541332], [0, 0, 1]])
d = np.array([-0.36824145, 0.2848545, 0, 0, 0]) # just use first two terms (no translation)
# read one of your images
img = cv2.imread("calibration_samples/GOPR0059.JPG")
h, w = img.shape[:2]
# undistort
newcamera, roi = cv2.getOptimalNewCameraMatrix(K, d, (w,h), 0)
newimg = cv2.undistort(img, K, d, None, newcamera)
cv2.imwrite("original.jpg", img)
cv2.imwrite("undistorted.jpg", newimg)
Here are the sample files I used if you want to reproduce (calibration_samples.zip, undist.py).