サイトアイコン NegativeMindException

2D→3D復元技術で使われる用語まとめ

2次元の画像から3次元の情報を復元するプログラムを本格的に実装してみようと思って、まずはOpenGVから触り始めたんだけど、オイラの基礎知識が乏し過ぎて苦戦中。



まだOpenGVに同梱されているtestコードをいじってみている段階。オイラはこの分野の基本的な用語の知識が欠けているので、OpenGV独自の抽象化APIで使われる言葉との区別もつかず、公式ドキュメントを読むだけでだいぶ苦労する。(ドキュメント自体はそれほど文量多くないけど)

ということで、まずはこの分野で使われる言葉の意味をちゃんと知っておこうと思います。この分野は「エピポーラ幾何(Epipolar geometry)」とか「エピ極線幾何学」って呼ぶんですかね。
ライブラリの公式ドキュメントは英語なので、英語表記と日本語表記の対応もちゃんとおさえておく。OpenMVG公式の機能一覧cameras, multiviewの解説と図がシンプルで分かりやすかったので引用しながらまとめる。
openMVG:複数視点画像から3次元形状を復元するライブラリ
最近、この手の2D→3D復元系のライブラリを色々と調べている。何となく、自分で3D復元ツールを作ってみたくてね。 この間のOpenGVは複数画像からカメラ(視点)の3次元位置・姿勢を推定するライブラリだった↓ こっちのopenMVG(Mul...


数学的な定義よりも画像処理での用途寄りに書いていきますが、間違ってたらごめんなさい。(ご指摘いただけると有難い)


Pinhole Camera Model:ピンホールカメラモデル

カメラは図のようなピンホールカメラモデルと呼ばれる単純な投影モデルで近似することができ、2D→3D復元の様々なアルゴリズムは基本的にこのモデルに基づいている。
ピンホールカメラモデルでは、カメラの射影行列(3D→2D)をintrinsic parameters(内部パラメータ)extrinsic parameters(外部パラメータ)の2つの行列で表す。内部パラメータは3D→2Dの投影関係、外部パラメータはカメラの3D空間での位置・向きを定義する。
上の図は、3Dのワールド座標をカメラで撮影することで2Dのスクリーン座標へ投影する様子を表している。

Homography:ホモグラフィ

画像認識におけるHomographyとは、2D空間同士の射影変換のこと。
(一般的には、射影変換全般をHomographyと呼ぶ)

図で赤く示されているような3D空間上のある平面について、2つのカメラから撮影した画像では、同じ頂点でも2枚の撮影画像上ではそれぞれ別の2D空間の座標となる。この2つのカメラ画像の2D座標の対応関係は2Dの射影変換(平面を別の平面へ射影する)で表すことができる。
このような、平面の座標系から別の平面の座標系へ変換する2D→2Dの射影変換行列がHomography行列H(3×3の行列)となる。

OpenCVだとcv::findHomography関数を使えば2枚の画像間のHomography行列を推定することができる↓
http://qiita.com/wakaba130/items/b566f15a4f2cf1ce414f

Homography行列の算出には、対応点が最低でも6点(全て同一平面上なら4点)必要だそうです。
https://qiita.com/tomoaki_teshima/items/dc49a1431562da4da436

Fundamental Matrix:基礎行列

Fundamental Matrix(基礎行列)は同一のシーンを撮影している2つのカメラ画像の関係を表す3×3の行列。カメラ画像中の点をもう1つのカメラ画像のスクリーン座標へ変換する2D-2Dの座標変換を行うことができる。基礎行列Fと表記されたりします。Fundamental Matrix(基礎行列)は2焦点テンソル(bifocal-tensor)とも呼ばれるとか。

OpenCVならcv::FindFundamentalMat関数を使えば2枚の画像からFundamental Matrix(基礎行列)を推定することができるらしい。

基礎行列の歌なんてのもあるようですよ↓


Essential Matrix:基本行列

図のように、2つのカメラの3D空間上の相対的な関係は、回転行列R(3×3の行列)と並進ベクトルt(3×1の行列)で表すことができる。この回転行列Rと並進ベクトルtはカメラの3D空間での位置・姿勢を表すもので、この図ではRtで2つのカメラの相対的な位置・姿勢を表します。

Essential Matrix(基本行列)は、このRtを1つにまとめた4×4の行列のこと。この基本行列は3D→3Dの変換を行う変換行列で、2つのカメラ間の対応を表す基本行列を使えば、のカメラ空間(3D)で表された座標をのカメラ空間で表された座標へ変換することできる。

ここで、行列をワールド空間の絶対座標で表せばカメラのextrinsic parameters(外部パラメータ)そのものになります。ちなみに、カメラのintrinsic parameters(内部パラメータ)となる行列はKと表記されたりもします。(何故Kなのでしょう?)
基本行列Eは基礎行列Fに内部パラメータKを与えることで導出できます。

OpenCVだと、このEssential Matrix(基本行列)cv::findEssentialMat関数を使えば算出できます。これは、いわゆる5点アルゴリズム(five-point algorithm)というやつで、計算するには対応点が5点以上必要となります。
また、cv::recoverPose関数cv::decomposeEssentialMat関数を使ってEssential Matrix(基本行列)を回転行列Rと並進ベクトルtへ分解することもできます。



スポンサーリンク

Resection/Pose Estimation:キャリブレーション/姿勢推定

Camera Resectionとは、いわゆるカメラキャリブレーションのことです。
カメラのキャリブレーション、カメラの姿勢を推定するにはワールド座標とスクリーン座標の3D-2Dの点の対応情報が必要です。推定したカメラパラメータを用いて3D→2Dの変換を行い、事前に与えたスクリーン座標との差を算出します。この差(残留誤差)が最小となるよう最適化することでカメラパラメータを求めます。

Triangulation:三角測量

CG屋は”Triangulation“と言うと三角形分割と訳してしまいそうですが、ここでは三角測量を意味します。
カメラの位置・姿勢、内部パラメータ、画像間の2D-2Dの対応の情報が既知であれば、三角測量の原理に基づいて対応点の三次元座標を推定することができます。

OpenCVには三角測量による三次元座標の計算を行うためのcv::triangulatePoints関数があります。


感想

とりあえず、今オイラが理解している情報を書いてみた。(後半ちょっと雑になりましたが)
今後も随時加筆修正していこうと思う。

こうしてまとめて見ると、OpenCVはその分野についての用語を知っていれば大体使えるようにAPIが上手く抽象化されているのが分かる。画像認識について体系的に学んだ人にとっては扱うのチョロいんだろうなぁ。
逆に、適切に抽象化されたAPIを使っているとその分野の体系が分かってくるとも言えるのかな。学ぶ上での教材としてこういうのは大事かも。これはエンジニア(プログラマ)流の学び方かもしれない。

追記:すごくいいまとめ記事↓
http://qiita.com/ykoga/items/14300e8cdf5aa7bd8d31

http://news.mynavi.jp/series/cv_future/006/
http://news.mynavi.jp/series/cv_future/008/
http://news.mynavi.jp/series/cv_future/009/
http://news.mynavi.jp/series/cv_future/010/

参考書

調べていたら、どうやらMultiple View Geometry in Computer Visionという洋書があるらしく、この書籍には2D→3D復元技術のことが体系的にまとまっているようです。



でもお高いです。。。
追記:本書の一部はPDFで無料公開されている↓
http://www.robots.ox.ac.uk/~vgg/hzbook/

追記:最近出たこちらの書籍はそのものズバリ、3次元コンピュータービジョンを体系的に学べるようになっています。かなり教科書っぽいので、それなりに覚悟は必要です↓



ピンホールカメラモデルとキャリブレーションについてはOpenCV 2 プログラミングブックのChapter4の2.1にもサンプルコードも合わせて解説が載っている。サンプルコードはサポートサイトから。



http://qiita.com/tunepolo/items/76058121238be386bb21

2D-3D対応からのカメラ位置・姿勢の推定する、いわゆるPnP問題(Perspective-n-Pont Problem)をOpenCVで解く方法についてはOpenCV3対応のこちらが詳しい↓



同様にサンプルコードはサポートページからダウンロードできる。

追記:OpenCV3公式のカメラキャリブレーションと3次元復元の解説ドキュメントの日本語訳を掲載しているサイトを見つけた↓
http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_calib3d/py_table_of_contents_calib3d/py_table_of_contents_calib3d.html

2019年6月 追記:SSII 2019でカメラキャリブレーションのチュートリアルがあった↓


スポンサーリンク

関連記事

  • Leap MotionでMaya上のオブジェクトを操作できるプラグイン
  • 映画『アバター:ウェイ・オブ・ウォーター』を観た
  • OpenMVSのサンプルを動かしてみる
  • 画像認識による位置情報取得 - Semi-Direct Monocular Visual Odome...
  • CGAN (Conditional GAN):条件付き敵対的生成ネットワーク
  • Open3D:3Dデータ処理ライブラリ
  • OpenMayaのPhongShaderクラス
  • MythTV:Linuxでテレビの視聴・録画ができるオープンソースプロジェクト
  • Raspberry Pi
  • iOSデバイスのためのフィジカル・コンピューティングツールキット『konashi(こなし)』
  • KelpNet:C#で使える可読性重視のディープラーニングライブラリ
  • UnityのTransformクラスについて調べてみた
  • ROMOハッカソンに行ってきた
  • Kinect for Windows v2の日本価格決定
  • OpenCVの三角測量関数『cv::triangulatepoints』
  • 映画『ジュラシック・ワールド/新たなる支配者』を観た
  • スター・ウォーズのスピンオフ『マンダロリアン』の舞台裏
  • ZBrushで作った3Dモデルを立体視で確認できるVRアプリを作る
  • GoogleのDeep Learning論文
  • Raspberry Pi 2を買いました
  • OpenSfM:PythonのStructure from Motionライブラリ
  • OpenCVのfindEssentialMat関数を使ったサンプルを読んでみる
  • サンプルコードにも間違いはある?
  • Kaolin:3Dディープラーニング用のPyTorchライブラリ
  • Math Inspector:科学計算向けビジュアルプログラミングツール
  • タマムシっぽい質感
  • ニューラルネットワークと深層学習
  • オープンソースの顔の動作解析ツールキット『OpenFace』
  • ポリゴンジオメトリ処理ライブラリ『pmp-library (Polygon Mesh Process...
  • Unityからkonashiをコントロールする
  • 顔追跡による擬似3D表示『Dynamic Perspective』
  • Deep Fluids:流体シミュレーションをディープラーニングで近似する
  • Point Cloud Consortiumのセミナー「3D点群の未来」に行ってきたよ
  • 『ローグ・ワン/スター・ウォーズ・ストーリー』"あのキャラクター"のメイキング
  • 『スター・ウォーズ 最後のジェダイ』のVFXブレイクダウン まとめ
  • 池袋パルコで3Dのバーチャルフィッティング『ウェアラブル クロージング バイ アーバンリサーチ』
  • pythonもかじってみようかと
  • iPhone x ロボットハッカソン~RomoのiPhone用SDKで目覚ましアプリを作る~
  • 3分の動画でプログラミングを学習できるサイト『ドットインストール』
  • Adobeの手振れ補正機能『ワープスタビライザー』の秘密
  • PCA (主成分分析)
  • Facebookの顔認証技術『DeepFace』
  • モバイルバージョンを終了