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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

OpenCV

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

C++

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

Q&A

解決済

1回答

6638閲覧

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

nuiri1343

総合スコア54

C

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

OpenCV

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

C++

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

0グッド

0クリップ

投稿2018/11/19 09:46

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

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

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

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

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

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

該当のソースコード

C++

1#include"main.h" 2 3 4int main(void) { 5 6 const std::string win_src = "Source"; 7 const std::string win_und = "Undistorted Image"; 8 const std::string file_cam_param = "cam_param.xml"; 9 10 std::vector<Mat> img; 11 const int NUM_IMG = 10; 12 const Size PAT_SIZE(5, 4); 13 float CHESS_SIZE = 1.56; 14 15 std::vector<std::vector<Point3f>> obj_pos(NUM_IMG); 16 std::vector<std::vector<Point2f>> img_pos(NUM_IMG); 17 18 TermCriteria criteria(TermCriteria::MAX_ITER | TermCriteria::EPS, 20, 0.001); 19 20 Mat inner; 21 Mat distort; 22 std::vector<Mat> r_vec; 23 std::vector<Mat> t_vec; 24 25 for (int i = 0; i < NUM_IMG; i++) { 26 std::string fileName = "./calib_img" + std::to_string(i + 1) + ".jpg"; 27 img.push_back(imread(fileName)); 28 } 29 30 for (int i = 0; i < NUM_IMG; i++) { 31 for (int j = 0; j < PAT_SIZE.area(); j++) { 32 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)); 33 } 34 } 35 36 for (int i = 0; i < NUM_IMG; i++) { 37 std::cout << "calib_img" << i + 1 << ".jpg"; 38 imshow(win_src, img[i]); 39 if (findChessboardCorners(img[i], PAT_SIZE, img_pos[i])) { 40 drawChessboardCorners(img[i], PAT_SIZE, img_pos[i], true); 41 imshow(win_src, img[i]); 42 std::cout << " - siccess" << std::endl; 43 waitKey(0); 44 } 45 else { 46 std::cout << " - fail" << std::endl; 47 waitKey(0); 48 return -1; 49 } 50 } 51 52 calibrateCamera(obj_pos, img_pos, img[0].size(), inner, distort, r_vec, t_vec); 53 54 55 56 Mat extr(4, 4, CV_64F); 57 setIdentity(extr); 58 Rodrigues(r_vec[0], extr(Rect(0, 0, 3, 3))); 59 t_vec[0].copyTo(extr(Rect(3, 0, 1, 3))); 60 61 FileStorage fswrite(file_cam_param, FileStorage::WRITE); 62 if (fswrite.isOpened()) { 63 fswrite << "extrinsic" << extr; 64 fswrite << "intrinsic" << inner; 65 fswrite << "distortion" << distort; 66 } 67 fswrite.release(); 68 69 Mat img_undist; 70 for (int i = 0; i < NUM_IMG; i++) { 71 undistort(img[i], img_undist, inner, distort); 72 imshow(win_src, img[i]); 73 imshow(win_und, img_undist); 74 waitKey(0); 75 } 76 77 return 0; 78 79 80 81}

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

Windows10
VisualStudio2017
OpenCV-3.4.2

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Webで調べたところ、openCVにはsolvePnPという関数があるようなのですが、

これは前述したような状況の時に使うものでしょうか?

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

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

cpp

1cv::Mat rvec; 2cv::Mat tvec; 3cv::solvePnP( 4 objectPoints, 5 imagePoints, 6 cameraMatrix, 7 distCoeffs, 8 rvec, 9 tvec);

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

投稿2018/11/19 10:30

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nuiri1343

2018/11/20 04:29

回答ありがとうございます。 solvePnPについてなのですが、 cameraMatrix, distCoeffs, rvec, tvecは それぞれZhangのキャリブレーションにて導出済みなので それを利用すればいいとわかるのですが objectPointsとimagePointsに関しては、 自分で物差しで測ったり等をして変数を用意する必要が あるのでしょうか? solvePnPの使い方について使用例等と同時に説明しているサイトを 探したのですが見つけることができませんでした。
tiitoi

2018/11/20 04:54

ご提示のソースコード内で findChessboardCorners() で imagePoints を求めていて、それに対応した objectPoints も作成していますよね。それと同じやり方で作って渡せばいいです。 rvec, tvec が外部パラメータなので、これは導出したものを渡すのではなく、結果を受け取るための引数を参照渡しするものです。
nuiri1343

2018/11/20 06:19

imagePointsを求めるfindChessboardCorners()は、openCVに元からある関数を利用しているのですが ということは、チェスボードパターンがないとsolvePnPもできないのでしょうか?
tiitoi

2018/11/20 06:25

他に方法はないのかはわかりませんが、基本的にはチェスボードを使って imagePoints は作ります。
nuiri1343

2018/11/21 06:44

チェスボードパターンを画像に写してのsolvePnPの利用が出来ない時、 何かしらの目印となるものを撮影した画像の、目印が写っている画素を手動で計測し、 cv::Point2dの変数のxとyにdouble型の値を代入、 これをimagePointsにpush_backする というやり方ではsolvePnPを実行できませんでしょうか?
fana

2018/11/21 08:55

必要なのはobjectPointsとimagePointsとの対応データなのだから,好きなものを使えば良い.
tiitoi

2018/11/21 15:26

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

2018/11/22 01:33

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

2018/11/22 07:11

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問