mapamok (日本語)

YCAMInterlab edited this page Feb 12, 2013 · 26 revisions

mapamokでYCAM図書館のモデルを表示しているところ

始める前に

mapamokは、プロジェクションマッピングに関してのいくつかの新しいアイデアを探るための実験的なアプリケーションです。

  • プロジェクタのキャリブレーションに長い時間をかけるべきではない
  • Think less about the projection, and more about the space.
  • アイデアのプロトタイピングは即座に実現されるべきだ

これらのアイデアに対していくつかの視点からアプローチしています:

  • カメラキャリブレーションの技術を用いた高速なプロジェクタキャリブレーションにより、キャリブレーションにかかる時間を1分以内に短縮
  • 2Dのマスクやメッシュを使うのではなく、常に3Dモデルを使用して作業を行う
  • 自動的にリロードされるGLSLシェーダを用いてアイデアのスケッチを行う

このチュートリアルではmapamokの使い方と、それ自体を開発する方法について説明します。使い方のセクションでは出来る限り平易な言葉で細部まで説明する事を試みました(それでも一部のトピックはまだここでカバーするには複雑すぎますが)。開発方法のセクションは、openFrameworksとOpenCVに関して、ある程度習熟されている事を前提としています。

mapamokの使い方

概要

mapamokをここからダウンロードすることが出来ます。現在OSX10.6以上を対象に開発されていますが、このアプリケーションを他のプラットフォームに移植するのに大きな障害はないはずです。

ダウンロードファイルを解凍すると作られるフォルダの中に、mapamok.appとdataフォルダが入っており、dataフォルダの中にはmodel.dae、shader.frag、shader.vertの三つのファイルが入っています。mode.daeはCollada形式の3Dモデルデータ、shader.fragとshader.vertの二つはGLSLシェーダのファイルです。

このチュートリアルでは、mapamokの基本的な使用方法として、まず始めに投影される対象のモデルを準備し、元々入っていたmodel.daeを作成した3Dモデルで置換、その後、mapamok.appを起動し、キャリブレーションを行った後、シェーダを使用していくつかのビジュアリゼーションを体験してみます。

SketchUpで3Dモデルを作成する

まずGoogle SketchUpをダウンロードしてインストールしてください。これからいくつかのキューブを使用して簡単なモデルを作成します。

まず始めにSketchUpを起動すると新規作成画面にります。画面中央に立っている人を選択し、deleteキーで削除します。もしこの時、何かツールを選択してしまっていてうまくいかない場合はスペースキーを押して選択モードにする事で人を選択する事が出来ます。次にoキーを押してオービットモードを選択し、視点を良い位置に移動します。画面内をドラッグすることで回転、シフトキーを押しながらドラッグでパン、スクロールをする事でズームを操作する事ができます。

画面上部の四角ツールのアイコンをクリックするか、CMD+kを押し、四角モードを選択してください。その後カーソルを3軸の中心点付近に移動させると、カーソルが中心点に吸着し、そこに黄色い点が表示されます。そこで一度クリックしてから、カーソルを中心点から離れる方向に移動させてください。四角形がマウスカーソルの動きにあわせて広がります。この状態でクリックをしないまま、キーボードで"500mm, 500mm"と入力し、エンターキーを押してください。これで500mm x 500mmの大きさの四角形を作る事が出来ます。

画面上部のプッシュ/プルツールのアイコンをクリックするか、CMD+=を押し、プッシュ/プルツールを選択してください。そして今作ったばかりの四角形の上をクリックして選択してください。マウスカーソルを上の方向に動かし、四角形の上面を上の方向に引っ張り上げます。この状態でクリックをせずに、"500mm"と入力しエンターキーを押してください。これで各辺500mmのサイズのキューブを作成する事が出来ます。

