こくぶん研究室

AR を作ろう

はじめに

普及してきた AR

「ポケモンGO」ではカメラの映像の中にポケモンが現れます。ニンテンドー 3DS の「AR ゲームズ」でも似たようなことができます。このように、現実世界(の映像)に CG などを重ねて表示する技術を AR(Augmented Reality; 拡張現実)といいます。「電脳コイル」や「ソードアート・オンライン」などのアニメーション作品でも AR のような描写があります。

AR はバーチャルリアリティ(Virtual Reality; VR)の一種ですが、カメラ1個で容易に実現できるため、いちはやく日常生活に普及してきました。

AR のしくみ

AR には様々な方法がありますが、基本的には、カメラがどこを向いているか(何を写しているか)を測って、特定の方向に向いていたら(特定の何かを写していたら)、カメラの映像に CG などを重ねて表示させます。

「ポケモンGO」では、スマホの GPS センサでユーザの居場所を測り、スマホのジャイロセンサや方位センサでユーザが向いている方向を測っています。ポケモンを配置した場所にユーザがいて、ポケモンがいる方向を向いていたら、ポケモンの CG を表示させます。3DS の「AR ゲームズ」では、「AR カード」という目印になる絵がカメラに写っていたら、カードの位置や向きを計算して、カードの上に CG を重ねています。

「センサ」とか「計算」とか、なんだか難しそうですが、わりと簡単に作れるんです! やってみましょう!

▲TOP

今回の内容

目標

まず、パソコンにつないだカメラで特定の模様(マーカ)を検出すると CG を表示する、典型的な AR を作ります。

今回の目標 1
今回の目標 1

さらに、もっと複雑な画像を検出して CG を表示する AR を作ります。

今回の目標 2
今回の目標 2

使うもの

ステップ

  1. カメラ映像をキャプチャする
  2. 超シンプルな AR
  3. CG モデルを表示させる
  4. 絵をマーカにする

▲TOP

1. カメラ映像をキャプチャする

AR にはカメラの映像が必要です。Processing で Web カメラの映像を撮る(キャプチャする)準備をします。外付けカメラを用意した場合はパソコンにつないでください。

video ライブラリの準備

Processing でカメラの映像を扱うには「video」というライブラリが必要です。これをインストールします。

まず、Processing の「スケッチ」メニュー -> ライブラリをインポート -> ライブラリを追加 を選びます。

ライブラリを追加
ライブラリを追加

出てきた「Contribution Manager」というウィンドウの「Libraries」タブの左上のテキストボックスに「video」と入力すると、ライブラリがいくつか表示されます。その中の「Video | GStreamer-based video library for Processing」を選択して、右下の「Install」をクリックします。するとダウンロードされ、自動的にインストールされます。

video ライブラリのインストール
video ライブラリのインストール

プログラムを書く

Processing に以下のコードを入力して、cam_test.pde という名前で保存しましょう。

import processing.video.*;               // video ライブラリを使う

Capture cam;                             // Capture オブジェクトの宣言

// 一度だけ実行される setup() 関数
void setup() {
  size(640, 480);                        // ウィンドウのサイズ設定
  String[] cameras = Capture.list();     // 利用可能なカメラデバイスを取得
  printArray(cameras);                   // 利用可能なカメラデバイスをコンソールに表示
  cam = new Capture(this, cameras[0]);   // ★ [0]の部分はあとから書き換える
  cam.start();                           // カメラをスタート
}

// 繰り返し実行される draw() 関数
void draw() {
  if(cam.available() == false) {         // カメラが利用可能な状態でなければ
    return;                              // 何もせず処理を終える
  }
  cam.read();                            // 映像をキャプチャする
  image(cam, 0, 0);                      // キャプチャした画像を表示する
}

入力し終えたら実行してください(▶をクリック)。この時点ではカメラの映像が映らなくても大丈夫です。

Processing の「コンソール」に利用可能なカメラの一覧が表示されます(パソコンにつないだカメラが 1台でも、解像度などのモードを複数持っているので、それぞれ別のカメラとして扱われます)。

