2014年2月3日月曜日

opencvでステレオカメラのキャリブレーションを行う1

カメラの内部、外部パラメータを計測するプログラムをC++とOpenCVで組んでみた。
参考にしたサイトはこのチュートリアル
OpenCVの関数を組み合わせて行けば簡単にできるはずだけど、上のチュートリアルはいろいろと手が混んでちょっと分かりにくかった。
今回は以下の2つの手順を踏んた。

  1. チェスボードの検出とそのコーナーの保存
  2. 検出したコーナーを使ってカメラの内部パラメータを求める。
1はfindChessboardCorners()を2はcalibrateCamera()を使えばよい。生成物はyaml形式でファイルに保存しとく。findChessboardCorners()は3500x2000の画像で1分くらいかかったので数が多いと何度も回すのは結構時間がかかる。yamlでの保存はFileStorageというクラスが準備されているので、これを使うと簡単にファイルでのやり取りができることがわかった。ここを参考にした。

まずはチェスボードの検出。findChessboardCornersの後にcornerSubPixを実行。これを行えば精度が上がるらしい。上がcornerSubPixを行わなかった場合。下が行った場合。確かに精度は良くなっている。時間も全然かからないのでやって損はないだろう。



ソースはこんな感じになった。
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;

int main() {
        
    Size patternsize(9, 6);
    vector<Point2f> corners;
    Mat src = imread("chessboard/image.JPG");

    //find chessboard corners
    std::cout << "finding chessboard corners..." << std::endl;
    bool found = findChessboardCorners(src, patternsize, corners, 
        CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE 
        + CALIB_CB_FAST_CHECK);

    //find more precise corners.
    if(found) {
        std::cout << "found. finding corners in sub-pixel accuracy..." << std::endl;
        Mat gray;
        cvtColor(src, gray, CV_BGR2GRAY);
        cornerSubPix(gray, corners, Size(9, 6), Size(-1, -1),
                    TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
        drawChessboardCorners(src, Size(9,6), corners, found);
    } else {
        std::cout << "not found." << std::endl;
    }
    std::cout << "done." << std::endl;
}

2へ続く。



0 件のコメント:

コメントを投稿