選択ツールのアイコンをクリックするか、スペースキーを押して選択ツールを選択し、画面内をドラッグして今作成したキューブ全体を選択してください。CMD+cを押してキューブをコピーし、CMD+vを押して貼付けます。貼付けを行うと、新たなキューブがマウスカーソルに張り付いた状態で現れます。マウスカーソルを動かして、キューブを並べてみましょう。既にあるキューブのコーナーにカーソルを移動させると、新しいキューブがスナップします。これを使って整列させる事が出来ます。張り付けと配置を繰り返し、プロジェクションの対象となるモデルの形状と同じ物を作ります。

最後に__ファイルメニュー>保存__を選択し、SketchUpファイルを保存します。そのあと__ファイルメニュー>エクスポート>3D モデル__を選択し、今作成したモデルを別形式のファイルで書き出します。"形式"のプルダウンメニューの中から"COLLADA ファイル(*.dae)"を選択します。オプションの設定は、"すべての面を三角化する"と"コンポーネントの階層をエクスポートする"のみにチェックを入れ、残りの項目のチェックを外してあれば良いはずです。SketchUpのモデルを作成する際、グループの機能を用いるとmapamokでうまく処理できない事がありますので、ご注意ください。ファイルの名前欄にmodel.daeと入力し、エクスポートボタンをクリックします。ここで作成したmodel.daeファイルをmapamokのdata/フォルダ内に移動します。

モデルを一から作成するのではなく、既にあるものを使用する場合、SketchUpの__ファイルメニュー>編集>グループ>分解__を選択し、モデル内の全てのグループを解除する必要があるでしょう。透明色の面はSketchUpでは書き出されないので、書き出し処理をする前に全ての透明色の面を何かの色で塗っておいてください。SketchUp上のモデルをmapamokで読み込む最も確実な方法は、一度SketchUpからSTL形式で書き出し、そのSTLファイルをMeshLabを用いてCOLLADAファイルに変換して用いる方法です。

mapamokの目標の一つは、このようにキューブを使ったようなプロジェションマッピングを、特に人の興味を換気しなくなるほど、とてもシンプルな物にしてしまう事です。キューブは説明のしやすい一つのサンプルに過ぎません。SketchUpを使えば非常に多くの種類の3D形状を作る事が出来ます。3Dスキャンデータやポイントクラウドデータなど、モデルにしたい他の3Dデータが既にある場合には、SketchUp以外のソフトウェアを使用してmodel.daeを作成するのも良いでしょう。

mapamokの構造

mapamokを起動すると、自動的にフルスクリーン表示になります。mapamokには二つのモードがあります。render(レンダリング)モードと、selection(選択)モードです。起動時、初期状態では選択モードになっています。操作は画面左に表示されるコントロールパネルを使って行いますが、その他に下記の4つのキーボードショートカットがあります:

  • tabキーでコントロールパネルの表示/非表示の切り替え
  • spaceキーでレンダリングモード/選択モードの切り替え
  • fキーでフルスクリーンモードの切り替え
  • sキーでキャリブレーション後の内部パラメータ(intrinsics)の保存

コントロールパネル表示時、上記のはじめの3つのショートカットに関しては画面左下にヒントが表示されています。また、画面右下にはアプリケーションの実行フレームレート(FPS)が表示されています。この値は普通の性能のコンピュータではおおよそ60になっているはずです。

コントロールパネルには、saving(設定の保存)とrestoring(読み込み)の二つのボタンがあり、設定は data/settings.xmlに記録されます。また、機能別に下記の5つのタブがあります。

  1. Interaction(インタラクション) 使用頻度の高い設定項目が入っています。
  2. Highlight(ハイライト) 頂点情報の順番を確認するために使える設定項目が入っています。
  3. Calibration(キャリブレーション) プロジェクタのキャリブレーションに関して低レベルの設定項目が入っています。
  4. Rendering(レンダリング) 描画の設定やアプリケーションの操作感を設定する項目が入っています。レンダリングモード用の物を多く含みます。
  5. Internal(インターナル) アプリケーションの内部設定の確認表示や、設定モード時の操作感を設定する項目が入っています。

