2009年3月アーカイブ

PTAMの問題点の1つに、「マップの3D座標空間が勝手に決められてしまう」というものがあります。

3D座標空間は、初期化完了時に出るグリッド平面で表されます。
これはCGにとっては「地面」を意味しているので、地面が正しい位置にないとCG表示もおかしくなってしまいます。
(例えば、垂直な壁が地面になってしまう等)


この問題を解決するには、地面の決定に別な方法を使う必要があります。例えば、
  • ユーザーのコントロールによって、地面の位置や方向を再調整する。
  • 加速度センサーでカメラの下方向を認識、そのベクトルにほぼ垂直で、面を形作っている特徴点の集合を探す
  • 地面の位置に目印を置いて、それを認識させる。
などが考えられます。


ここで、上記の項目に何か見覚えがあるものが入っています。それは、「目印」の認識です。
これは、今まで散々使ってきたARToolKitを使えば簡単にできそうです。



----- < ライセンスの問題 > -----

ですが、ARToolKitの利用には、ライセンス面で大きな問題があります。
ARToolKitのライセンスはGPLになっています。
そして、PTAMのライセンスもGPLに近く、しかしこれとは異なるライセンスとなっています。

この2つのソースを一緒にし、そして実行ファイルやソースコードを公開した場合には、2つのライセンスが完全に重なってしまい、ライセンス違反となる危険性があります。
なので、現在のバージョンでは、実行ファイルやソースコードの公開は行えません。


では、出力結果のみを公開する場合はどうでしょうか?
GPLでは、出力結果のみの公開で(条件はありますが)ソースコードの公開義務は発生せず、問題は起きません。
PTAMの、出力結果を公開する場合では、それがPTAMから出力されたことを明記する必要があるようです。

これならば、PTAM+ARToolKitを実行し、その動画を公開した場合には問題がないように思えます。



----- < PTAMでのマーカー認識 > -----

さて、PTAMにてマーカーの認識処理を加える場合、どういった処理が考えられるでしょうか?
  1. PTAMのマップ座標系を、マーカーから得られた3Dワールド座標系に合わせる
  2. 2次元画像内で、マーカーの四角の頂点位置を計算して、特徴点のリストに追加する
1の場合は、マーカー座標系をマップ座標系にうまく変形し、合わせてやる必要があります。こちらの方が正確ですが、座標系の違いを調査するのに手間がかかります。
2の場合は、マーカーの頂点だけ、他の特徴点とは別な処理を行う必要があります。こちらは逆に簡単ですが、正確性に欠ける場合があります。

理想的には1番なのですが、とりあえず最初に2番で実装してみます。



----- < 実際の変更点 > -----

PTAMのソースにARToolKitの処理を入れます。
2番では、ARToolKitマーカーの認識処理であるarDetectMarkerをPTAM内で呼ぶことになります。

  • PTAMプロジェクトにARToolKitの必要なプロジェクトを追加する

  • PTAMのループ内で、arDetectMarkerを呼ぶようにする。

  • arDetectMarkerの実行結果から、マーカーの頂点座標の値を取得する。

  • 取得した頂点座標を、Tracker::TrackForInitialMap()内の特徴点のステレオペアを格納しているところに入れてやる。

  • さらにその中で、MapMaker::InitFromStereo()が呼ばれているので、そこでステレオ計算させる。

  • ステレオ計算され、3次元情報の点になったら、その4点から基準となる座標系を作成する。

  • 作成したマーカー座標系使って、MapMaker::CalcPlaneAligner()内でグリッド平面の位置合わせを行う。

  • 変形されたグリッド座標系に合わせるように、MapMaker::ApplyGlobalTransformationToMap()でマップ上の点が変形させられる。
といったような修正内容になります。



追記(2009/03/31 22:56)

目印は平面であることが分かれば十分なので、SIFTなどの特徴点認識が利用できるかもしれません。
さらに、初期化を行うときの特徴点を平面に固定してしまうなど、いろいろ考えられます。

まぁ目印があればとても分かりやすく、場合によってはPTAMの初期化がいらなくなるので、楽かもしれません。



