Калибровка камеры с помощью цифровой камеры

Я работаю над калибровкой камеры около недели. Примеры, которые я видел в онлайн-статьях и блогах, используют веб-камеру для захвата изображений.

Но для моего сценария я использую цифровую камеру, а именно Casio Exilim EX-Z77. Я добавляю изображения в заданные аргументы программы и обращаюсь к ним по отдельности с помощью цикла for. Таким образом я смог имитировать работу веб-камеры.

Могу ли я получить правильные искажения и внутренности?? Поправьте меня, если я ошибаюсь или имею недопонимание.

Вот статья, в которой я основал свой код. Код ниже - это то, что я смог сделать.

     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;
}

Я использую блоки кода 10.05 и Opencv 2.3.0, компилятор Mingw GNU GCC.


person njm    schedule 22.12.2011    source источник


Ответы (1)


Цифровые камеры, такие как Casio Exilim EX-Z77, обычно выполняют некоторую коррекцию изображения прямо в камере.

Я полагаю, что изображения, получаемые с этой камеры, уже исправлены (относительно дисторсии объектива), но мне не удалось найти ссылку, подтверждающую это утверждение.

Что касается нескольких изображений, которые вы используете, на практике вам нужно только одно, чтобы найти искажение. Для получения дополнительной информации об этой процедуре с использованием OpenCV проверьте этот ответ.

ИЗМЕНИТЬ:

Поскольку вы упомянули сшивание изображений, OpenCV начал поддерживать эту функцию в версии 2.2:

Выпущен OpenCV 2.2! Тизеры уже далеко ПОСЛЕ этого выпуска: Панорамное сшивание

На эту тему в этом интересном посте есть несколько исходный код.

person karlphillip    schedule 22.12.2011
comment
В зависимости от того, что вы пытаетесь сделать с параметрами, не имеет значения, происходит ли уже какое-то исправление. Вам просто нужно учитывать, что вы определяете параметры для всей камеры, а не только для ее оптики. Прошло некоторое время с тех пор, как я коснулся OpenCV в университете, но я всегда использовал более одного изображения шахматной доски для калибровки. Просто так было намного точнее, особенно. без идеального освещения и прочего. - person Mario; 22.12.2011
comment
спасибо за немедленный ответ.. на самом деле я думал о том же.. что цифровые камеры предварительно калибруются перед продажей на рынке. . Но проблема в том, что я работаю над проектом. Это сшивание изображений. Пример из списка рассылки opencv требует, чтобы камера была откалибрована, чтобы выполнить успешную деформацию изображения. Надеюсь, вы поняли, о чем я говорю. - person njm; 22.12.2011
comment
Вам нужно только откалибровать камеру с помощью OpenCV, если захваченное изображение искажено. Это явно не тот случай с вашей камерой. Но тот, кто опубликовал этот пример, должен был решить эту проблему. Вам не нужно делать этот шаг. - person karlphillip; 22.12.2011
comment
@mario.. Я использовал 16 изображений, полученных с помощью майской камеры.. но когда я искажаю изображение, используя результирующее искажение и внутренние свойства.. результирующее изображение неудачно, и оно не только неудачно, но и уничтожено.. я попытаюсь исправить другое изображение, просто чтобы убедиться.. спасибо. - person njm; 22.12.2011
comment
Кстати, проверьте эту тему по сшиванию изображений с помощью opencv. - person karlphillip; 22.12.2011
comment
@karlphillip спасибо, что помогли мне .. могу ли я задать вопрос, не относящийся к тому, что я опубликовал? это относительно того, что я пытаюсь сделать с изображениями. - person njm; 22.12.2011
comment
@njm Да, напишите мне в твиттер в любое время. Только не забудьте закрыть этот вопрос, если вы чувствуете, что на него ответили. Рядом с каждым ответом есть небольшой флажок, вы можете нажать на него, чтобы выбрать его в качестве официального ответа на ваш вопрос. - person karlphillip; 22.12.2011
comment
@njm Кстати, я обновил ответ, так что теперь там есть несколько интересных ссылок. - person karlphillip; 22.12.2011