Monday, October 26, 2009

Camera Calibration using OpenCV

Actually this is one of the thing that I wanted to try last two year but at that time I didn't understand how to use it so I left it. But right now I have understood how to use this, so I would like to share it with you.

The usage is very simple. If you have already succeeded with capturing webcam using OpenCV, this example will be a lot more fun than that :D.

Suppose you have already connect your webcam to be captured using OpenCV, what you need to do is preparing these variables:

int patternCol(7);
int patternRow(4);
int numOfCorner(28);
int cornerCount(0);
int nBoards(8);
int successes(0);
int step(0);
CvPoint2D32f *cornerPoints;

Remember that you need to initialize the cornerPoints using new because it's a dynamic array.

Then, you need to add these lines into the callback of your webcam, suppose the variable of your callback is image:

int found = cvFindChessboardCorners(image, boardSize, cornerPoints, &cornerCount, CV_CALIB_CB_ADAPTIVE_THRESH);
cvDrawChessboardCorners(image, boardSize, cornerPoints, numOfCorner, found);

What you will see is that the chessboard corners are marked with a circle. If the circle has different colors, then it means the algorithm is successful. Something like this:

Then, the next thing you have to do is to save the position of the corners into a variable until you have enough images to perform the camera calibration. I tried using only 8 images, you can try more. I set the number of images using nBoards variable.

if( cornerCount == numOfCorner )
for( int i=step, j=0; j <>
CV_MAT_ELEM( *image_points, float, i, 0 ) = cornerPoints[j].x;
CV_MAT_ELEM( *image_points, float, i, 1 ) = cornerPoints[j].y;
CV_MAT_ELEM( *object_points, float, i, 0 ) = j/patternCol;
CV_MAT_ELEM( *object_points, float, i, 1 ) = j%patternRow;
CV_MAT_ELEM( *object_points, float, i, 2 ) = 0.0f;
CV_MAT_ELEM( *point_counts, int, successes, 0 ) = nBoards;

Then, the next thing is to calibrate the camera using these lines of code:
CvMat* object_points2 = cvCreateMat( successes*nBoards, 3, CV_32FC1 );
CvMat* image_points2 = cvCreateMat( successes*nBoards, 2, CV_32FC1 );
CvMat* point_counts2 = cvCreateMat( successes, 1, CV_32SC1 );

// Transfer the points into the correct size matrices
for( int i = 0; i <>
CV_MAT_ELEM( *image_points2, float, i, 0) = CV_MAT_ELEM( *image_points, float, i, 0 );
CV_MAT_ELEM( *image_points2, float, i, 1) = CV_MAT_ELEM( *image_points, float, i, 1 );
CV_MAT_ELEM( *object_points2, float, i, 0) = CV_MAT_ELEM( *object_points, float, i, 0 );
CV_MAT_ELEM( *object_points2, float, i, 1) = CV_MAT_ELEM( *object_points, float, i, 1 );
CV_MAT_ELEM( *object_points2, float, i, 2) = CV_MAT_ELEM( *object_points, float, i, 2 );

for( int i=0; i <>
CV_MAT_ELEM( *point_counts2, int, i, 0 ) = CV_MAT_ELEM( *point_counts, int, i, 0 );

// At this point we have all the chessboard corners we need
// Initiliazie the intrinsic matrix such that the two focal lengths
// have a ratio of 1.0

CV_MAT_ELEM( *intrinsic_matrix, float, 0, 0 ) = 1.0;
CV_MAT_ELEM( *intrinsic_matrix, float, 1, 1 ) = 1.0;

// Calibrate the camera
cvCalibrateCamera2( object_points2, image_points2, point_counts2, cvSize( image->width, image->height ),intrinsic_matrix, distortion_coeffs, NULL, NULL, CV_CALIB_FIX_ASPECT_RATIO );

the output of the calibration is these two matrices: intrinsic_matrix, distortion_coeffs. You can save it into a file using cvSave(...) or directly call it from somewhere in your program.

These are some excerpts of the steps that I implement in my program. I followed the examples provided in Chapter 11 of OpenCV book :). If you're interested just try it :D

Wait for my next post about why this camera calibration stuff is important, hehehe... :D

Labels: , , , , ,

Wednesday, October 07, 2009

Real time Lissajous Graph using OpenCV

If you need a real time charting tools, you might need to make one by your own. In my case, I need to observe the Lissajous Curve of my signal to ensure the phase difference between two signal is correct.

We could perform this using oscilloscope if it is electrical signal, but in my case I need to do take the data from an image captured by camera and I need to observe the Lissajous figure at real time. I found that common windows GUI component (at least the one that I use..) is not fast enough. So I create a custom graph using OpenCV which cost me around 2-3ms to show.

I like OpenCV because it's fast and it's enough for my application. For example if we have a signal like this one and we want to check the phase difference between the Blue point and the Red point, or you want to check the phase difference between Red point and Yellow Point. First we have to determine the points.

We can draw it on a Lissajous Curve by drawing the intensity on the X-Y axis as follow. This is simply just drawing a point based on the intensity of the point.

Based on the theory, if the phase difference is 90 degree, the Lissajous curve will be a circle. We can apply circle eccentricity algorithm to determine whether it's a circle or not. In my case, I haven't implemented it yet. If the shape is almost circle, then it is just enough for my application.

Labels: , , ,

Thursday, October 01, 2009

Creating a custom report based on OpenCV

If you need to create a colorful chart with simple text information, this article might be useful for you. In my case, I need to develop a software for measuring an object and usually if the result is visualized using Matlab. Hmm.. it takes time and usually what we need might be only a simple result.

I want to do this because sometimes when I need to present a data, I still have to set the fonts size and some other settings in order to get several results with the same style and when I use different computer, the size and the resolution of the image changes, and it takes a long time just to set the image properties. Such a boring task...

So, I came up with an idea to visualize the data using our own software. Therefore, we only need to run the application and at the end you can obtain the result that is ready to be presented either in a paper or presentation. If you need to take another data just repeat it and you'll get the same style.

The idea is simple, what you need to do is:
  1. Save the result into a file/memory.
  2. Read the file/memory and then draw it into an image for 2D or visualize in 3D.
  3. Give some information about the data, i.e. the axis, numbers, limits, etc. which are essential for your data.

Just that simple. This is a sample of the result that I can made, it's not a real data though, but it can be used as a sample. Well, actually we still need to do some preprocessing of the data until we can present something meaningful but that's out of this context.

The color in the chart is made by using HSI to RGB transformation. For those who are not familiar with this transformation, you can search about it in wikipedia or google. The credit goes to Loc, my colleague who has written the code for doing the transformation.

Labels: , , ,