PTAMは優れたプログラムですが、問題点もいくつかあります。
その1つは、実行にある程度のスペックを必要とすることです。

現在発売されている通常の価格帯のPCであれば、このスペック不足はほとんど問題ありません。
しかし、PTAMをEeePCのような低価格PCや、w-zero3のような携帯端末で実行しようと、これが大きな問題となります。


そこで、その解決方法のうちの1つとして、別スレッドで実行されている「マップの更新」をスレッドで行わずに、
ユーザーの操作によって発生するイベントとして処理する方法を試してみます。


お気づきの方もいると思いますが、このような処理を行った場合、このプログラムは最早PTAM(Parallel Tracking and Mapping)とは言えず、STAM(Serial Tracking and Mapping)(なんじゃそりゃ)になってしまいます。

なので、本末転倒な気がしますが、たとえマップの更新が自動じゃなくても、その他のPTAMの機能はとても魅力的なものです。
これを携帯端末などで動かすことができれば、楽しいことができそうだと考え、改良してみることにしました。




---- < マップの更新処理に必要なもの > ----

この改良で重要なのが、「マップの更新がどのように行われるか?」ということです。
PTAMの解析でも大まかに説明しましたが、マップに特徴点を追加するにはキーフレームが必要になります。

ここで、キーフレームの決め方には2つ方法があります。
1.マップの初期化時に、ユーザーがスペースキーを押した時のフレーム(2個)が、キーフレームとして保存される。
2.マップをトラッキングしている時に、よりキーフレームに適したフレームが、自動的にキーフレームとして選ばれる。

1で決まった2つのキーフレームでは、特徴点のステレオ計算が行われて、3D座標としてマップに追加されます。
2で決まった1つのキーフレームは行列に入れられ、マップの更新スレッドが実行される度に一つずつマップに追加されます。



---- < キーフレームの追加方法 > ----


ということで、更新を手動で行う場合のキーフレームの追加方法も、2つあるということになります。
それは、ユーザーが決める方法と、自動で決めさせる方法です。

・ユーザーが決める場合: 初期化時と同じように、ユーザーが適切なキーフレームを選べるような手助けをしてあげなくてはいけません。
・自動で決めさせる場合: 適切なキーフレームが選ばれますが、それは現在見ている画像とは違うフレームになります。

さて、どちらを選ぶのがより良いでしょうか?
ちなみにPTAMの初期化作業は結構面倒で、慣れないと失敗します。対して、自動の場合はボタン1回押しで済み、フレームの違いも大きな問題にはなりません。

結果、後者の自動キーフレーム生成を選択しました。
キーフレームが追加できたら、あとは任意のタイミングでマップの更新処理を行ってやるだけです。



---- < ソースの変更点 > ----


では実際に、PTAMを改良していきます。

  • 最初にマップ更新スレッドを切らなくてはいけません。マップ更新のスレッドはMapMakerクラスで行われています。
    このクラスはCVD::Threadを継承しているので、この継承関係をコメントアウトします。

  • 継承を切ってしまうと、そのままコンパイルした時にエラーが出るので、必要ないもの(run()など)もコメントアウトします。

  • ここで、MapMaker::Reset()を行わないようにしてしまうと、マップのリセットなども行われず、プログラムが動きません。
    この関数もどこかで呼ばれるようにしましょう。(MapMaker::RequestReset()が呼ばれる所など)

  • キーフレームをマップに追加する処理は、MapMaker::AddKeyFrameFromTopOfQueue()で行われます。
    これを任意のタイミング(スペースキー押下時など)に実行するようにします。

  • このままだと、マップの修正処理が行われないので、MapMaker::BundleAdjustAll()などのマップ調整関数も、更新後に行われるようにしましょう。
大雑把な変更点はこんな感じになります。プログラミングの知識があり、PTAMの大まかな処理を理解できていれば、さほど難しくないと思われます。


PTAMの解析 - 4 動画の公開

|
PTAMの解析が進み、処理の全体像がなんとなく理解できてきたので、
PTAMプログラムへの入門として、動画を作成しました。




解説動画としては、情報が足りませんが、足がかりとして見ていただければと思います。