利用可能なカメラの一覧
利用可能なカメラの一覧

この一覧の中から「size=640x480,fps=30」というカメラを見つけ、その左端の値を控えてください。上の画像の例では [0] です。

その値を、プログラムの 10行目の cameras[ ] の [ ] 内に書きます。

  cam = new Capture(this, cameras[0]);   // ★ [0]の部分はあとから書き換える

実行して、カメラの映像が映れば成功です!

▲TOP

2. 超シンプルな AR

今から作るもの
今から作るもの

ここからが本番です。

まず AR を実現するための「NyARToolkit」というライブラリをダウンロードして設定します。続いて AR のプログラミングです。

NyARToolkit のダウンロードとインストール

こちらのサイトを開き、「Latest release」というマークの右にある「Downloads」から「nyar4psg.zip」をクリックします。するとダウンロードが始まります。

NyARToolkit のダウンロード
NyARToolkit のダウンロード

ダウンロードされた「nyar4psg.zip」をダブルクリックして開き(zip を展開しないまま)、中にある「nyar4psg」というフォルダを右クリックして「コピー」を選びます。

nyar4psg をコピー
nyar4psg をコピー

自分の「ドキュメント」フォルダに移動します(例えば C:\Users\{ユーザ名}\Documents)。その中に「Processing」という名前のフォルダがあります。さらに中に「libraries」というフォルダがあるので開きます。そこで右クリックして「貼り付け」を選びます。これで nyar4psg がインストールされました。

libraries フォルダに貼り付け
libraries フォルダに貼り付け

もし Processing が開いていたら、いったん全て終了させてから、あらためて Processing を起動します。これで nyar4psg ライブラリが使えるようになりました。

AR のプログラミング

Processing に以下のコードを入力して、ar_box.pde という名前で保存しましょう。

それぞれのコードが何をしているのかは、コード中のコメント文を見て考えながら入力していきましょう。

import processing.video.*;               // video ライブラリを使う
import jp.nyatla.nyar4psg.*;             // nyar4psg ライブラリを使う

Capture cam;                             // Capture オブジェクトの宣言
MultiMarker mm;                          // MultiMarker オブジェクトの宣言

void setup() {
  // ウィンドウとカメラの設定
  size(640, 480, P3D);                   // ウィンドウのサイズ設定(P3Dモード)
  String[] cameras = Capture.list();     // 利用可能なカメラデバイスを取得
  printArray(cameras);                   // 利用可能なカメラデバイスをコンソールに表示
  cam = new Capture(this, cameras[0]);   // ★ cameras[ ] 内にカメラのテストで控えた数字を入れる
  cam.start();                           // カメラをスタート
  // NyARToolkit の設定
  mm = new MultiMarker(this,             // NyARToolkit の初期設定
             width,                      // カメラ画像の幅(ウィンドウの幅と同じ 640)
             height,                     // カメラ画像の高さ(ウィンドウの高さと同じ 480)
             "camera_para.dat",          // カメラの校正ファイル
             NyAR4PsgConfig.CONFIG_PSG); // nyar4psg を Processing 用に設定する決まり文句
  mm.addNyIdMarker(0, 80);               // 認識するマーカを登録する (ID, マーカの幅[mm])
}

void draw() {
  // ビデオキャプチャ
  if(cam.available() == false) {         // カメラが利用可能な状態でなければ
    return;                              // 何もせず処理を終える
  }
  cam.read();                            // 映像をキャプチャする
  // AR 処理の開始
  mm.detect(cam);                        // キャプチャした画像内でマーカを探す
  mm.drawBackground(cam);                // ウィンドウの背景にキャプチャした画像を設定
  if(mm.isExist(0) == false) {           // マーカ[0] が存在しなければ
    return;                              // 何もせず処理を終える
  }
  mm.beginTransform(0);                  // マーカ[0] の位置にもとづいて座標の投射(変換)を始める
    translate(0, 0, 40);                 // 原点の位置の調整(原点をZ軸方向に 40mm 移動)
    fill(255, 165, 0, 127);              // CG の塗りつぶしの設定 (R, G, B, 不透明度)
    box(80);                             // 80mm 四方の箱の CG を描く
  mm.endTransform();                     // 座標の投射(変換)を終了
  // AR 処理の終了
}

