Sunday, January 9, 2011

206

OPENCV: STEREO CAMERA CALIBRATION

One of the basic tasks in Computer Stereo Vision is to calibrate the stereo camera in order to obtain the parameters that will allow you to calculate 3D information of the scene.

Now, I could tell you a lot of stuff about camera projection models, stereoscopy, lens distortion, etc... but there is a lot of information available about such topics out there. So, this post is for those who simply need to calibrate a stereo camera system and start calculating 3D stuff right away by using OpenCV

Anyway, I strongly recommend you to read the book: Learning OpenCV: Computer Vision with the OpenCV Library by Gary Bradski and Adrian Kaehler, Published by O'Reilly Media, October 3, 2008.

So... what do I need to calibrate my stereo camera? A chessboard like this:

Why a chessboard? Because its corners are very easy to find by using computer vision algorithms and its geometry is very simple. In order to find out the position of any corner you only need to know how many horizontal and vertical squares there are in the chessboard and the size of a square. The chessboard in the image is a 9x6 chessboard and if you print it in a paper of size A4 the size of the squares would be more or less 2.5cm.

OK, I've printed my chessboard and I have measured the real size of the squares, now what?
Now you just take multiple views of the chessboard in different positions and orientations with your stereo camera using your favorite software (maybe your own software, software provided by your camera manufacturer or some other free software like Coriander). The images should look like this:

(Yeah, that is me in Hawaiian shorts on a summer day :P)
The more variety of positions and orientations of the checkerboard in the images the better.
Great, you have taken a lot of shots of the chessboard in different positions, now create a text file with the paths to the images. For example:

images/left01.ppm
images/right01.ppm
images/left02.ppm
images/right02.ppm
images/left03.ppm
images/right03.ppm
images/left04.ppm
images/right04.ppm
images/left05.ppm
images/right05.ppm
images/left06.ppm
images/right06.ppm
images/left07.ppm
images/right07.ppm
images/left08.ppm
images/right08.ppm
images/left09.ppm
images/right09.ppm
images/left10.ppm
images/right10.ppm
images/left11.ppm
images/right11.ppm
images/left12.ppm
images/right12.ppm
images/left13.ppm
images/right13.ppm
images/left14.ppm
images/right14.ppm
images/left15.ppm
images/right15.ppm
images/left16.ppm
images/right16.ppm
images/left17.ppm
images/right17.ppm
images/left18.ppm
images/right18.ppm
images/left19.ppm
images/right19.ppm
images/left20.ppm
images/right20.ppm
Now download this software and compile it.



It is just one of the examples of the book mentioned above that I modified to accept some configuration parameters and store the results of the calibration. The usage of the software is as follows:

USAGE: ./stereo_calibrate imageList nx ny squareSize
imageList : Filename of the image list (string). Example : list.txt
nx : Number of horizontal squares (int > 0). Example : 9
ny : Number of vertical squares (int > 0). Example : 6
squareSize : Size of a square (float > 0). Example : 2.5

So, in this example the call to the program stereo_calibrate would be:

./stereo_calibrate list.txt 9 6 2.5

The program will start showing the detected chessboards, calculate the calibration parameters and store them in a bunch of xml files:

D1.xml D2.xml
M1.xml M2.xml
mx1.xml mx2.xml
my1.xml my2.xml
P1.xml P2.xml
R1.xml R2.xml
Q.xml

Congratulations! You have calibrated your stereo camera!! Now you can load this parameters into any other program that uses that stereo camera and play with them:

CvMat *Q = (CvMat *)cvLoad("Q.xml",NULL,NULL,NULL);
CvMat *mx1 = (CvMat *)cvLoad("mx1.xml",NULL,NULL,NULL);
CvMat *my1 = (CvMat *)cvLoad("my1.xml",NULL,NULL,NULL);
CvMat *mx2 = (CvMat *)cvLoad("mx2.xml",NULL,NULL,NULL);
CvMat *my2 = (CvMat *)cvLoad("my2.xml",NULL,NULL,NULL);