もう少し詳しい情報のページ:
http://render.s73.xrea.com/pipe_render/2009/03/ptam-1.html
http://render.s73.xrea.com/pipe_render/2009/03/ptam-2.html
http://render.s73.xrea.com/pipe_render/2009/03/ptam-3.html

BGM:エコテロニカ(sansuiさん)
前回の処理プロセス概要に、該当するソースの関数名を割り振り、遷移図にしました。

この図は、PTAMのソースをそのまま図に書いたものでないということに注意してください。
論文での主要な処理に合わせて、ソースの処理はいくつか省かれています

--------- < メイン処理 > ---------
以下の処理をループさせます。
ptam_frow_01.gif
--------- < 1.マップの初期化 > ---------ptam_frow_01.gif
--------- < 2.トラッキング > ---------

ptam_frow_01.gif
--------- < 3.マップの更新 > ---------
これはスレッドで実行され、ステレオの初期化以下がループします。
ptam_frow_01.gif
2回目は、PTAMの処理プロセスの概要です。

また概要になります、すいません。
各プロセスの詳細は、後々解説していこうと思います。



--------- < 処理プロセスについて > ---------

PTAMでの処理は、大きく分けて次のようなものがあります。

1.マップの初期化
2.トラッキング
3.マップの更新


○1のマップの初期化は、一番最初に行われる作業です。
PTAMの動画を見ていると分かりますが、最初にバッチ処理っぽいことを行っています。
この時の画像を元にマップが構築されて、これが基本のマップになります。

○2のトラッキングでは、このマップを元にカメラの位置・姿勢(方向)の推定が行われます。
この処理はスレッドで行われ、coarse-to-fineという手法が用いられます。

coarse-to-fine:最初に大まかなマッチングを行い、大体の位置を確定できたら、次に細かいマイッチングを行って計測を確定するといったような手法です。

○3のマップの更新も別のスレッドで実行され、そのループの先頭では新しいキーフレームを探します。
キーフレームとは、トラッキングがうまくいって、より正確な特徴点が取得できたフレームのことです。たキーフレームは、それぞれある程度離れたものが選択されます。

キーフレームが見つかったら、それを使ってマップを更新します。
マップ上の各特徴点を修正し、新しい特徴点が見つかったらマップに追加します。

キーフレームがない場合は、マップの調整を行います。
バッチ処理でマップ内の特定の範囲を調べて、複数の特徴点で整合性が取れるようにします。


各処理の説明を行います。



--------- < 1.マップの初期化 > ---------
"Tracker::TrackFrame内の TrackForInitialMap()"

1.1.ユーザーがキーを押して、初期化スタート                    Tracker::GUICommandHandler
1.2.最初のキーフレームが決定される                              Tracker::TrailTracking_Start
1.3.特徴点1000個が検出※1される                          Tracker::TrailTracking_Start
1.4.特徴点周辺の画像を2Dのパッチにする                      Tracker::TrailTracking_Start
1.5.ユーザーがキーを押して、初期化終了                        Tracker::GUICommandHandler
1.6.2つ目のキーフレームが決定される                           MapMaker::InitFromStereo
1.7.5点アルゴリズムで※2で、特徴点マップを3Dにする MapMaker::InitFromStereo
1.8.3Dマップに対し、束調整を行う。                               MapMaker::BundleAdjustAll
1.9.RANSAC※3で不適切な点を除去                           MapMaker::CalcPlaneAligner



※1 徴点の検出
 特徴点の検出(corner detector)という方法がとられています。
※2 8点アルゴリズム(eight-point algorithm)(5点アルゴリズムは、まだ分かっていません)
・エピポーラ幾何:二つの画像間における幾何学的関係。
・エピポーラ拘束:2つのカメラ間の画像関係の条件、「基準カメラに写ったある点はもう一方の画像上のある直線(エピポーラライン)上に射影される」というもの
・8点アルゴリズム:2枚の画像の8組以上の対応点の組から画像間のエピポーラ拘束を表す行列を求める方法。
http://www.ric.titech.ac.jp/saneken/stereocamera.htm

