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

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

ただいまの
回答率

90.37%

  • C

    4832questions

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

  • C++

    4667questions

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

  • OpenCV

    1621questions

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

Zhangのキャリブレーションを行った後、外部パラメータを求める方法

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 622

nuiri1343

score 48

 前提・実現したいこと、試したこと

Zhangのキャリブレーションを行うプログラム(下記のプログラム)で
内部パラメータ、外部パラメータ、レンズのゆがみ係数を求めることはできました。

しかし、ここで求められた外部パラメータとは、プログラムに与えた1枚目のチェスボードパターンを
撮影した時の外部パラメータです。

例えば、事前にZhangのキャリブレーションで内部パラメータとゆがみ係数を求めておき、
実験する時にその都度、その状態の外部パラメータを算出するというようなことをやりたい場合
どうしたらいいのでしょうか。

その時もまたZhangのキャリブレーションを行わなければならないのでしょうか。

Webで調べたところ、openCVにはsolvePnPという関数があるようなのですが、
これは前述したような状況の時に使うものでしょうか?
しかし、これを使用する場合、どういう値をどういう形で与え、使用すればいいのかわかりませんでした。
もしよろしければ、使い方を詳しく教えていただけないでしょうか。

 該当のソースコード

#include"main.h"


int main(void) {

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

    std::vector<Mat> img;
    const int NUM_IMG = 10;
    const Size PAT_SIZE(5, 4);
    float CHESS_SIZE = 1.56;

    std::vector<std::vector<Point3f>> obj_pos(NUM_IMG);
    std::vector<std::vector<Point2f>> img_pos(NUM_IMG);

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

    Mat inner;
    Mat distort;
    std::vector<Mat> r_vec;
    std::vector<Mat> t_vec;

    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++) {
            obj_pos[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, img_pos[i])) {
            drawChessboardCorners(img[i], PAT_SIZE, img_pos[i], true);
            imshow(win_src, img[i]);
            std::cout << " - siccess" << std::endl;
            waitKey(0);
        }
        else {
            std::cout << " - fail" << std::endl;
            waitKey(0);
            return -1;
        }
    }

    calibrateCamera(obj_pos, img_pos, img[0].size(), inner, distort, r_vec, t_vec);



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

    FileStorage fswrite(file_cam_param, FileStorage::WRITE);
    if (fswrite.isOpened()) {
        fswrite << "extrinsic" << extr;
        fswrite << "intrinsic" << inner;
        fswrite << "distortion" << distort;
    }
    fswrite.release();

    Mat img_undist;
    for (int i = 0; i < NUM_IMG; i++) {
        undistort(img[i], img_undist, inner, distort);
        imshow(win_src, img[i]);
        imshow(win_und, img_undist);
        waitKey(0);
    }

    return 0;



}

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

Windows10
VisualStudio2017
OpenCV-3.4.2

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

Webで調べたところ、openCVにはsolvePnPという関数があるようなのですが、
これは前述したような状況の時に使うものでしょうか?

外部パラメータのみ推定する場合は、solvePnP() でよいです。
使い方は 公式リファレンス を参照してください。

  • objectPoints: 3次元上の点一覧
  • imagePoints: キャリブレーションボードで検出した画像座標の点一覧
  • cameraMatrix: すでに求めてあるカメラ行列
  • distCoeffs: すでに求めてある歪み係数
  • rvec: 回転ベクトル
  • tvec: 平行移動ベクトル
cv::Mat rvec;
cv::Mat tvec;
cv::solvePnP(
    objectPoints,
    imagePoints,
    cameraMatrix,
    distCoeffs,
    rvec,
    tvec);

回転 rvec は回転ベクトルなので、、回転行列の形式でほしければ、cv::Rodrigues() で変換できます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/22 00:26

    fana さんがおっしゃるように面倒ですが手動でやってもできると思います。

    キャンセル

  • 2018/11/22 10:33

    リファレンス見てたら,solvePnPRansac というのもあるみたいですね.
    (「目印」から得られるデータの個数と「手動で計測」の精度次第ではこっちを使ってみるという手もありそう)
    あと,solvePnPはrvec,tvecを初期値として使えるみたいなので,何か(ある程度良い)近似値が存在するような場面であれば,初期値指定を試してみても良いかも.

    キャンセル

  • 2018/11/22 16:11

    ありがとうございます。
    できそうな気がします。
    助かりました!

    キャンセル

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

  • ただいまの回答率 90.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

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

  • C

    4832questions

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

  • C++

    4667questions

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

  • OpenCV

    1621questions

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