通常は1番目のタブ以外、気にする必要はありません。

Interaction(インタラクション)タブ

  • setupMode レンダリングモードでキャリブレーションポイントの点の表示/非表示を切り替えます。キャリブレーション後にこの設定で非表示にする事が出来ます。
  • scale 画面内のモデルをズームイン/ズームアウトします。ズームはマウスの右ボタンでドラッグする事でも操作可能です。
  • backgroundColor プロジェクタをキャリブレーションしている際、この設定を使用して背景色を変更する事で、対象物上の点を選択しやすくなる事があります。
  • drawMode モデル上のポリゴンの描画方法を指定します。
  • shading シェーダに関しての設定をします。全てを白色で表示するか、3D空間内の光源を利用して表示するか、オリジナルのシェーダを使用するかを選択できます。

Highlight(ハイライト)タブ

このタブは主にデバッグ用です。

  • highlight ハイライトのON/OFFを切り替えます。ハイライトがONの場合、モデルの中で選ばれた一部のみが表示されます。
  • highlightPosition and highlightOffset ハイライトがONの時、モデルのどの部分を表示するかを設定する事が出来ます。

"position"は空間内の頂点配置の順番ではなく、モデルのCOLLADAファイル内の頂点番号を示しています。

Calibration(キャリブレーション)タブ

通常、このタブの内容を変更する必要はないでしょう。ただし使用しているプロジェクタのレンズが極端に広角の物だった場合や、何か別の意味で極端なレンズを使用している場合、もしかしたらこれらの設定を調整する必要があるかもしれません。しかし、この部分を説明しようとすると、内容がこのドキュメントの対象範囲を超えてしまうのでここでは説明をしません。詳細に関しては OpenCV documentationをご参照ください。

もしも非常にハイクオリティのレンズを使用して、かつレンズシフトも使用しない場合、CV__CALIB__FIX__PRINCIPAL__POINTを有効にするとよいかもしれません。

通常、プロジェクタはカメラと比較して非常に周方向ひずみ(tangential distortion)が小さいので、CV_CALIB_ZERO_TANGENT_DISTはデフォルトで有効になっています。

非常に広角な魚眼レンズや、半径方向ひずみの大きなレンズを使用する場合、CV_CALIB_FIX_K1CV_CALIB_FIX_K2CV_CALIB_FIX_K3を有効にすると良いかもしれません。

ピクセルが正方形に表示されないような、特殊なプロジェクタを使用していない限り、CV_CALIB_FIX_ASPECT_RATIOは常に有効になっていたほうが良いでしょう。

Rendering(レンダリング)タブ

このタブの設定は全て、様々な描画の設定を調整するための物です。オリジナルのシェーダを使用する場合、ほとんどの設定項目は効果がありません。ここではその中から2つだけを説明します。

  • __Fog__は__useFog__で有効にする事ができ、__fogNear__と__fogFar__で調整します。
  • __Interactionタブ__で__shadingモード__を__lights__に設定している場合、randomLighting__を有効にする事で面白い効果を得られるかもしれません。この機能を使用しない場合は__lightX, lightY, __lightZ__の設定項目を使用して光源の位置を調節します。

Internal(インターナル)タブ

普段このタブの内容を変更する事はまずないでしょう。この中にある設定項目は一番下の二つ(slowLerpRateとfastLerpRate)を除き、全て、アプリケーション内部の状態を表示する物です: __slowLerpRate__と__fastLerpRate__は、スクリーン内をドラッグしてキャリブレーションポイントを移動させる時の、キャリブレーションポイントの移動速度(低速移動と高速移動それぞれの)を設定します。キャリブレーションポイントはキャリブレーション時に、左クリックでドラッグすると低速移動、右クリックでドラッグすると高速移動をします。

キャリブレーション

mapamokを起動し、オリジナルモデルの読み込みが完了すると、次にすべき事はプロジェクタのキャリブレーションです。この作業は、初めての場合でも10分以内、慣れてくると1分以内に完了する事が出来るでしょう。