※3 RANSAC(RANdom SAmple Consensus):
特徴点の検出で得られた対応点は、間違っている場合(外れ値"outlier")もあるので、これを除去するための処理。
(外れ値の反対は正対応"inlier")

ランダムに幾つかのサンプルを抽出し, 最小二乗法に当てはめることを繰り返す。
抽出したサンプルに外れ値が含まれなければより確からしい推定が得られ, 且つ外れ値の数が全測定数に比べて少なければ推定される誤差範囲内により多くの測定値が含まれる。このことから,もっとも多くの測定値が範囲内に含まれるときの推定を正しい推定とみなす. 



--------- < 2.トラッキング > ---------
"Tracker::TrackFrame内の TrackMap()等"

2.1.画像を取得する                                          KeyFrame::MakeKeyFrame_Lite
2.2.仮のカメラ姿勢位置※4を計算                   Tracker::ApplyMotionModel
2.3.それを使い、マップ上の点を画像に投影する   TrackerData::Project

○大まかなマッチング   Tracker::TrackMap()内の // ... coarse stage 以下
2.4.特徴が強い点50個を、画像から検索する
2.5.マップの点と50個の特徴点をマッチングする
2.6.マッチング結果からカメラの位置を修正

○詳細なマッチング   Tracker::TrackMap()内の // ... fine tracking stage 以下
2.7.1000個の点をマップから画像に再度投影
2.8.画像内からも通常の特徴点を検出
2.9.1000個の点と、画像の特徴点をマッチングする
2.10.最終的なカメラ位置を計算する

※4 仮のカメラの姿勢位置の計算には、運動モデルを用います。この運動モデルでは、カメラの動きが遅いという想定になっています。



--------- < 3.マップの更新 > ---------
MapMaker::run()

3.1.新しいキーフレームがあるかどうか調べる

○新しいキーフレームが見つからなかった場合                              QueueSize() == 0
3.2.キーフレームが見つからなかったら、マップの調整を行う。
3.2.1.マップが局所的でない場合は、局所的な束調整※5を行う。  MapMaker::BundleAdjustRecent
3.2.2.マップが全体的でない場合は、全体的な束調整を行う。         MapMaker::BundleAdjustAll
3.2.3.どちらもOKなら、データ間の関係を更新する。                      MapMaker::ReFindFromFailureQueue
○新しいキーフレームが見つかった場合                                        QueueSize() > 0
3.3.見つかったら、新しい特徴点追加する。                                  MapMaker::AddKeyFrameFromTopOfQueue
3.3.1.キーフレームのデータ関係を更新                                       MapMaker::ReFindInSingleKeyFrame
3.3.2.キーフレームを統合する                                                   MapMaker::ThinCandidates
3.3.3.新しい特徴点を追加する                                                   MapMaker::AddPointEpipolar

fig_6_1.gif

※5 束調整(bundle adjustment):

再投影誤差の平方和を最小化する方法

再投影誤差は、特徴点追跡に基づく外部パラメータ推定手法で、一般的に用いられる誤差関数であり。再投影誤差の二乗和を最小にすることでカメラパラメータを推定する手法は、バンドル調整法と呼ばれている。


PTAMの解析 - 1 概要

|
PTAM(Parallel Tracking and Mapping for Small AR Workspaces)の解析を行っております。
正直言って非常に難しいです。

なので、とりあえず概要について説明したいと思います。
また資料として、以下のサイトを参考にさせていただきました。
masayashiPTAMを15分でなんとなく理解する
CagylogicPTAMのアルゴリズムを理解するのに必要な用語


※非常に大雑把に翻訳しているので、誤りや不足があるはずです、ご注意ください。
※また、この内容は未完成で、修正される可能性があります。



○PTAMとは?

マーカーなしのARの手法です。
以下のような特徴があります。

  • 初めて映す場所でも実行できる(マーカーなどの目印いらず)
  • 最初の場所から少し移動しても、トラッキングし続けることができる。(常にマップを更新)
  • マップの更新とトラッキングを別スレッドに分けて処理をしている
  • 狭い作業空間(机の上など)を想定している
  • 他の手法と比べても、”高速”で”正確”で”安定”している



