2

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.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
njm
  • 51
  • 1
  • 2
  • 7

1 Answers1

2

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.

Community
  • 1
  • 1
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • Depending on what you're trying to do with the params, it shouldn't matter if there's some correction going on already. You just have to consider you're determining the params for the whole camera, not just its optics. Been some time since I touched OpenCV in university, but I've always used more than one chessboard image for calibration. Just been a lot more accurate that way, esp. without perfect lighting and stuff. – Mario Dec 22 '11 at 15:48
  • thank you for the immediate response.. actually i was thinking about the same thing.. that digital cameras is pre-calibrated before being sold into the market. . But the problem is that I am working on a project. It is image stitching.. an example on the opencv mailing list requires the camera to be calibrated to perform a successful image warping of the image.. hope you get what i am saying.. – njm Dec 22 '11 at 15:51
  • You only need to calibrate the camera with OpenCV if the captured image is distorted. This is clearly not the case with your camera. But whoever posted that example had to deal with this issue. You don't need to do this step. – karlphillip Dec 22 '11 at 15:56
  • @mario.. I used 16images obtain with may camera.. but when i undistort an image using the resulting distortion and instrinsic.. the resulting image is unsuccessful, and is not only unsuccessful but destroyed.. i will try to undistort another image just to make sure.. thank you. – njm Dec 22 '11 at 15:56
  • By the way, check [this thread](http://stackoverflow.com/questions/6017943/opencv-image-stitching) on image stitching with opencv. – karlphillip Dec 22 '11 at 15:57
  • @karlphillip thank you for helping me.. can i ask an unrelated question to what i posted? this regarding to what i am trying to do with the images. – njm Dec 22 '11 at 15:58
  • @njm Yes, drop me a message on twitter anytime. Just don't forget to close this question if you feel it was answered. There's a little checkbox near every answer, you can click on it to select it as the official answer to your question. – karlphillip Dec 22 '11 at 16:00
  • @njm By the way, I updated the answer so there's some cool references in there now. – karlphillip Dec 22 '11 at 16:06