すぐに実行したくなりますが、もう少し我慢です。

各種ファイルとマーカの準備

まず、さきほどインストールした nyar4psg フォルダを開いてください(ドキュメント\Processing\libraries\nyar4psg)。その中の「data」というフォルダの中で以下のファイルを見つけてください。

いま書いたプログラム「ar_box.pde」のフォルダの中に「data」という名前のフォルダを作って、その中に「camera_para.dat」をコピーしください。これは「カメラ校正ファイル」というものですが、ここでは詳しく説明しません。

最後に、こちらのファイルをダウンロードして、プリンタで印刷してください。プリンタが無ければ、パソコンの画面に表示させておいてください。スマホで使う QR コードに似ていますが、AR 用の「マーカ」と呼ばれる図形です。

動作確認

お待たせしました! これで準備完了です。

ar_box.pde を実行し、マーカをカメラで写してください(左上の「000」のマーカ全体が入るように)。

マーカの上にオレンジ色の半透明の箱が表示されれば成功です! カメラを動かしてマーカをいろんな方向から写したら、どうなりましたか? マーカを近づけたり遠ざけたり傾けたら、どうなりましたか?(カメラやマーカを動かす時はゆっくり、また、「000」のマーカ全体が写るようにしましょう)

ar_box.pde の実行結果
ar_box.pde の実行結果

▲TOP

3. CG モデルを表示させる

上の例では単純な箱を表示しただけで、あまり面白くありませんね。box(80); のように、プログラムの中で CG を描く方法だと、あまり複雑なものは描けません。複雑な CG モデルは別のソフトウェアで作り、Processing で読み込んで表示させます。

ここでは CG モデルの作り方は解説しません。例えば Windows 10 には「3D Builder」というソフトウェアがはじめから入っています。他にも例えば、BlenderMetasequoiaGoogle SketchUp などが無料で使えるメジャーな CG ソフトウェアです。どれを使っても構いません。最終的に「*.obj」というファイル形式でモデルを保存すれば Processing で表示できます。

ここでは、Processing にはじめから入っている CG モデルを使って AR 表示させてみます(CG モデルのありかはのちほど解説します)。

今から作るもの
今から作るもの

プログラミング

Processing に以下のコードを入力して ar_obj.pde という名前で保存しましょう。さきほどの ar_box.pde を「名前をつけて保存」して、書き加えたり書き換えていくと効率的でしょう。

それぞれのコードが何をしているのか、さっきと何が違うか、コード中のコメント文を見て考えながら入力していきましょう。

import processing.video.*;               // video ライブラリを使う
import jp.nyatla.nyar4psg.*;             // nyar4psg ライブラリを使う

Capture cam;                             // Capture オブジェクトの宣言
MultiMarker mm;                          // MultiMarker オブジェクトの宣言
PShape obj;                              // CG を扱う PShape オブジェクトの宣言
float ry;                                // CG モデルを回転させるための変数 ry の宣言

void setup() {
  // ウィンドウとカメラの設定
  size(640, 480, P3D);                   // ウィンドウのサイズ設定(P3Dモード)
  String[] cameras = Capture.list();     // 利用可能なカメラデバイスを取得
  printArray(cameras);                   // 利用可能なカメラデバイスをコンソールに表示
  cam = new Capture(this, cameras[0]);   // ★ cameras[ ] 内にカメラのテストで控えた数字を入れる
  cam.start();                           // カメラをスタート
  // NyARToolkit の設定
  mm = new MultiMarker(this,             // NyARToolkit の初期設定
             width,                      // カメラ画像の幅(ウィンドウの幅と同じ 640)
             height,                     // カメラ画像の高さ(ウィンドウの高さと同じ 480)
             "camera_para.dat",          // カメラの校正ファイル
             NyAR4PsgConfig.CONFIG_PSG); // nyar4psg を Processing 用に設定する決まり文句
  mm.addNyIdMarker(0, 80);               // 認識するマーカを登録する (ID, マーカの幅[mm])
  // PShape の設定
  obj = loadShape("rocket.obj");         // "rocket.obj" という名前の CG モデルを読み込む
}