○PTAMの概要

マーカーなしのトラッキングを行える手法は他にもありますが、
PTAMがその他の手法と異なる部分は、次のような処理を行っている点です。

  • トラッキングとマップの更新を分離して、2つのスレッドで実行する
  • マップの更新はバッチ処理を使って、キーフレーム毎に行われる
  • マップは最初に、ステレオ・ペア(5-Point Algorithm)で初期化される。
  • マップの更新時には、エピポーラ幾何が使用される。
  • 非常に多数(数千)の点がマップされる。

こういった手法には、元々ロボットの研究分野で使われていたSLAM(Simultaneous Localisation and Mapping)という技術が使われています。
参考論文:Real-Time Simultaneous Localisation and Mapping with a Single Camera


ですが、ロボットのカメラを使ったトラッキングと、ARの人が手に持って使うカメラでのトラッキングでは、かなり勝手が違います。ロボットは、走行距離を返してくれたり、ゆっくり動いてもいいですが、人の場合はそうはいきません。

多くの場合、トラッキングとマップの更新は同時行われていますが、人を対象にしたARの場合はこれだと問題(data association errors)が起きてきます。そこで、トラッキングとマップの更新を分離しました。

この2つの処理を分離することにより、この問題を解決できるだけではなく、トラッキングの処理にかける時間を増やすことができます。
この論文では、coarse-to-fineという(高解像度と低解像度の複数の画像を用いる)手法を使うことで、トラッキングの性能を上げることができました。


さらに、フレーム毎にマップを処理するのではなく、うまく認識できたフレーム(キーフレーム)のみを対象にマップの更新を行うことで、ここに重いバッチ処理を使用することができます。
(マップの更新をリアルタイムに行う必要がなくなるので)

このバッチ処理には、"bundle adjustment"という手法を用います。
この手法を用いることで、マップ全体を最適化することができ、さらに安定したマップになります。


久しぶりの更新です。
最近はPTAMの解析や、ARToolKitと他のCGツールを協調させるアプリの製作などをコツコツやっております。

AR系の情報は日課のように収集しておりますが、今日は実際に体験できるものを見に行きました。
ITmedia:「拡張現実で恐竜がよみがえる!? 科博でジュラシックパーク気分」



当日は早く着いてしまい、時間が余ったので先にこっちを体験
全球型映像施設「シアター360」

こちらもかなりの没入間で非常に面白かったです。子供たちがちょっと怖がるくらいリアル。
本当に浮いていて高速移動しているような感じで、体がその移動に反応しようとしているのが分かりました。

全球型は立体視じゃなくても相当の没入感があるようです。



それが終わってから、やっと目的の展示へ。
大き目の双眼鏡ぐらいのゴーグルを渡され、スタート。

実際に体験して最初に驚いたのが、その精度の高さ。
骨の模型にピッタリ一致するようにCGが表示され、ブレもほとんど無し。

ゴーグルを左右に振っても、思っていたほどズレが発生しませんでした。


また、後から聞いた話ですが、画像認識だけではなくジャイロセンサーも着いてるそうで、
マーカーが映っていなくてもある程度カバーできるとのこと。

実際に操作しているときには、1度もCGが消えることはありませんでした。
(もっと時間があれば、少し意地悪なこともしたかったのですが^^;


その後、技術者の方を紹介してもらい、いろいろ質問。
一番気になっていた、マーカー内の六角形をあわせたような図形の意味は、経験的な理由であるとのことでした。
四角形や3角形などなどを試してみて、一番認識率が良かったそうです。

画像認識以外にジャイロも着いていたのは意外でしたが、やはり位置検出は複合的な要素を合わせて行ったほうが、高い精度が出たり、範囲外に出た場合にも強いようです。


他にも機材についてや技術話など、それ以外の話なども少しして終了。
もっとお話したかったw


今日は非常に勉強になり、またとても楽しい1日でした。
スタッフの方々、ありがとうございました。


090315-203007_02.jpg

このアーカイブについて

このページには、2009年3月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2008年12月です。

次のアーカイブは2009年4月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 4.01a