1

我正在做 Bradski 的“Learning OpenCV”的示例 11-1。我的实现在尝试使用 cvInitUndistortMap() 时崩溃。

一个类似的帖子(这里)有关于 cvUndistort2() 和 cvRemap() 使用彩色图像的问题。我不确定这里的问题是否相关。

代码如下:

#include "stdafx.h"

#include "opencv\cv.h"
#include "opencv\highgui.h"
#include "stdio.h"
#include "stdlib.h"
#include "iostream"
#include "iomanip"

using namespace std;

int n_boards; 
const int board_dt = 20; // Wait 20 frames per chessboard view
int board_w;
int board_h;

int main(int argc, char* argv[])
{
    board_w = 7;
    board_h = 7;
    n_boards = 10;

    int board_n = board_w * board_h;
    CvSize board_sz = cvSize(board_w, board_h);
    CvCapture* capture = cvCreateCameraCapture(0);
    assert(capture);

    cvNamedWindow("Calibration");

    // Allocate storage
    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, frame = 0;

    IplImage *image = cvQueryFrame(capture);
    IplImage *gray_image = cvCreateImage(cvGetSize(image),8,1); // subpixel

    // Capture corner views loop until we've got n_boards
    // Successful captures (all corners on the board are found)
    //
    while(successes < n_boards) {
        // Skip every board_dt frames to allow user to move chessboard
        if(frame++ % board_dt == 0){
            //Find chessboard corners:
            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++;
            }

            //display how many successes we currently have
            printf("\nImages: %d / %d", successes, n_boards);

        } // end skip board_dt between chessboard capture

        // Handle pause/unpause and ESC
        int c = cvWaitKey(15);
        if(c=='p'){
            c = 0;
            while(c!='p' && c != 27){
                c = cvWaitKey(250);
            }
        }
        if(c==27)
            return 0;

        image = cvQueryFrame(capture); // get next image
    } // end collection while loop

    // Allocate matrices according to how many chessboards were found
    printf("\n\n\nAllocating matrices...");
    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);
    printf("success!");

    // Transfer the points into the correct size matrices
    /*
    printf("\nTransfering points into the correct size matrices...");
    image_points->rows = object_points->rows = \
        successes*board_n;
    point_counts->rows = successes;
    printf("success!");
    */

    // The above two lines can alternatively be written in the following two loops
    printf("\nTransfering 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){ //These are all the same number
        CV_MAT_ELEM(*point_counts2, int, i, 0) = CV_MAT_ELEM(*point_counts, int, i, 0);
    }
    printf("success!");

    // At this point, we have all the chessboard corners we need. 
    // Initialize the intrinsic matrix such that the two focal lengths
    //  have a ratio of 1.0
    //
    printf("\nInitializing intrinsic matrix...");
    CV_MAT_ELEM(*intrinsic_matrix, float, 0, 0) = 1.0f;
    CV_MAT_ELEM(*intrinsic_matrix, float, 1, 1) = 1.0f;
    printf("success!");

    // Calibrate the camera
    printf("\nCalibrating camera...");
    cvCalibrateCamera2(
        object_points2, image_points2,
        point_counts2, cvGetSize(image),
        intrinsic_matrix, distortion_coeffs,
        NULL, NULL, 0 //CV_CALIB_FIX_ASPECT_RATIO
    );
    printf("success!");

    // Save the intrinsics and distortions
    printf("\nSaving intrinsic matrix and distortion coefficients..."); 
    cvSave("Instrinsics.xml",intrinsic_matrix);
    cvSave("Distortion.xml",distortion_coeffs);
    printf("success!");

    // Release old objects
    printf("\nReleasing old objects...");
    cvReleaseMat(&object_points);
    cvReleaseMat(&image_points);
    cvReleaseMat(&point_counts);
    cvReleaseMat(&object_points2);
    cvReleaseMat(&image_points2);
    cvReleaseMat(&point_counts2);
    cvReleaseMat(&intrinsic_matrix);
    cvReleaseMat(&distortion_coeffs);
    printf("success!");

    // Example of loading the above matrices back in
    printf("\nLoading intrinsic matrix and distortion coefficients...");
    CvMat *intrinsic  = (CvMat*)cvLoad("Intrinsics.xml");
    CvMat *distortion = (CvMat*)cvLoad("Distortion.xml");
    printf("success!");

    // Build the undistort map that we will use for all subsequent frames
    printf("\nBuilding undistort map...");
    IplImage* mapx = cvCreateImage( cvGetSize(image), IPL_DEPTH_32F, 1);
    IplImage* mapy = cvCreateImage( cvGetSize(image), IPL_DEPTH_32F, 1);
    printf("\nCrash incoming...");
    cvInitUndistortMap( // PROBLEM APPEARS TO BE HERE
        intrinsic,
        distortion,
        mapx,
        mapy
    );
    printf("success!");

    // Just run the camera to the screen, now showing the raw
    //  and the undistorted image.
    printf("Displaying undistorted images...");
    cvNamedWindow("Undistort");
    while(image) {
        IplImage *image = cvQueryFrame(capture);

        IplImage *imageRemapped = cvCloneImage(image);
        cvShowImage("Calibration", image); // Show raw image
        cvRemap(image, imageRemapped, mapx, mapy);     // Undistort image

        cvShowImage("Undistort", imageRemapped);   // Show corrected image

        // Handle pause/unpause and ESC
        int c = cvWaitKey(15);
        if(c=='p'){
            c=0;
            while(c!='p' && c!=27){
                c = cvWaitKey(250);
            }
        }
        if(c==27){
            cvReleaseImage(&image);
            cvReleaseImage(&imageRemapped);
            break;}
        image = cvQueryFrame(capture);
    }
    printf("success!");

    return 0;
}

其中 Intrinsics.xml 和 Distortion.xml 的校准结果如下:

Intrinsics.xml:

<?xml version="1.0"?>
<opencv_storage>
<Instrinsics type_id="opencv-matrix">
  <rows>3</rows>
  <cols>3</cols>
  <dt>f</dt>
  <data>
    6.58263672e+002 0. 3.61270020e+002 0. 6.50179993e+002
    2.34282578e+002 0. 0. 1.</data></Instrinsics>
</opencv_storage>

失真.xml:

<?xml version="1.0"?>
<opencv_storage>
<Distortion type_id="opencv-matrix">
  <rows>5</rows>
  <cols>1</cols>
  <dt>f</dt>
  <data>
    -1.43585190e-001 1.10129333e+000 -3.21008405e-003 2.23791786e-002
    -3.69336128e+000</data></Distortion>
</opencv_storage>

我正在使用 OpenCV 2.4、Windows7、Microsoft Visual C++ 2010 Express 和 MBP 网络摄像头。

4

0 回答 0