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

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



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

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


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


スポンサーリンク

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

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

Homography:ホモグラフィ

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

図で赤く示されているような3D空間上のある平面について、2つのカメラO_LO_Rから撮影した画像では、同じ頂点でも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(基礎行列)を推定することができるらしい。

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

基礎行列の歌 (The Fundamental Matrix Song)

Essential Matrix:基本行列

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

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

ここで、行列[R|t]をワールド空間の絶対座標で表せばカメラの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復元技術のことが体系的にまとまっているようです。

Multiple View Geometry in Computer Vision

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

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

3次元コンピュータビジョン計算ハンドブック

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

OpenCV 2 プログラミングブック OpenCV 2.2/2.3対応

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

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

OpenCV 3 プログラミングブック

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

追記: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でカメラキャリブレーションのチュートリアルがあった↓


スポンサーリンク

関連記事

COLMAP:オープンソースのSfM・MVSツール
Deep Fluids:流体シミュレーションをディープラーニングで近似する
動的なメモリの扱い
オープンソースのSLAMライブラリ『Cartographer』
続・ディープラーニングの資料
Raspberry Pi
Russian3DScannerのトポロジー転送ツール『WrapX』
SSD (Single Shot Multibox Detector):ディープラーニングによる一般...
クラスの基本
ブログのデザイン変えました
オープンソースのロボットアプリケーションフレームワーク『ROS (Robot Operating S...
SDカードサイズのコンピューター『Intel Edison』
Raspberry Pi 2のGPIOピン配置
OpenCVのための軽量GUIライブラリ『cvui』
スクラッチで既存のキャラクターを立体化したい
機械学習について最近知った情報
AMIMOTO(PVM版)で作成したインスタンスをAMIMOTO (HVM版)へ移行する
adskShaderSDK
WordPressのサーバ引っ越し方法を考える
スクレイピング
写真から3Dメッシュの生成・編集ができる無料ツール『Autodesk Memento』
AfterEffectsプラグイン開発
OpenCVで動画の手ぶれ補正
Unityで画面タッチ・ジェスチャ入力を扱う無料Asset『TouchScript』
Unityの各コンポーネント間でのやり取り
Google XML Sitemap Generatorプラグインを3.4.1へダウングレード
AndroidもopenGLも初心者さ (でもJavaは知ってるよ)
Unity ARKitプラグインサンプルのドキュメントを読む
konashiのサンプルコードを動かしてみた
3Dボリュームデータ処理ライブラリ『OpenVDB』
U-Net:ディープラーニングによるSemantic Segmentation手法
書籍『OpenCV 3 プログラミングブック』を購入
CGのためのディープラーニング
C#で使える遺伝的アルゴリズムライブラリ『GeneticSharp』
Fast R-CNN:ディープラーニングによる一般物体検出手法
BlenderでPhotogrammetryできるアドオン
Seleniumを使ったFXや株の自動取引
Google App Engine上のWordPressでFlickrの画像を貼る
フォトンの放射から格納までを可視化した動画
Unityで使える数値計算ライブラリ『Math.NET Numerics』
FCN (Fully Convolutional Network):ディープラーニングによるSema...
定数

コメント