1

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()) / を飛び​​越え、2 番目の if ステートメント / if( !copyData ) / に入り、最後の行 /*datalimit = dataend = datastart + rows を実行します。 *step[0]*/ は、最初の if ステートメントに戻り、=> を返します。Assertion failed エラーが発生します。

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

3 に答える 3

1

デバッガーで関数にステップ インし、どのアサーションが失敗しているかを正確に確認します。(おそらく float ではなく double (CV_64F) の値が必要です。)

OpenCV の新しい「inputarray」ラッパーは、任意の形状のマット、ポイントのベクトルなどで関数を呼び出すことができるようにサポートされており、それを整理します。しかし、多くの関数は特定の inut 形式を想定しているか、特定の形式を強制する廃止されたアサーションを持っています。

ステレオ/キャリブレーション システムは、特定のレイアウトを必要とする場合に最悪であり、頻繁に連続する操作では別のレイアウトが必要になります。

于 2012-10-10T14:41:23.770 に答える
0

少なくとも私のために働いたコードでは、さまざまなタイプを使用しました(ドキュメントに記載されているように)。

objectPoints – オブジェクト座標空間のオブジェクト ポイントの配列、3xN/Nx3 1 チャネルまたは 1xN/Nx1 3 チャネル、ここで N はポイントの数です。vector もここで渡すことができます。

imagePoints – 対応するイメージ ポイントの配列、2xN/Nx2 1 チャネルまたは 1xN/Nx1 2 チャネル、ここで N はポイントの数です。vector もここで渡すことができます。

cameraMatrix – 入力カメラ行列 A = \vecthreethree{fx}{0}{cx}{0}{fy}{cy}{0}{0}{1} .

distCoeffs – 4、5、または 8 要素の歪み係数 (k_1、k_2、p_1、p_2[、k_3[、k_4、k_5、k_6]]) の入力ベクトル。ベクトルが NULL/空の場合、歪み係数はゼロであると見なされます。

rvec – tvec と共に、モデル座標系からカメラ座標系にポイントをもたらす出力回転ベクトル ( Rodrigues() を参照)。

tvec – 出力変換ベクトル。

useExtrinsicGuess – true (1) の場合、関数は提供された rvec 値と tvec 値をそれぞれ回転ベクトルと並進ベクトルの初期近似値として使用し、さらにそれらを最適化します。

ドキュメントはこちらから。

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)ます。

注: 私はまったく同じ問題に遭遇しましたが、これはうまくいきました (キャリブレートカメラはベクトルを使用するため、少し混乱します)。ただし、imagePointsまたはboardPointsについては試していません(ただし、上記のリンクに記載されているように、vectorvectorは機能するはずです。言及した方がよいと思いました)が、rvectrecについては自分で試しました。

于 2015-07-14T09:41:45.940 に答える