void draw() {
  // ビデオキャプチャ
  if(cam.available() == false) {         // カメラが利用可能な状態でなければ
    return;                              // 何もせず処理を終える
  }
  cam.read();                            // 映像をキャプチャする
  // AR 処理の開始
  mm.detect(cam);                        // キャプチャした画像内でマーカを探す
  mm.drawBackground(cam);                // ウィンドウの背景にキャプチャした画像を設定
  if(mm.isExist(0) == false) {           // マーカ[0] が存在しなければ
    return;                              // 何もせず処理を終える
  }
  mm.beginTransform(0);                  // マーカ[0] の位置にもとづいて座標の投射(変換)を始める
    lights();                            // 3D シーンに照明を追加
    scale(0.3);                          // CG モデルのサイズを調整
    translate(0, 0, 80);                 // 原点の位置の調整(原点をZ軸方向に 80mm 移動)
    rotateX(PI/2);                       // CG モデルを X軸まわりに 90度(π/2)回転させる
    rotateY(ry);                         // CG モデルを Y軸まわりに ry ぶん回転させる
    shape(obj);                          // CG モデルを表示
  mm.endTransform();                     // 座標の投射(変換)を終了
  // AR 処理の終了
  ry += 0.1;                             // rotateY(ry); で回転させる角度 ry を少し増やす
}

すぐに実行したくなりますが、もう少し我慢です。

各種ファイルとマーカの準備

いま書いたプログラム「ar_obj.pde」のフォルダ内に「data」という名前のフォルダを作って、その中に、さきほども使った「camera_para.dat」(カメラ校正ファイル)をコピーしください(「ar_box.pde」を「名前をつけて保存」してから書き始めた場合は、既に入っているかもしれません)。

次に、CG モデルを用意します。Processing.exe のあるフォルダを開いてください。そこから、modes -> java -> examples -> Basics -> Shape -> LoadDisplayOBJ -> data とフォルダをたどってください。以下の三つのファイルがあります。

これら三つすべてを「ar_box.pde」のフォルダ内の「data」の中にコピーしてください。

最後に、さきほどと同じマーカも準備してください。

動作確認

お待たせしました! これで準備完了です。

ar_obj.pde を実行し、カメラでマーカを写してください(左上の「000」のマーカ全体が入るように)。

以下のように、マーカの上にロケットが表示され、くるくる回っていれば成功です!

ar_obj.pde の実行結果
ar_obj.pde の実行結果

この CG がポケモンだったら、「ポケモンGO」みたいですね!(あくまで「みたい」ではありますが)

▲TOP

4. 絵をマーカにする

ここまでは白黒の四角いマーカを使ってきました。AR を試すぶんにはこれでなんの問題もありませんが...。例えば絵本をカメラで写したら絵が飛び出す 3D 絵本を作るとしましょう。やさしい画風の絵本にこの無機質なマーカが貼ってあったら、なんだか興ざめしてしまいます。

安心してください。NyARToolkit は白黒の四角いマーカだけでなく、絵や写真などの複雑な図柄もマーカに使うことができます。絵本のページそのものをマーカにすることができるんです。専門的には「自然特徴点追跡(NFT; Natural Feature Tracking)といいます。

そのための手順は以下です。順を追ってやってみましょう。

  1. 絵や写真の画像ファイルを用意する
  2. 画像の特徴点ファイルを作る
  3. プログラミング
今から作るもの
今から作るもの

絵や写真の画像ファイルを用意する

マーカとして使いたい画像ファイルを用意します。写真でもイラストでも構いませんが、できるだけ複雑な画像が向いています(さっぱりした画像だと特徴を見つけにくいのです)。ファイル形式は jpg または png 形式がよいです。さらに、解像度があまり高いとこの後の処理で時間がかかるので、「ペイント」などのソフトウェアで 640x480 ピクセルくらいにしておきます。