まず、mapamokがselectionモードである事を確認してから、左クリックでドラッグをして、画面に表示されたモデルの絵とプロジェクタから見たプロジェクタの投影対象の見え方が同じになるように、モデルを回転させます。selectionモードで変更したモデルの回転などは、実際のキャリブレーションには影響を与えません。なので、見え方が同じといっても使用上の不便が無ければ大体で大丈夫です。

コンピュータ画面を見て、表示されている青い点のうちどれかにマウスカーソルを重ねると、その場所に数字のラベルが表示され、マゼンダ色の大きめの点で表示されます。クリックして選択すると、その点は黄色で表示されるようになります。ここでspaceキーを押してselectionモードからrenderモードにモードを変更します。すると選択した点(キャリブレーションポイント)が表示されています。コンピュータの画面内で、その点をクリックしてドラッグしてみてください。点はドラッグしている最中は黄色で表示されます。

点をドラッグしながら、実際にプロジェクションをしている対象を見てください。その中で今ドラッグしているポイントを、対象物の上の対応している位置にくるように移動させてください。まく移動できたらspaceキーを押して再度selectionモードに戻ります。

再度コンピュータ画面を見て、モデル内の別の点を選択し、何度か同じ事をしてみてください。6つの点(まれに7点必要な事も)を選択すると、mapamokはプロジェクタに対して焦点距離、作成したモデルとの相関、向きなどに関する最初の推察を始めます。最終的に8点から12点のコンピュータ画面上の点を、現実のモデル内で対応している位置に調整すると、良好な結果を得る事が出来ます。

コンピュータ内のモデルが大体正確なものであって、使用しているプロジェクタのレンズが歪みすぎていなければ、この行程でキャリブレーションを行う事が出来ます。キャリブレーションポイントを選択、位置調整するときに覚えておいて欲しいことを下記に示します。

  • 投影しているモデルのワイヤーフレームが現実のモデルときちんと重ならない場合は、キャリブレーションポイントを追加して対応関係を設定してください。ただし同時に言える事として、良いキャリブレーションを得るために、12点を超えるキャリブレーションポイントが必要になる事はないでしょう。
  • キャリブレーションがそれでもうまくいかない場合には、もう一度、本当にコンピュータ内で選択した点が、現実のモデル上の対応した位置にきているかどうかを確認してください。もしも1、2点が間違った箇所に対応付けられていると、キャリブレーション後の投影像を歪めてしまいます。
  • 出来るだけモデル全体をカバーするように、キャリブレーションポイントを選びます。この際、モデルの中心付近の点とモデルの最も外側の点を含むように選んでください。
  • 近い距離の範囲内で複数の点を選択しないようにしてください。
  • 3Dモデル内で、同じ平面上になる点をあまり多く選択しないでください。数学的な話になりますが、選択される点はお互いに可能な限り一次独立の関係にある必要があります。

これらはキャリブレーションの役に立つはずです。しかし、キャリブレーションで良い結果を得るために全てを理解しなくてはいけない、という事ではありません。

一旦プロジェクタのキャリブレーションが完了すると、キーボードのsキーを押す事で内部パラメータ(intrinsics)を保存する事が出来ます。将来的にはこのカメラのキャリブレーションのデータはより多くのデータ形式で書き出せたほうが良いでしょう(画角や位置、向きに関して)。現時点では、このデータは保存のみが可能で、読み出す方法はありません。

ライブコーディング

モデルの準備、プロジェクタのキャリブレーションが終了したら、シェーダを使っていろいろなビジュアリゼーションを試す事が出来ます。

mapamokのdataフォルダ内にはshader.vert(頂点シェーダ)とshader.frag(フラグメントシェーダ)の二つのシェーダーファイルがあります。基本的に、コンピュータの画面に何かが描画される際、描画はまず頂点シェーダ処理、その次にフラグメントシェーダ処理を通過します。GLSLに関しての詳細はこのチュートリアルで扱う範囲を超えるのでここでは扱いませんが、フラグメントシェーダ(shader.frag)の中にいくつかのサンプルコードが入っています。

