OpenCV :: solvePNP() - 断言失败

时间:2012-10-09 21:29:27

标签: opencv runtime-error pose-estimation

我试图在OpenCV的solvePNP()的帮助下获得相机的姿势。

运行我的程序后,我收到以下错误:

OpenCV Error: Assertion failed (npoints >= 0 && npoints == std::max(ipoints.checkVector(2, CV_32F), ipoints.checkVector(2, CV_64F))) in solvePnP, file /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_tarballs_ports_graphics_opencv/opencv/work/OpenCV-2.4.2/modules/calib3d/src/solvepnp.cpp, line 55
libc++abi.dylib: terminate called throwing an exception

我试图搜索如何解决这些错误,但遗憾的是我无法解决它!

这是我的代码,非常感谢所有评论/帮助:

enum Pattern { NOT_EXISTING, CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID };

void calcBoardCornerPositions(Size boardSize, float squareSize, vector<Point3f>& corners,
                          Pattern patternType)
{
    corners.clear();

    switch(patternType)
    {
    case CHESSBOARD:
    case CIRCLES_GRID:
        for( int i = 0; i < boardSize.height; ++i )
            for( int j = 0; j < boardSize.width; ++j )
                corners.push_back(Point3f(float( j*squareSize ), float( i*squareSize ), 0));
        break;

    case ASYMMETRIC_CIRCLES_GRID:
        for( int i = 0; i < boardSize.height; i++ )
            for( int j = 0; j < boardSize.width; j++ )
                corners.push_back(Point3f(float((2*j + i % 2)*squareSize), float(i*squareSize), 0));
        break;
    }
}

int main(int argc, char* argv[])
{
    float squareSize = 50.f;

    Pattern calibrationPattern = CHESSBOARD;

    //vector<Point2f> boardCorners;
    vector<vector<Point2f> > imagePoints(1);
    vector<vector<Point3f> > boardPoints(1);

    Size boardSize;
    boardSize.width = 9;
    boardSize.height = 6;

    vector<Mat> intrinsics, distortion;
    string filename = "out_camera_xml.xml";
    FileStorage fs(filename, FileStorage::READ);
    fs["camera_matrix"] >> intrinsics;
    fs["distortion_coefficients"] >> distortion;
    fs.release();

    vector<Mat> rvec, tvec;
    Mat img = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); // at kell adnom egy kepet

    bool found = findChessboardCorners(img, boardSize, imagePoints[0], CV_CALIB_CB_ADAPTIVE_THRESH);

    calcBoardCornerPositions(boardSize, squareSize, boardPoints[0], calibrationPattern);
    boardPoints.resize(imagePoints.size(),boardPoints[0]);

    //***Debug start***
    cout << imagePoints.size() << endl << boardPoints.size() << endl << intrinsics.size() << endl << distortion.size() << endl;
    //***Debug end***

    solvePnP(Mat(boardPoints), Mat(imagePoints), intrinsics, distortion, rvec, tvec);

    for(int i=0; i<rvec.size(); i++) {
            cout << rvec[i] << endl;
    }

    return 0;
}

编辑(一些调试信息):

我逐行调试它。我介入了所有的功能。我在SolvePNP(...)中得到断言失败。您可以在下面看到我在进入solvePNP函数时看到的内容。首先,它跳过第一个if语句/if(vec.empty())/,并进入第二个if语句/ if(!copyData) /,当时它执行最后一行/ * datalimit = dataend = datastart + rows * step [0] * /跳回第一个if语句并返回=&gt;比我得到断言失败错误。

template<typename _Tp> inline Mat::Mat(const vector<_Tp>& vec, bool copyData)
: flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG),
dims(2), rows((int)vec.size()), cols(1), data(0), refcount(0),
datastart(0), dataend(0), allocator(0), size(&rows)
{
    if(vec.empty())
        return;
    if( !copyData )
    {
        step[0] = step[1] = sizeof(_Tp);
        data = datastart = (uchar*)&vec[0];
        datalimit = dataend = datastart + rows*step[0];
    }
    else
        Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this);
}