よいものがすぐに見つからなければこの画像をダウンロードして使ってください。

画像の特徴点ファイルを作る

Processing を起動して、「ファイル」メニューから「サンプル」を選んでください。すると以下のような小さなウィンドウが出ます。「Contributed Libraries」の中の「nyar4psg」を開きます。ここにある nftFileGen をダブルクリックします。

サンプルから nftFileGen を開く
サンプルから nftFileGen を開く

開いたプログラムを実行すると、NyAR NftFileGenerator というウィンドウが開きます。

NyAR NftFileGenerator
NyAR NftFileGenerator

「Import」メニューから「Load image」を選び、出てきたダイアログで、上で準備した画像ファイルを選びます。

マーカにする画像ファイルの読み込み
マーカにする画像ファイルの読み込み

右のほうにある「Source DPI」欄に、読み込んだ画像の DPI 値を入れます。DPI 値の調べ方は...。Windows の画面で画像ファイルを右クリックして「プロパティ」を選びます。開いたウィンドウの「詳細」タブの中にある「水平方向の解像度」の値を調べます。以下の例では 72 DPI でした。この値を「Source DPI」欄に入力します。

画像ファイルの DPI 値の調べ方
画像ファイルの DPI 値の調べ方

NftFileGenerator の「Make Feature Set」ボタンをクリックします。すると、画像の中から特徴的な部分(自然特徴点)を探し始めます。

特徴点の抽出中
特徴点の抽出中

しばらく待つと、以下のように特徴的な場所に赤や青の印が示され、右下に様々な値が出ます。これらの特徴点をカメラの映像から探してマーカ代わりにします。なお、これらの赤や青の印ができるだけ画像内にまんべんなくあるほうがカメラで検出しやすい画像です。あまりにも印が少なかったり、どこかに偏っていたら、違う画像を使うことも検討しましょう。

特徴点が抽出された
特徴点が抽出された

最後に、「Export」メニューの「Save FeatureSet Files」を選ぶと、ファイル保存ダイアログが開きます。適当な名前で保存してください。なお、ここでは拡張子(.jpg など)は入力しません。例えば launchpad という名前で保存すると以下のような三つのファイルができます。これらを後から使います

プログラミング

ar_obj.pde を「名前をつけて保存」で ar_nft.pde という名前で保存します。そこに以下のコードを入力しましょう。それぞれのコードが何をしているのか、さっきと何が違うか、コード中のコメント文を見て考えながら入力していきましょう。

22行目の "launchpad" の部分は、上で作った特徴点ファイルの名前を指定します。

import processing.video.*;               // video ライブラリを使う
import jp.nyatla.nyar4psg.*;             // nyar4psg ライブラリを使う

Capture cam;                             // Capture オブジェクトの宣言
MultiNft nft;                            // ★ MultiNft オブジェクトの宣言
PShape obj;                              // CG を扱う PShape オブジェクトの宣言
int pz;                                  // ★ CG モデルを動かすための変数 pz の宣言

void setup() {
  // ウィンドウとカメラの設定
  size(640, 480, P3D);                   // ウィンドウのサイズ設定(P3Dモード)
  String[] cameras = Capture.list();     // 利用可能なカメラデバイスを取得
  printArray(cameras);                   // 利用可能なカメラデバイスをコンソールに表示
  cam = new Capture(this, cameras[0]);   // ★ cameras[ ] 内にカメラのテストで控えた数字を入れる
  cam.start();                           // カメラをスタート
  // NyARToolkit の設定
  nft = new MultiNft(this,               // ★ NyARToolkit の初期設定
             width,                      // カメラ画像の幅(ウィンドウの幅と同じ 640)
             height,                     // カメラ画像の高さ(ウィンドウの高さと同じ 480)
             "camera_para.dat",          // カメラの校正ファイル
             NyAR4PsgConfig.CONFIG_PSG); // cnyar4psg を Processing 用に設定する決まり文句
  nft.addNftTarget("launchpad", 145);    // ★ 認識するターゲット画像を登録 (ファイル名, 画像の幅[mm])
  // PShape の設定
  obj = loadShape("rocket.obj");         // "rocket.obj" という名前の CG モデルを読み込む
}

