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

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



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

ということで、まずはこの分野で使われる言葉の意味をちゃんと知っておこうと思います。この分野は「エピポーラ幾何(Epipolar geometry)」とか「エピ極線幾何学」って呼ぶんですかね。
ライブラリの公式ドキュメントは英語なので、英語表記と日本語表記の対応もちゃんとおさえておく。OpenMVG公式の機能一覧cameras, multiviewの解説と図がシンプルで分かりやすかったので引用しながらまとめる。
openMVG:複数視点画像から3次元形状を復元するライブラリ
最近、この手の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(基礎行列)を推定することができるらしい。

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


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


スポンサーリンク

関連記事

DensePose:画像中の人物表面のUV座標を推定する
GAN (Generative Adversarial Networks):敵対的生成ネットワーク
iOSデバイスと接続して連携するガジェットの開発方法
Verilog HDL
第25回コンピュータビジョン勉強会@関東に行って来た
ROSの薄い本
AnacondaとTensorFlowをインストールしてVisual Studio 2015で使う
Unity ARKitプラグインサンプルのチュートリアルを読む
WordPressプラグインによるサイトマップの自動生成
池袋パルコで3Dのバーチャルフィッティング『ウェアラブル クロージング バイ アーバンリサーチ』
Model View Controller
OANDAのfxTrade API
Kinect for Windows v2の日本価格決定
Raspberry PiでIoTごっこ
動的なメモリの扱い
AfterEffectsプラグイン開発
ベイズ推定とグラフィカルモデル
AmazonEC2のインスタンスをt1.microからt2.microへ移行する
SONY製のニューラルネットワークライブラリ『NNabla』
Google Chromecast
libigl:軽量なジオメトリ処理ライブラリ
Cartographer:オープンソースのSLAMライブラリ
Unityで強化学習できる『Unity ML-Agents』
Web経由でRaspberry PiのGPIOを操作したい
ポイントクラウドコンソーシアム
UnrealCV:コンピュータビジョン研究のためのUnreal Engineプラグイン
Open3D:3Dデータ処理ライブラリ
HD画質の無駄遣い
機械学習で遊ぶ
python-twitterで自分のお気に入りを取得する
Windows10でPyTorchをインストールしてVSCodeで使う
pythonの機械学習ライブラリ『scikit-learn』
書籍『ゼロから作るDeep Learning』で自分なりに学ぶ
UnityでPoint Cloudを表示する方法
OpenMVS:Multi-View Stereoによる3次元復元ライブラリ
OpenCVでカメラ画像から自己位置認識 (Visual Odometry)
UnityからROSを利用できる『ROS#』
SegNet:ディープラーニングによるSemantic Segmentation手法
Mayaのレンダリング アトリビュート
Point Cloud Libraryに動画フォーマットが追加されるらしい
Adobeの手振れ補正機能『ワープスタビライザー』の秘密
OpenGVの用語

コメント