質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • C

    4543questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    4445questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • OpenCV

    1518questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

opencvのZhangのキャリブレーションが合っているのかどうか

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 408

nuiri1343

score 46

 前提・実現したいこと

OpenCVを使って、Zhangのキャリブレーションを行い、内部パラメータと外部パラメータを求めたいです。

求めるところまではできましたが、結果得られたパラメータが合っているのかすごく心配です。

以下のソースコード(一般的なZhangのキャリブレーションを実行するプログラムです)でZhangのキャリブレーションを行いました。
この時使用した画像の一枚目がこれです。
1枚目の画像(原画像)

この画像に、findChessboardCornersとdrawChessboardCornersを実行した結果得られた画像がこれです。
1枚目の画像(コーナー検出後)

そして、今回のキャリブレーションによって得られたパラメータのうち、回転行列と並進ベクトルが以下のようになりました。

回転行列 : 
[0.8864976089930998, -0.2546690562624887, 0.3863491439512847;
0.06027432266890168, 0.8913665284993816, 0.4492579636442369;
-0.4587907968522497, -0.3749791776263512, 0.8055443011221314]

並進ベクトル
[-95.4959092690081;
-97.60717747135726;
452.887102880167]

この二つのパラメータ(外部パラメータ)は、上で載せた1枚目のチェスボードパターン画像の回転行列と並進ベクトルです。

しかし、この並進ベクトルがおかしいのではないかと思います。
なぜなら、ワールド座標の座標軸は、画像のチェスボードパターンの左上の交点を原点として、
右方向にx軸、下方向にy軸、手前から奥に向かってz軸なので(OpenCVは右手座標系なので)
カメラのある位置と全く違う位置を示しているように思えるのです。

少なくとも、チェスボードパターンの左側にカメラはありませんし、チェスボードパターンの上側にもありません。
ましてや、チェスボードパターンの裏側にカメラがあるなどありえないと思うのです。

再投影誤差は0.409436でした。
一枚目の画像の再投影誤差は0.261726でした。
あまり誤差があるとは思えないのですが
何か解釈が間違っているのでしょうか?

お詳しい方、どうか教えてください。
よろしくお願いします。

 該当のソースコード

int main(void) {

    const std::string win_src = "Source";
    const std::string win_und = "Undistorted Image";
    const std::string file_cam_param = "camera_param.xml";

    std::vector<Mat> img;
    const int NUM_IMG = 9;
    const Size PAT_SIZE(13, 9);
    float CHESS_SIZE = 18.8;

    std::vector<std::vector<Point3f>> objectPoints(NUM_IMG);
    std::vector<std::vector<Point2f>> imagePoints(NUM_IMG);

    TermCriteria criteria(TermCriteria::MAX_ITER | TermCriteria::EPS, 20, 0.001);

    Mat cameraMatrix;
    Mat distCoeffs;
    std::vector<Mat> rvec;
    std::vector<Mat> tvec;

    for (int i = 0; i < NUM_IMG; i++) {
        std::string fileName = "./calib_img" + std::to_string(i + 1) + ".jpg";
        img.push_back(imread(fileName));
    }

    for (int i = 0; i < NUM_IMG; i++) {
        for (int j = 0; j < PAT_SIZE.area(); j++) {
            objectPoints[i].push_back(Point3f(static_cast<float>(j%PAT_SIZE.width*CHESS_SIZE), static_cast<float>(j / PAT_SIZE.width*CHESS_SIZE), 0.0));
        }
    }

    for (int i = 0; i < NUM_IMG; i++) {
        std::cout << "calib_img" << i + 1 << ".jpg";
        imshow(win_src, img[i]);
        if (findChessboardCorners(img[i], PAT_SIZE, imagePoints[i])) {
            drawChessboardCorners(img[i], PAT_SIZE, imagePoints[i], true);
            imshow(win_src, img[i]);
            std::cout << " - siccess" << std::endl;
            waitKey(0);
        }
        else {
            std::cout << " - fail" << std::endl;
            waitKey(0);
            return -1;
        }
    }

    double result = calibrateCamera(objectPoints, imagePoints, img[0].size(), cameraMatrix, distCoeffs, rvec, tvec);
    std::cout << "result:" << result << std::endl;


    for (int i = 0; i < (int)objectPoints.size(); i++) {
        std::vector<Point2f> imagePoints2;
        projectPoints(objectPoints[i], rvec[i], tvec[i], cameraMatrix, distCoeffs, imagePoints2);
        double error = cv::norm(imagePoints[i], imagePoints2, cv::NORM_L2);
        error = std::sqrt(error * error / (int)objectPoints[i].size());
        std::cout << "error" << i + 1 << ":" << error << std::endl;

    }



    Mat rmat;
    Rodrigues(rvec[0], rmat);

    Mat extr(4, 4, CV_64F);
    setIdentity(extr);
    Rodrigues(rvec[0], extr(Rect(0, 0, 3, 3)));
    tvec[0].copyTo(extr(Rect(3, 0, 1, 3)));



    FileStorage fswrite(file_cam_param, FileStorage::WRITE);
    if (fswrite.isOpened()) {
        fswrite << "cameraMatrix" << cameraMatrix;
        fswrite << "distCoeffs" << distCoeffs;
        fswrite << "rvec" << rvec[0];
        fswrite << "rmat" << rmat;
        fswrite << "tvec" << tvec[0];
        fswrite << "extr" << extr;
    }
    fswrite.release();

    Mat img_undist;
    for (int i = 0; i < NUM_IMG; i++) {
        undistort(img[i], img_undist, cameraMatrix, distCoeffs);
        imshow(win_src, img[i]);
        imshow(win_und, img_undist);
        //imwrite("undistort_img" + std::to_string(i + 1) + ".jpg", img_undist);    
        waitKey(0);
    }

    return 0;



}

 補足情報(FW/ツールのバージョンなど)

Windows10
VisualStudio2017
Opencv-3.4.2

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

外部パラメータの意味が異なるのではないでしょうか.

別の質問:
画素のカメラに対する角度を求めたい
で引用した式では,外部パラメータ(R,t)は

カメラ座標 = R * ワールド座標 + t

となっています.

  • tとは,ワールド原点をカメラ座標系で書いたもの
  • Rの各行ベクトルが,カメラ座標系の基底ベクトルをワールド座標系で書いたもの
  • Rの各列ベクトルが,ワールド座標系の基底ベクトルをカメラ座標系で書いたもの

ではないかと.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • C

    4543questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    4445questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • OpenCV

    1518questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。