void draw() {
  // ビデオキャプチャ
  if(cam.available() == false) {         // カメラが利用可能な状態でなければ
    return;                              // 何もせず処理を終える
  }
  cam.read();                            // 映像をキャプチャする
  // AR 処理の開始
  nft.detect(cam);                       // ★ キャプチャした画像内でマーカを探す
  nft.drawBackground(cam);               // ★ ウィンドウの背景にキャプチャした画像を設定
  if(nft.isExist(0) == false) {          // ★ ターゲット[0] が存在しなければ
    return;                              // 何もせず処理を終える
  }
  nft.beginTransform(0);                 // ★ ターゲット[0] の位置にもとづいて座標の投射(変換)を始める
    lights();                            // 3D シーンに照明を追加
    scale(0.15);                         // ★ CG モデルのサイズを調整
    translate(-500, 300, pz);            // ★ 原点の位置の調整
    rotateX(PI/4);                       // ★ CG モデルを X軸まわりに 45度(π/4)回転させる
    shape(obj);                          // CG モデルを表示
  nft.endTransform();                    // ★ 座標の投射(変換)を終了
  // AR 処理の終了
  pz += 20;                              // ★ CG を動かす値を増やす
  if(pz > 1000) {                        // ★ もし pz が 一定値以上なら
    pz = 0;                              // ★ 元の位置に戻す
  }
}

すぐに実行したくなりますが、もう少し我慢です。

各種ファイルとターゲット画像の準備

いま書いたプログラム「ar_nft.pde」のフォルダ内に「data」という名前のフォルダを作って、その中に、さきほども使った「camera_para.dat」(カメラ校正ファイル)をコピーしください(「ar_obj.pde」を「名前をつけて保存」してから書き始めた場合は、既に入っているかもしれません)。

次に、さきほども使った CG モデルを用意します。以下の三つのファイルを「data」の中にコピーしてください(これらも「ar_obj.pde」を「名前をつけて保存」してから書き始めた場合は、既に入っているかもしれません。もし無ければ... Processing.exe のあるフォルダを開き、modes -> java -> examples -> Basics -> Shape -> LoadDisplayOBJ -> data とフォルダをたどって見つけてください)。

さらに、さきほど作った三つの特徴点ファイル(*.fset, *.fset3, *.iset)も「data」の中に入れてください。

最後に、さきほど用意した画像ファイルをプリンタで印刷してください。プリンタが無ければ、パソコンの画面に表示させておいてください。

動作確認

お待たせしました! これで準備完了です。

ar_nft.pde を実行し、ターゲット画像を写してください。

以下のように、ターゲット画像の上にロケットが表示され、飛んでいけば成功です!

ar_nft.pde の実行結果
ar_nft.pde の実行結果

これで、四角いマーカを使わなくても、飛び出す絵本などができますね!

▲TOP

まとめ

AR のプログラミング、いかがでしたか?

プログラミング以外の作業が少し多いですが、プログラム自体は実質 40行くらいでした。AR を作ること自体はとても簡単なのです(親切な方々が簡単にしてくれているのです)。これからは「AR を使って何をする?」というのが大切な視点です。ぜひいろんなアイデアを試してみましょう。

例えば ar_box.pde を改造して...

例えば ar_obj.pde を改造して...

例えば ar_nft.pde を改造して...

などなど、改造して遊びながら、楽しい応用を考えてみましょう。

補足

上で作ったコードはすべてこちら(GitHub)に置いてありますから、参考にしてください。

ほかにも、NyARToolkit に付属しているサンプル(ドキュメント\Processing\libraries\nyar4psg\examples の中)を開いていろいろ試してみてください。

慣れてきたらリファレンス(ドキュメント\Processing\libraries\nyar4psg\reference の中)も見ると、いろいろ改造・応用のヒントが思い浮かぶかもしれません。

▲TOP