Search code examples
opencvassemblycamera-calibrationstereo-3d

Assembly explanation about stereoCalibrate error with OutputArray::Create assertion error


I came across an error during execute stereoCalibrate in Opencv 2.4.11, which is says :

OpenCV Error: Assertion failed (!fixedSize() || ((Mat*)obj)->size.operator()() == Size(cols, rows)) in cv::_OutputArray::create,

I think this must be some size error between these parameters, which go through them one by one. But there is still error. I hope someone awesome could find the error from the assembly code below. Here is the method call in my code.

double error = cv::stereoCalibrate(
        objPoints, cali0.imgPoints, cali1.imgPoints,
        camera0.intr.cameraMatrix, camera0.intr.distCoeffs,
        camera1.intr.cameraMatrix, camera1.intr.distCoeffs,
        cv::Size(1920,1080), m.rvec, m.tvec, m.evec, m.fvec,
        cv::TermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 100, 1e-5)
        ,CV_CALIB_FIX_INTRINSIC + CV_CALIB_USE_INTRINSIC_GUESS
    );

In my code, m.rvec is (3,3,CV_64F), m.tvec is (3,1,CV_64F), m.evec and m.fvec are not preallocated which is same with the stereoCalibrate example. And intr.cameraMatrix is (3,3,CV_64F) and intr.distCoeffs is (8,1,CV_64F), objPoints is computed from the checkerboard which stores the 3d position of corners and all z value for point is zero.

After reading advice from @Josh, I modify the code as plain output mat object which are in CV_64F, but it still throws this assertion.

cv::Mat R, t, e, f;
    double error = cv::stereoCalibrate(
        objPoints, cali0.imgPoints, cali1.imgPoints,
        camera0.intr.cameraMatrix, camera0.intr.distCoeffs,
        camera1.intr.cameraMatrix, camera1.intr.distCoeffs,
        cali0.imgSize, R, t, e, f,
        cv::TermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 100, 1e-5));

Finally I solved this problem, as a reminder, make sure the camera parameters you passed in are not const type....


Solution

  • Why go for assembly? OpenCV is open source and you can check the code you're calling here: https://github.com/opencv/opencv/blob/master/modules/calib3d/src/calibration.cpp#L3523

    If you get assertion fails in OpenCV it's usually because you've passed a matrix with an incorrect shape. OpenCV is extremely picky. The assertion fail is on an OutputArray, so checking the function signature there are four possible culprits:

    OutputArray _Rmat, OutputArray _Tmat, OutputArray _Emat, OutputArray _Fmat
    

    The sizing is done inside cv::stereoCalibrate here:

    https://github.com/opencv/opencv/blob/master/modules/calib3d/src/calibration.cpp#L3550

    _Rmat.create(3, 3, rtype);
    _Tmat.create(3, 1, rtype);
    
    <-- snipped -->
    
    if( _Emat.needed() )
    {
        _Emat.create(3, 3, rtype);
        p_matE = &(c_matE = _Emat.getMat());
    }
    if( _Fmat.needed() )
    {
        _Fmat.create(3, 3, rtype);
        p_matF = &(c_matF = _Fmat.getMat());
    

    }

    The assertion is being triggered in one of these calls, the code is here:

    https://github.com/opencv/opencv/blob/master/modules/core/src/matrix.cpp#L2241

    Try passing in plain Mat objects without preallocating their shape.