OpenCV 2.3 camera calibration
camera-calibration, computer-vision, matlab, opencv, vision
Solution
First off, your camera matrix is wrong. If you read the documentation, it should look like:
fx 0 cx
0 fy cy
0 0 1
If you look at yours, you've got it the wrong way round:
fx 0 0
0 fy 0
cx cy 1
So first, set `camera_matrix` to `camera_matrix.T` (or change how you construct `camera_matrix`. Remember that `camera_matrix[i,j]` is row `i`, column `j`).
camera_matrix = camera_matrix.T
Next, I ran your code and I see that "can't seem to get it to work" means the following error (by the way - always say what you mean by "can't seem to get it to work" in your questions - if it's an error, post the error. If it runs but gives you weirdo numbers, say so):
OpenCV Error: Assertion failed (ni >= 0) in collectCalibrationData, file /home/cha66i/Downloads/OpenCV-2.3.1/modules/calib3d/src/calibration.cpp, line 3161
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
cv2.error: /home/cha66i/Downloads/OpenCV-2.3.1/modules/calib3d/src/calibration.cpp:3161: error: (-215) ni >= 0 in function collectCalibrationData
I then read the documentation (very useful by the way) and noticed that `obj_points` and `img_points` have to be vectors of vectors, because it is possible to feed in sets of object/image points for multiple images of the same chessboard(/calibration points).
Hence:
cv2.calibrateCamera([obj_points], [img_points],size, camera_matrix, dist_coefs)
What? I still get the same error?!
Then, I had a look at the OpenCV python2 samples (in the folder `OpenCV-2.x.x/samples/python2`), and noticed a `calibration.py` showing me how to use the calibration functions (never underestimate the samples, they're often better than the documentation!).
I tried to run `calibration.py` but it doesn't run because it doesn't supply the `camera_matrix` and `distCoeffs` arguments, which are necessary. So I modified it to feed in a dummy `camera_matrix` and `distCoeffs`, and hey, it works!
The only difference I can see between my `obj_points`/`img_points` and theirs, is that theirs has `dtype=float32`, while mine doesn't.
So, I change my `obj_points` and `img_points` to also have dtype float32 (the python2 interface to OpenCV is funny like that; often functions don't work when matrices don't have a `dtype`):
obj_points = obj_points.astype('float32')
img_points = img_points.astype('float32')
Then I try again:
>>> cv2.calibrateCamera([obj_points], [img_points],size, camera_matrix, dist_coefs)
OpenCV Error: Bad argument
(For non-planar calibration rigs the initial intrinsic matrix must be specified)
in cvCalibrateCamera2, file ....
What?! A different error at least. But I did supply an initial intrinsic matrix!
So I go back to the documentation, and notice the `flags` parameter:
flags – Different flags that may be zero or a combination of the following values:
`CV_CALIB_USE_INTRINSIC_GUESS` cameraMatrix contains valid initial values of fx, fy, cx, cy that are optimized further
...
Aha, so I have to tell the function explicitly to use the initial guesses I provided:
cv2.calibrateCamera([obj_points], [img_points],size, camera_matrix.T, dist_coefs,
flags=cv2.CALIB_USE_INTRINSIC_GUESS)
Hurrah! It works!
(Moral of the story - read the OpenCV documentation carefully, and use the newest version (i.e. on opencv.itseez.com) if you're using the Python `cv2` interface. Also, consult the examples in the `samples/python2` directory to supplement the documentation. With these two things you should be able to work out most problems.)
Problem
I'm trying to use `OpenCV 2.3` python bindings to calibrate a camera. I've used the data below in matlab and the calibration worked, but I can't seem to get it to work in OpenCV. The camera matrix I setup as an initial guess is very close to the answer calculated from the matlab toolbox. ``` import cv2 import numpy as np obj_points = [[-9.7,3.0,4.5],[-11.1,0.5,3.1],[-8.5,0.9,2.4],[-5.8,4.4,2.7],[-4.8,1.5,0.2],[-6.7,-1.6,-0.4],[-8.7,-3.3,-0.6],[-4.3,-1.2,-2.4],[-12.4,-2.3,0.9], [-14.1,-3.8,-0.6],[-18.9,2.9,2.9],[-14.6,2.3,4.6],[-16.0,0.8,3.0],[-18.9,-0.1,0.3], [-16.3,-1.7,0.5],[-18.6,-2.7,-2.2]] img_points = [[993.0,623.0],[942.0,705.0],[1023.0,720.0],[1116.0,645.0],[1136.0,764.0],[1071.0,847.0],[1003.0,885.0],[1142.0,887.0],[886.0,816.0],[827.0,883.0],[710.0,636.0],[837.0,621.0],[789.0,688.0],[699.0,759.0],[768.0,800.0],[697.0,873.0]] obj_points = np.array(obj_points) img_points = np.array(img_points) w = 1680 h = 1050 size = (w,h) camera_matrix = np.zeros((3, 3)) camera_matrix[0,0]= 2200.0 camera_matrix[1,1]= 2200.0 camera_matrix[2,2]=1.0 camera_matrix[2,0]=750.0 camera_matrix[2,1]=750.0 dist_coefs = np.zeros(4) results = cv2.calibrateCamera(obj_points, img_points,size, camera_matrix, dist_coefs) ```