Reputation: 51
I have been working on Camera Calibration for about a week know. The examples I saw from online articles and blogs uses a Web Camera to Capture the images.
But for my scenario I am using a digital camera namely Casio Exilim EX-Z77. I add the images into the set program arguments and access them individually using a for loop. In this manner I was able to imitate how a web camera works.
Is it possible for me to get the correct distortions and intrinsics?? Correct me if I am wrong or having a misunderstanding.
Here is the article I based my code. The code below is what I was able to make.
int n_boards = 0;
int board_w;
int board_h;
using namespace std;
int main( int argc, char *argv[] )
{
board_w = 5; // Board width in squares
board_h = 8; // Board height
n_boards = 16; // Number of boards
int board_n = board_w * board_h;
CvSize board_sz = cvSize( board_w, board_h );
CvMat* image_points = cvCreateMat( n_boards*board_n, 2, CV_32FC1 );
CvMat* object_points = cvCreateMat( n_boards*board_n, 3, CV_32FC1 );
CvMat* point_counts = cvCreateMat( n_boards, 1, CV_32SC1 );
CvMat* intrinsic_matrix = cvCreateMat( 3, 3, CV_32FC1 );
CvMat* distortion_coeffs = cvCreateMat( 5, 1, CV_32FC1 );
CvPoint2D32f* corners = new CvPoint2D32f[ board_n ];
int corner_count;
int successes = 0;
int step;
int a;
for(a =1; a<=n_boards; a++){
while( successes < n_boards ){
IplImage *image = cvLoadImage(argv[a]);
IplImage *gray_image = cvCreateImage( cvGetSize( image ), 8, 1 );
int found = cvFindChessboardCorners( image, board_sz, corners,
&corner_count, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS );
// Get subpixel accuracy on those corners
cvCvtColor( image, gray_image, CV_BGR2GRAY );
cvFindCornerSubPix( gray_image, corners, corner_count, cvSize( 11, 11 ),
cvSize( -1, -1 ), cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));
// Draw it
cvDrawChessboardCorners( image, board_sz, corners, corner_count, found );
//cvShowImage( "Calibration", image );
// If we got a good board, add it to our data
if( corner_count == board_n ){
step = successes*board_n;
for( int i=step, j=0; j < board_n; ++i, ++j ){
CV_MAT_ELEM( *image_points, float, i, 0 ) = corners[j].x;
CV_MAT_ELEM( *image_points, float, i, 1 ) = corners[j].y;
CV_MAT_ELEM( *object_points, float, i, 0 ) = j/board_w;
CV_MAT_ELEM( *object_points, float, i, 1 ) = j%board_w;
CV_MAT_ELEM( *object_points, float, i, 2 ) = 0.0f;
}
CV_MAT_ELEM( *point_counts, int, successes, 0 ) = board_n;
successes++;
}
}
IplImage *image1 = cvLoadImage(argv[1]);
CvMat* object_points2 = cvCreateMat( successes*board_n, 3, CV_32FC1 );
CvMat* image_points2 = cvCreateMat( successes*board_n, 2, CV_32FC1 );
CvMat* point_counts2 = cvCreateMat( successes, 1, CV_32SC1 );
// Transfer the points into the correct size matrices
for( int i = 0; i < successes*board_n; ++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 < successes; ++i ){
CV_MAT_ELEM( *point_counts2, int, i, 0 ) = CV_MAT_ELEM( *point_counts, int, i, 0 );
}
cvReleaseMat( &object_points );
cvReleaseMat( &image_points );
cvReleaseMat( &point_counts );
CV_MAT_ELEM( *intrinsic_matrix, float, 0, 0 ) = 1.0;
CV_MAT_ELEM( *intrinsic_matrix, float, 1, 1 ) = 1.0;
cvCalibrateCamera2( object_points2, image_points2, point_counts2, cvGetSize( image1 ),
intrinsic_matrix, distortion_coeffs, NULL, NULL, CV_CALIB_FIX_ASPECT_RATIO );
cvSave( "Intrinsics.xml", intrinsic_matrix );
cvSave( "Distortion.xml", distortion_coeffs );
// Example of loading these matrices back in
CvMat *intrinsic = (CvMat*)cvLoad( "Intrinsics.xml" );
CvMat *distortion = (CvMat*)cvLoad( "Distortion.xml" );
IplImage* mapx = cvCreateImage( cvGetSize( image1 ), IPL_DEPTH_32F, 1 );
IplImage* mapy = cvCreateImage( cvGetSize( image1 ), IPL_DEPTH_32F, 1 );
cvInitUndistortMap( intrinsic, distortion, mapx, mapy );
cvNamedWindow( "Undistort" );
while( image1 ){
IplImage *t = cvCloneImage( image1 );
cvShowImage( "Calibration", image ); // Show raw image
cvRemap( t, image1, mapx, mapy ); // undistort image
cvReleaseImage( &t );
cvShowImage( "Undistort", image1 ); // Show corrected image
}
}
return 0;
}
I am using Code blocks 10.05 and Opencv 2.3.0, Mingw GNU GCC compiler.
Upvotes: 2
Views: 1638
Reputation: 93410
Digital cameras such as Casio Exilim EX-Z77 usually perform a certain amount of image correction in-camera.
I believe that the images you get from this camera are already corrected (regarding lens distortion), but I couldn't find a reference to back up this claim.
As for the multiple images you are using, in practice you only need one to find the distortion. For more information on this procedure using OpenCV check this answer.
EDIT:
Since you mentioned image stitching, OpenCV started to support this feature on version 2.2:
OpenCV 2.2 is released! Teasers already far along AFTER this release: Panoramic Stitching
On this subject, this interesting post shares some source code.
Upvotes: 2