異なる描画を試すには、mapamokで__shader__を有効(Interactionタブのshadingの選択肢で__shader__を選択)にして、shader.fragの下記の行の数字を違う値に変更します:

float stages = 6.;

このシェーダファイルはmapamokの実行中にも変更できます。シェーダの内容を保存すると自動的にmapamokに読み込まれ、描画が変化します。もしもいくつかの描画が次々に変化するようにしたい場合には、下記のようにelapsedTimeが使用できるでしょう。

float stage = mod(elapsedTime * .6, stages);

現時点ではコンパイルの出来ないシェーダに対しての、デバッグのヒントはConsole.appに表示される情報しかありません。このため、mapamokは試してみる用途には向いていますが、込み入った開発には必ずしも向いていません。より複雑な描画を開発するためには、まずOpenGL Shader Builderから始めて、そこで出来上がった物をコピーして使用する方法が良いかもしれません。

mapamokの開発

mapamokのコードのほとんどはインターフェースとコントロールパネル関係のコードです。それ以外の重要なパートは全てopenFrameworksのアドオンと、オンラインで公開されているコードで構成されています:

  • ofxProCamToolkit (ProCamToolkitのレポジトリに含まれます)は現実世界とコンピュータ内の世界との境界で機能します。例えば、ofScreenToWorld()や、ofWorldToScreen()といった具合にです。これらのコードは将来的に更新され、openFrameworksのコアに含まれるようになる可能性もあります。
  • LineArt (ProCamToolkitのレポジトリに含まれます)はほぼopenFrameworksのアドオンの形式をとり、InteractionタブのdrawMode内にある機能で、アウトラインだけを表示させたり、隠面消去を行って表示させる部分で使われています。
  • __ofxAssimpLoader__はmodel.daeファイルを読み込み、objectMesh内にあるofMeshにデータを格納します。
  • __ofxControlPanel__はコントロールパネル用のコードです。ここでは__ofxControlPanel__の拡張版である__ofxAutoControlPanel__を用いています。これは私がオリジナルのofxControlPanelからフォークして開発している物です。
  • __ofxCv__はいくつかのキャリブレーション用のクラスとメソッドを使用しています。

mapamokの背景にある重要なアイデアはキャリブレーションのターゲットとして、形状が既にわかっている現実のモデルを使用するという事です。通常、カメラ(やプロジェクタ)のキャリブレーションにはチェスボードのパターンやそれに類似する繰り返しの多いパターンを使用します。しかし、カメラのキャリブレーションで必要な物はコンピュータ内と現実空間のモデル間の対応関係だけなので、形状が前もってわかっていればどんなモデルでもキャリブレーションは可能です。キャリブレーションのターゲットに平面ではないものを使用する場合、OpenCVではカメラマトリックスを初期化する必要があります。 下に示すコードは、コントロールパネルの__Calibration__タブ内にある"angle of view"の推測が使われている箇所です:

float aov = getf("aov");
Size2i imageSize(ofGetWidth(), ofGetHeight());
float f = imageSize.width * ofDegToRad(aov);
Point2f c = Point2f(imageSize) * (1. / 2);
Mat1d cameraMatrix = (Mat1d(3, 3) <<
	f, 0, c.x,
	0, f, c.y,
	0, 0, 1);

カメラマトリックスを初期化した後に、標準的なカメラキャリブレーションの手法でプロジェクタの内的パラメータ(intrinsics)と外的パラメータ(extrinsics)を求める事が出来ます。

calibrateCamera(referenceObjectPoints, referenceImagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, flags);

GitHubから、libraryという名前のmapamokの重要なブランチをダウンロードする事ができます。libraryブランチにはNovationのLauchPadとの間の入出力やMIDI出力のサポートといった、いくつかの特別な機能が追加されています。