8

私は OpenCV プロジェクトに取り組んでおり、キャリブレーションを行っています。コードを正しく実装したと思います。ただし、カメラマトリックスの値が異なる場合があり、大きく異なる場合があります。キャリブレーションパターンを10回表示することを6回繰り返した後、次のようになります(わかりやすくするために小数点以下は切り捨てられます)

[573, 0,  386;
  0, 573, 312;
  0,  0,   1]

[642, 0,  404;
  0, 644, 288;
  0,  0,   1]

[664, 0,  395;
  0, 665, 272;
  0,  0,   1]

[629, 0,  403;
  0, 630, 288;
  0,  0,   1]

[484, 0,  377;
  0, 486, 307;
  0,  0,   1]

[644, 0,  393;
  0, 643, 289;
  0,  0,   1]

これらの値は、許容できないほど異なります。与えられたパラメータが何であるかをかなりの精度で知る必要があります。通常、これらの大きな不正確さの原因は何ですか?また、特定のマトリックスの正確性を評価するにはどうすればよいですか? パターンを表示するさまざまな距離と方向に依存しているようですが、パターンの意味がわかりません。

コード:

using namespace cv;
using namespace std;

int main(int, char**)
{
    VideoCapture cap(1);
    if(!cap.isOpened())
        return -1;

    cap.set(CV_CAP_PROP_FRAME_WIDTH,800);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT,600);
    Mat edges;
    Size size(9,17);

    int counter = 10;

    vector<Point2f> corners;
    bool found;

    vector<Point3f> chess = fr::ChessGen::getBoard(size,1,true);

    vector<vector<Point3f> > objectPoints;
    vector<vector<Point2f> > imagePoints;

    Mat camera = Mat::eye(3,3,CV_64F);
    Mat distortion = Mat::zeros(8, 1, CV_64F);
    vector<Mat > rvecs;
    vector<Mat > tvecs;

    namedWindow("edges",1);
    for(;;)
    {
        Mat frame;
        cap >> frame;
        cvtColor(frame, edges, CV_BGR2GRAY);

        found = findCirclesGrid(edges,size,corners
                                ,CALIB_CB_ASYMMETRIC_GRID
                                );
        if(found) frame.convertTo(edges,-1,0.2);

        drawChessboardCorners(edges,size,corners,found);

        imshow("edges", edges);
        if(found){
            if(waitKey(200)>=0){
                objectPoints.push_back(chess);
                imagePoints.push_back(corners);
                if(--counter<= 0)
                    break;
            }
        }
        else waitKey(30);
    }

    calibrateCamera(objectPoints,imagePoints,Size(800,600),camera,distortion,rvecs,tvecs,0);

    if(found) imwrite("/home/ryan/snapshot.png",edges);

    cout << camera << endl;

    return 0;
}
4

4 に答える 4

5

カメラ/レンズと必要な精度によって異なりますが、おそらく 10 を超える位置が必要で、より広い範囲の視野角をカバーする必要があります。

私は 800x600 から、これが歪みの多いシンプルな広角レンズを備えた Web カメラであると想定しています。カメラに対して3〜4の異なる角度のそれぞれで、ターゲットの6〜8の位置/回転が必要だと思います。また、ターゲットとカメラが固定されており、画像中に動かないようにする必要があります。繰り返しますが、カメラに単純なオートゲインがあると仮定すると、ターゲットが十分に照らされていることを確認して、高速シャッター スピードと低ゲインを使用する必要があります。

openCV で使用される技術の問題の 1 つは、フレームを識別してソリューションで使用するには、ターゲット上のすべてのコーナー/ドットを確認する必要があることです。そのため、画像のコーナーの近くをポイントするのは非常に困難です。キャリブレーションで実際に使用された画像の数については、データを確認する必要があります。おそらく、10 枚の画像のうちのいくつかですべてのポイントを見つけ、そのサブセットに基づいてソリューションを作成しているだけです。

于 2012-12-02T18:33:22.963 に答える
3

カメラに対して垂直なパターンだけを撮るのではなく、回転させることも重要です。結果の品質を向上させるために、検出されたコーナーの位置を詳しくチェックし、一部のコーナーが正しく検出されなかった画像を削除して、アルゴリズムを再度実行することもできます。

どのカメラを使用しているかはわかりませんが、カメラの歪みが大きく、シャープさが不十分な場合、コーナーを正しく検出するのが難しくなる可能性があります。OpenCV キャリブレーションは、この場合により良い結果が得られる円パターンでも実現できます。

于 2012-12-05T10:33:05.890 に答える
1

私の経験から、OpenCV が提供する関数 undistort() を使用して、歪みのない画像を使用して調整する必要があります。

つまり、キャリブレーションを 2 回実行し、1 回目はレンズ係数を決定します。次に、2 回目の実行で各チェス盤のフレームの歪みを元に戻します。歪みのないキャリブレーション フレームを使用すると、焦点距離 fx と fy がより正確になります。

于 2015-05-28T13:10:09.280 に答える