Each of the files contains a matrix, if you would like to know the meaning of each matrix, please refer to the book at the beginning of this post. Right now, the useful stuff is contained on the files mx1.xml, my1.xml, mx2.xml, my2.xml and Q.xml.

The files m*.xml are the distortion models of the cameras. So we will need these matrices to undo the distortion of the images caused by the lens. Using the cvRemap() function:

cvRemap(imgLeftOrig, imgLeftUndistorted, mx1, my1);
cvRemap(imgRightOrig, imgRightUndistoreted, mx2, my2);

The goal of all this is to be able to calculate the 3D position (in meters, cm, mm or whatever magnitude you chose) of a point given its position (in pixels) on the left image and its correspondent on the right image. We are almost there, but for that we need the matrix Q. Given the position an interest point in the left and right image, its 3D position can be calculated as follows:

d = pointRightImage.X - pointLeftImage.X;

X = pointLeftImage.X * Q[0, 0] + Q[0, 3];
Y = pointLeftImage.Y * Q[1, 1] + Q[1, 3];
Z = Q[2, 3];
W = d * Q[3, 2] + Q[3, 3];

X = X / W;
Y = Y / W;
Z = Z / W;

And thats pretty much it, now you know how to calculate 3D positions from 2 images using OpenCV. How to find interest points in one image and its correspondent on the other is an art that will be explained another day ;)

EDIT [2011/06/16]: Many people asked me about a good book to get started in OpenCV, so take a look at this:  OpenCV 2 Computer Vision Application Programming Cookbook

EDIT [2011/08/22]: What next? Check out the following post: OpenCV: Stereo Matching

EDIT [2011/08/27]: I changed the Makefile of the software for one much simpler and without hard-coded stuff. Also hosted the software in my own server (it was in megaupload, sorry about that), the link to the software in this post has been updated. Here it is, just in case: http://www.martinperis.com/stereocalibration/OpenCV-Stereo-Calibration.tgz 
EDIT [2012/01/05]: My hosting bandwidth was not enough to handle the traffic so I had to host the software on googlecode, the link to the software in this post has been updated. Here it is, just in case: http://opencv-stereo-calibration.googlecode.com/files/OpenCV-Stereo-Calibration-1.0.tgz

206 comments:

«Oldest   ‹Older   201 – 206 of 206
Unknown said...
This comment has been removed by the author.
Unknown said...

Hi martin. Can you help me. My project is about 3D map reconstruction using stereo vision but now I have a problem on stereo calibration. I'm using opencv 2.4.3 and visual studio 2010 - windows 8. I am still new with this software.

Nikita said...

Hello Sir,
Thanks for an great article . You suggested in above comments that if you want to work on coordinates you may use mx and my maps obtained to locate the corresponding points in stereo rectified image like this
"mx and my are not anything else but a couple of matrices of the same size as your images that contains the correspondent coordinate in the undistorted image for a point in the original image.

So what you are looking for is just this:

P2.x = mx(P1.x, P1.y)
P2.y = my(P1.x, P1.y)
"
I checked the value of mx and my they have negative values so it doesn't map to same coordinates is there any normalization that needs to be done after this step .

Nikita said...

Hello Sir,
Thanks for an great article . You suggested in above comments that if you want to work on coordinates you may use mx and my maps obtained to locate the corresponding points in stereo rectified image like this
"mx and my are not anything else but a couple of matrices of the same size as your images that contains the correspondent coordinate in the undistorted image for a point in the original image.

So what you are looking for is just this:

P2.x = mx(P1.x, P1.y)
P2.y = my(P1.x, P1.y)
"
I checked the value of mx and my they have negative values so it doesn't map to same coordinates is there any normalization that needs to be done after this step .

Todo para el masaje said...

Where is the code?

Amelia said...

Thanks all commenters.EPC-3D Stereo Video Camera People Counter .

«Oldest ‹Older   201 – 206 of 206   Newer› Newest»

Post a Comment