色々なことやってみてる最中です。かたりぃなです。
一昔前にミクさん召喚とか流行って以降あまり噂を聞かなかったartoolkitを調べてみました。
コードリーディングと言っても、軽く眺めた程度なので間違ってるところあるかと思います。
一番知りたいのはマーカーの姿勢推定の部分。
最近はwindowsストアアプリでも作ろうかなとも考えているので、うまく利用できたらいいなと思っています。
artoolkitって?
マーカーを使ったARを実現するためのライブラリ。
ニコ動あたりでartoolkitで検索かけると、色々と面白いものが見れると思います。
オープンソースのライブラリなので気軽に利用できるのですが、昔はライセンスがGPLだったのでアプリに組み込むにはちょっと……な状態でした。
今の最新バージョン(5.3.1)ではライセンスがLGPLv3になっているので、手軽に利用しやすくなったと思います。
リポジトリ:https://github.com/artoolkit/artoolkit5
とりあえずWindowsでビルドしてみた
configure-win32.vbsを叩くとソリューションができるのでビルドするだけ。
VisualStudio2015だとプロジェクトの設定がおかしいといわれた個所が幾つかあったので修正しました。
修正内容ですが、エラー番号をぐぐってMSDNのページ見れば分かる内容でした。
あとDLL不足が幾つかあったのでその都度修正。実験するだけでシステムディレクトリ汚すのはちょっと嫌なので、VisualStudioが見つけてくれるパスに置いておくことにしました。
コードリーディングの前に情報収集
古いライブラリ(私がコレ使って遊んだのはもう5年くらい前?)なので、だいたいのアルゴリズムは有識者によって調べられています。
先人の知恵と機械の力(デバッガ)を使いつつ読み進めることにしました。
マーカーでの姿勢認識 - やねうらお−ノーゲーム・ノーライフ
理論上はartoolkitでマーカーの姿勢を推定するためには、「平行な線分2組からなる図形」であればいいわけですね。
具体的な形状としては、よく使われる「Hiro」と書かれた正方形マーカーなどですね。
適当な長方形図形でもマーカーとして使えそうです。
(mk_pattユーティリティで自前マーカー作るとき、長方形図形もマーカー候補として認識されました)
平行四辺形や菱形もマーカーに使えそうですが、当面はそんな形状使うことなさそうなので無視することにします。
サンプルプログラムを軽く眺めて全体像を掴む
simple_liteサンプルプログラムを眺めてみます。
カメラから映像を取り込み、マーカー上に立方体をレンダリングするだけというものです。
まず、カメラからの映像取り込みはMicrosoftのDirectShowを使っているようです。windowsストアアプリではMediaFoundationを使うことになるので、カメラ画像取り込み部分は他の手段に頼ることになりそうです。
試しにopencvのVideoCaptureクラスから取り込んだusbカメラの画像を使うように書き換えたところうまくいきました。(こちらも中身はDirectShowだったりすることもありますが。)
置き換えるならカラーフォーマットと解像度を合わせることを忘れずに。
座標系の変換でありがちな転置行列や逆行列を求めるコードは見当たらなかったので、artoolkitの内部の座標系はopenGLに合わせてあるのではないかと推測できます。
もしレンダリング周りをDirectXに置き換えるとしたらひと手間かかりそうです。
ここまでで、映像の入出力の手段はar-toolkitとは独立していると考えてよさそうです。
さて、肝心のアルゴリズムの部分。
arDetectMarker
arGetTransMat
arglCameraViewRH
あたりかと思います。
が、arglCameraViewRHの中身は3x4行列を4x4行列にしてスケールファクタを掛けてるだけでした。
なので、
arDetectMarker
arGetTransMat
あたりがartoolkitの肝ですね。
あ、マーカーの識別を忘れるところでした。
マーカーパターンの読み込みはarLoadPattでやっていて、識別するためのidを返してくれるようです。
マーカーを検出すると、検出したマーカーN個それぞれのidと信頼度がわかる仕組みのようです。
arDetectMarker
いわゆるマーカー検出処理ですね。
この関数が定義されているファイルarDetectMarker.cではグローバルに状態変数を持って何やらやっているっぽい。
直前のフレームの情報を保持しているので(光の加減などで)マーカー消失したとき対策か何かかもしれませn。きっと?
さらに下の階層に下ると、arLabeling.cではグローバルに画像処理用のワークバッファを1024x1024保持してるみたいだけども、最近の高性能webカメラみたいに1600x1200とか突っ込んだらどうなるんだろう?
まあ、やってることは一般的な物体検出の手順っぽいので適当に流し読み。
私が知りたいのは↑でも紹介した物体の姿勢推定のアルゴリズムだけ。
他のアルゴリズムはopencvなりの適当な画像処理ソリューションで何とかなるはず。
arLabelingでラベリングする
ラベリングですね。
arGetContourで輪郭線を抽出
輪郭を成す全てのピクセルの座標がx_coord,y_coordに入る
つまり点p(x_coord[n], y_coord[n])を描画すると輪郭線が見える。
check_squareで検出した輪郭線で四角形ができるのかチェック
ここで輪郭の頂点(vertex)を求めている。
つまりp(x_coord[vertex[n]],y_coord[vertex[n]])としてn=0,1,2,3で四角形をなす4つの頂点を表現できる。
arGetMarkerInfoでマーカーパターンと照合した結果の信頼度とかを返す。
この関数内でarGetLineを呼んでる。
arGetLine、よくわかっていないけれども、、、
↑で紹介したアルゴリズムの入り口の気配。
ここまでに検出した「四角形の1辺をなす全てのピクセル座標pn(x,y)」を「nx2」の行列としてとらえて、歪み補正などを加える。このnx2行列をPCA(=主成分分析。ここではKL展開して次元を落とすのが目的と考えたほうが捉えやすい?)
この処理を四角形を成す4辺全てに対してやっている。。。。
わかったようなわからないような?
arGetLineで得られた結果の数字を見てもいまいちピンと来ない。
このあたりは少しずつ勉強しよう。
最後にarGetCodeであらかじめ読み込まれているマーカーパターンとテンプレートマッチング
マッチング手法とモードは
AR_TEMPLATE_MATCHING_COLOR
AR_TEMPLATE_MATCHING_BW
AR_MATCHING_WITHOUT_PCA
AR_MATCHING_WITH_PCA
これだけっぽい。
arGetTransMat
この関数も調べ終わってから今回の投稿にしたかったのですが、疲れたのでこれくらいにします。
気が向いてまた調べることがあったら投稿するかもしれません。
気になったこと
カメラキャリブレーションなしでそれなりにARが実現できるってのはすごいですが、「それなりに」という部分が引っかかります。
サンプルプログラムではどうやって作られたのか謎なカメラ内部パラメータファイルを使っていました。
気になることはまだ残っていますが、ミッションクリティカルなシステムでなければ、このくらいの手軽さで使えるほうがユーザーウケはよさそうです。