3 个答案:

答案 0 :(得分:1)

进入调试器中的函数并确切地查看哪个断言失败。 (可能它需要双精度值(CV_64F)而不是浮点数。)

OpenCVs新的“inputarray”包装器可以让你用任何形状的垫子,点矢量等调用函数 - 它会将它排序。但是许多函数都假定使用特定的inut格式,或者使用过时的断言来强制执行特定的格式。

立体声/校准系统是需要特定布局的最差系统,而且经常成功的操作需要不同的布局。

答案 1 :(得分:0)

这些类型似乎不对,至少在为我工作的代码中我使用了不同的类型(如文档中所述)。

  

objectPoints - 对象坐标空间中的对象点数组,3xN / Nx3 1通道或1xN / Nx1 3通道,其中N是点数。矢量也可以在这里传递。

     

imagePoints - 相应图像点的阵列,2xN / Nx2 1通道或1xN / Nx1 2通道,其中N是点数。   矢量也可以在这里传递。

     

cameraMatrix - 输入相机矩阵A = \ vecthreethree {fx} {0} {cx} {0} {fy} {cy} {0} {0} {1}。

     

distCoeffs - 输入   失真系数矢量(k_1,k_2,p_1,p_2 [,k_3 [,k_4,   k_5,k_6]])4,5或8个元素。如果向量为NULL /空,则为   假设零失真系数。

     

rvec - 输出旋转矢量(参见Rodrigues()),与tvec一起,将点从模型坐标系带到   相机坐标系。

     

tvec - 输出翻译向量。

     

useExtrinsicGuess - 如果为true(1),则函数使用提供的rvec和tvec值作为初始值   旋转和平移向量的近似值,   并进一步优化它们。

Documentation from here.

vector<Mat> rvec, tvec应该是Mat rvec, tvec

vector<vector<Point2f> > imagePoints(1)应该是vector<Point2f> imagePoints(1)

vector<vector<Point3f> > boardPoints(1)应该是 而是vector<Point3f> boardPoints(1)

注意:我遇到了完全相同的问题,这对我有用(由于 calibrateCamera 使用向量,这有点令人困惑)。虽然没有尝试过imagePoints或boardPoints。(但正如上面链接中记录的那样, vector vector 应该有效,我想我最好提一下),但对于 rvec trec 我自己尝试过。

答案 2 :(得分:0)

我在solvePnP和opencv3中运行完全相同的问题。我试图在一个测试用例中隔离问题。我将std :: vector传递给cv :: InputArray的接缝不符合预期。以下小测试适用于opencv 2.4.9但不适用于3.2。

这正是将std :: vector of points传递给solvePnP并导致solvepnp.cpp中第63行的断言失败的问题!

在传递给solvePnP之前,从向量列表中生成cv :: mat。

xhtml2pdf

结果opencv 2.4.9 macos:

//create list with 3 points
std::vector<cv::Point3f> vectorList;
vectorList.push_back(cv::Point3f(1.0, 1.0, 1.0));
vectorList.push_back(cv::Point3f(1.0, 1.0, 1.0));
vectorList.push_back(cv::Point3f(1.0, 1.0, 1.0));

//to input array
cv::InputArray inputArray(vectorList);
cv::Mat mat = inputArray.getMat();
cv::Mat matDirect = cv::Mat(vectorList);

LOG_INFO("Size vector: %d mat: %d matDirect: %d", vectorList.size(), mat.checkVector(3, CV_32F), matDirect.checkVector(3, CV_32F));

QVERIFY(vectorList.size() == mat.checkVector(3, CV_32F));

结果opencv 3.2 win64:

TestObject: OpenCV
Size vector: 3 mat: 3 matDirect: 3