OpenCV undistortPoints Assertion Failed

Im using the c++ style openCV calls, with ofxOpenCV.

I declare the matrices in my header:

  
  
    cv::Mat srcMat;  
    cv::Mat destMat;  
    cv::Mat cameraMat;  
    cv::Mat distCoeffs;  
    cv::Mat projR;  
    cv::Mat projT;  
  

Read them in setup:

  
  
const char* proj_calibration_filename_str = (ofToDataPath("projector_calibration.yml")).c_str();  
cv::FileStorage fs(proj_calibration_filename_str, cv::FileStorage::READ);  
      
    if(fs.isOpened()) {  
          
        fs["proj_intrinsics"] >> cameraMat;  
        fs["proj_distortion"] >> distCoeffs;  
        fs["R"] >> projR;  
        fs["T"] >> projT;  
          
		printf("Read Calibration File\n");  
        fs.release();  
	} else {  
		printf("Error Reading Calibration File\n");  
	}  
  

Which prints “Read Calibration File”, so it seems like it’s finding the file, at least.

Then in my draw function, I declare my points to be unconverted:

  
  
cv::Mat srcMat = cv::Mat(1,2,CV_32FC2);  
srcMat.at<float>(0,0) = static_cast<float>(srcPoint.x);  
srcMat.at<float>(0,1) = static_cast<float>(srcPoint.y);  
cv::vector<cv::Point2f> destMat;  
  

srcPoint is an ofPoint declared elsewhere.
Finally, I try to run cv::undistortPoints:

  
 cv::undistortPoints(srcMat, destMat, cameraMat, distCoeffs, projR, projT);  

Which breaks with the following error:

  
OpenCV Error: Assertion failed (CV_IS_MAT(_cameraMatrix) && _cameraMatrix->rows == 3 && _cameraMatrix->cols == 3) in cvUndistortPoints, file /Users/theo/Documents/CODE/__OPENFRAMEWORKS/gitOF/__BuildAllLibs/OpenCV-2.2.0/modules/imgproc/src/undistort.cpp, line 274  
terminate called after throwing an instance of 'cv::Exception'  

It seems like either the cameraMat is not considered a Matrix, or it doesn’t have the right numbers of rows and columns. The projector_calibration.yml file was generated using RGBDemo, and looks correct when I compare it to the example:

  
  
%YAML:1.0  
proj_intrinsics: !!opencv-matrix  
   rows: 3  
   cols: 3  
   dt: d  
   data: [ 1.4036195446237848e+03, 0., 5.2713483837741012e+02, 0.,  
       1.3998619573122030e+03, 7.7886478000166096e+02, 0., 0., 1. ]  
proj_distortion: !!opencv-matrix  
   rows: 1  
   cols: 5  
   dt: d  
   data: [ 0., 0., 0., 0., 0. ]  
R: !!opencv-matrix  
   rows: 3  
   cols: 3  
   dt: d  
   data: [ 9.9999687297817286e-01, -6.4960911594646336e-04,  
       -2.4149620850954703e-03, 1.2429759122214333e-03,  
       9.6705492037515506e-01, 2.5456479723065450e-01,  
       2.1700333540309175e-03, -2.5456700294067780e-01,  
       9.6705270382179442e-01 ]  
T: !!opencv-matrix  
   rows: 3  
   cols: 1  
   dt: d  
   data: [ -1.0536869947605793e-01, 8.1490447719949871e-02,  
       2.9455761979362217e-02 ]  
proj_size: !!opencv-matrix  
   rows: 1  
   cols: 2  
   dt: i  
   data: [ 1024, 768 ]  
  
  

Has anyone done this successfully? I have a budget for this project and could hire someone to help me get this working if you’re available right away.

I might be off here, but I don’t think that this:

  
fs["proj_intrinsics"] >> cameraMat;  

does the right thing by default, I think you need to stream that into something else, a string buffer, and then allocate and set each part of cameraMat by hand, i.e.

  
  
cv::Mat camMat = cv::Mat(3,3,CV_32FC2);  
//...  
vector<string> s = ofSplitString(stringBuf);  
camMat[0][0] = ::atof(s[0].c_str()); // and so on  
  

I can’t really test that right now, but I remember the oCV file streaming not being that smart.

I double-checked, and this function works for the c++ style calls in openCV. I was gettings confused by the e+ notation and thought the decimal places were off, when it was my understanding of the notation that was off. My issue above may have been caused by casting to float instead of double. I’m going to recalibrate my system and try it again.