LoginSignup
14
16

More than 5 years have passed since last update.

Processing 3.3 と NyARToolkit 5.0.5 で AR の練習

Last updated at Posted at 2017-02-19

動機

長らく、Processing 1.5.1 と NyARToolkit で AR を楽しんできました。
少し自由な時間ができたので… さすがにもう、最新の環境に乗り移ろうと決心しました。最新の NyARToolkit は 3.0.2 以降、従来のマーカに加えて、NFT(Natural Feature Tracking; 自然特徴点追跡)もできるので、そのあたりも練習してみました。

環境

やったこと

  • ビデオキャプチャのテスト
  • 最もシンプルな AR
  • OBJ 形式の 3DCG モデルで AR
  • マルチ NFT(自然特徴点追跡)による AR

コード

解説は主にコード中のコメントのみで恐縮です。

ビデオキャプチャのテスト

まずは、Processing 標準の video ライブラリでビデオキャプチャのテストです。
Processing 3 では、video ライブラリは自分でインストールするようです。Processing IDE の「ライブラリの追加...」で The Processing Foundation の video ライブラリをインストールしました。

Processing 1.5.1 時代に比べて(特に Windows 環境では)とても容易になりました。

cam_test.pde
// cam_test.pde
// Install "video" library via "Add Library" tool of Processing IDE.
// Connect a Web camera to your PC.
// Run this sketch once.
// Find a camera device number with "size=640x480,fps=30" from the list.
// * Rewrite "x" with the device number you use.
// Run this sketch again, and confirm the video is shown.
// Coded by Mitsuteru Kokubun, 2017/02/20

import processing.video.*;               // using "video" library

Capture cam;                             // declaration of Capture object

// setup() function is executed once
void setup() {
  size(640, 480);                        // setting size of window
  String[] cameras = Capture.list();     // getting available camera devices
  printArray(cameras);                   // listing available camera devices
  cam = new Capture(this, cameras[12]);  // * Rewrite [x] with the device number you use.
  cam.start();                           // starting capture
}

// draw() function is exectuted repeatedly
void draw() {
  if(cam.available() == false) {         // if camera is not available
    return;                              // do nothing and return
  }
  cam.read();                            // capturing image
  image(cam, 0, 0);                      // displaying captured image
}

最もシンプルな AR

NyARToolkit for Processing の GitHub リポジトリの指示通りに、nyar4psg ライブラリをインストールしました。
カメラのキャリブレーションパラメータもデフォルトの "camera_para.dat" を使いました。
また、NyID マーカを使っています(こちらのサイトで作成)。
実質20行くらいでできました。

ar_box.JPG

ar_box.pde
// ar_box.pde
// A simple AR demo using NyARToolkit and Proceccing 3.
// Install "video" library via "Add Library" tool of Processing IDE.
// Install "nyar4psg" library according to the URL below.
//   -> https://github.com/nyatla/NyARToolkit-for-Processing/
// Connect a Web camera to your PC.
// * Rewrite "x" with the camera device number you use.
// Place "camera_para.dat" in "data" folder of this sketch.
//   - "camera_para.dat" is included within ./libraries/nyar4psg/data
// Print NyID markers on paper. ("NyId_000-005.pdf")
// Run this sketch, and check that an orange transparent box is superimposed on the marker.
// Coded by Mitsuteru Kokubun, 2017/02/20

import processing.video.*;               // using "video" library
import jp.nyatla.nyar4psg.*;             // using "nyar4psg" library

Capture cam;                             // declaration of Capture object
MultiMarker mm;                          // declaration of MultiMarker object

void setup() {
  // window and camera settings
  size(640, 480, P3D);                   // setting size of window with P3D mode
  String[] cameras = Capture.list();     // getting available camera devices
  printArray(cameras);                   // listing available camera devices
  cam = new Capture(this, cameras[12]);  // * Rewrite [x] with the device number you use.
  cam.start();                           // starting capture
  // NyARToolkit settings
  mm = new MultiMarker(this,             // initial settings of NyARToolkit
             width,                      // width of the input image
             height,                     // height of the input image
             "camera_para.dat",          // camera calibration parameter file
             NyAR4PsgConfig.CONFIG_PSG); // configuration for Processing
  mm.addNyIdMarker(0, 80);               // adding NyId marker(ID, marker_width[mm])
}

void draw() {
  // video capture
  if(cam.available() == false) {         // if camera is not available
    return;                              // do nothing and return
  }
  cam.read();                            // capturing image
  // Start of AR process
  mm.detect(cam);                        // detecting marker within captured image
  mm.drawBackground(cam);                // drawing captured image on background
  if(mm.isExist(0) == false) {           // if marker[0] is not exist within the image
    return;                              // do nothing and return
  }
  mm.beginTransform(0);                  // starting coordinate projection based on marker[0]
    translate(0, 0, 40);                 // move the origin 40 mm in the Z axis direction
    fill(255, 165, 0, 127);              // fill color(R, G, B, opacity)
    box(80);                             // draw a 80 mm square box
  mm.endTransform();                     // ending coordinate projection
  // End of AR process
}

OBJ 形式の 3DCG モデルで AR

3DCG のモデルを読むには、Processing 1.5.1 時代は、saitoobjloaderMQOLoader などを使わせていただいてきました。
今回、saitoobjloader を試したところ、Processing 3.3 では動きませんでした。
少し調べたら、Processing 標準の PShape で OBJ 形式のモデルが読めることが分かったので、試したら、簡単にできました。実質30行くらいです。
OBJ 形式の 3DCG モデル(rocket.obj, rocket.mtl, rocket.png)は、Processing のサンプル「LoadDisplayObj.pde」で使われているものを使いました。Processing 本体のフォルダ内の、modes\java\examples\Basics\Shape\LoadDisplayOBJ\data の中にあります。

ar_obj.JPG

ar_obj.pde
// ar_obj.pde
// A 3DCG (*.obj) AR demo using NyARToolkit and Proceccing 3.
// Install "video" library via "Add Library" tool of the Processing IDE.
// Install "nyar4psg" library according to the URL below.
// Connect a Web camera to your PC.
// * Rewrite "x" with the camera device number you use.
// Place "camera_para.dat" in "data" folder of this sketch.
//   - "camera_para.dat" is included within ./libraries/nyar4psg/data
// Place "rocket.obj", "rocket.mtl", and "rocket.png" in "data" folder of this sketch.
//   - "rocket.*" are included within ./Processing_3.x.x/
//       modes/java/exmples/Basics/Shape/LoadDisplayOBJ/data
// Print NyID markers on paper. ("NyId_000-005.pdf")
// Run this sketch, and check that a rocket of 3DCG is superimposed on the marker.
// Coded by Mitsuteru Kokubun, 2017/02/20

import processing.video.*;               // using "video" library
import jp.nyatla.nyar4psg.*;             // using "nyar4psg" library

Capture cam;                             // declaration of Capture object
MultiMarker mm;                          // declaration of MultiMarker object
PShape obj;                              // declaration of PShape object
float ry;                                // variable for rotation of 3DCG model

void setup() {
  // window and camera settings
  size(640, 480, P3D);                   // setting size of window with P3D mode
  String[] cameras = Capture.list();     // getting available camera devices
  printArray(cameras);                   // listing available camera devices
  cam = new Capture(this, cameras[12]);  // * Rewrite [x] with the device number you use.
  cam.start();                           // starting capture
  // NyARToolkit settings
  mm = new MultiMarker(this,             // initial settings of NyARToolkit
             width,                      // width of the input image
             height,                     // height of the input image
             "camera_para.dat",          // camera calibration parameter file
             NyAR4PsgConfig.CONFIG_PSG); // configuration for Processing
  mm.addNyIdMarker(0, 80);               // adding NyId marker(ID, marker_width[mm])
  // PShape setting
  obj = loadShape("rocket.obj");         // loading a 3DCG model named "rocket.obj"
}

void draw() {
  // video capture
  if(cam.available() == false) {         // if camera is not available
    return;                              // do nothing and return
  }
  cam.read();                            // capturing image
  // Start of AR process
  mm.detect(cam);                        // detecting marker within captured image
  mm.drawBackground(cam);                // drawing captured image on background
  if(mm.isExist(0) == false) {           // if marker[0] is not exist within the image
    return;                              // do nothing and return
  }
  mm.beginTransform(0);                  // starting coordinate projection based on marker[0]
    lights();                            // adding lights in the 3D scene
    scale(0.3);                          // adjusting the size of the 3DCG model
    translate(0, 0, 80);                 // adjusting the position of the 3DCG model
    rotateX(PI/2);                       // rotating the 3DCG model 90 degrees around the X axis
    rotateY(ry);                         // rotating the 3DCG model ry radians around the Y axis
    shape(obj);                          // displaying the 3DCG model
  mm.endTransform();                     // ending coordinate projection
  // End of AR process
  ry += 0.1;                             // changing rotation angle
}

マルチ NFT(自然特徴点追跡)による AR

最後に NFT も練習してみましした。せっかくなので、適当に写真を撮ってそれを NFT のターゲットに、重畳表示させる CG モデルも Blender を使って自作しました。

以下はターゲット用に撮影した写真です。
IMG_0177.JPG

NyARToolkit のサンプルとして付属する NftFileGenerator を使って画像から特徴点を抽出し、特徴点ファイル(*.fset, *.fset3, *.iset の三つのファイル)を出力します。
nftgen_savefeatureset.PNG

Blender で適当に CG を作りました。
blender_time.PNG

完成です。
nft_clock.JPG

ar_nft.pde
// ar_nft.pde
// An NFT(Natural Feature Tracking) AR demo using NyARToolkit and Proceccing 3.
// Install "video" library via "Add Library" tool of the Processing IDE.
// Install "nyar4psg" library according to the URL below.
// Connect a Web camera to your PC.
// * Rewrite "x" with the device number you use.
// Place "camera_para.dat" in "data" folder of this sketch.
//   - "camera_para.dat" is included within ./libraries/nyar4psg/data
// Place "drop.{obj, mtl}" and "time.{obj, mtl}" in "data" folder of this sketch.
//   - These obj models are made by using some modeling software, e.g. Blender.
// Place "faucet.{fset,fset3, iset}" and "time.{fset,fset3, iset}" in "data" folder of this sketch.
// Print "faucet.jpg" and "clock.jpg" on paper.
// Run this sketch, and check that the 3DCGs are superimposed on the marker.
// Coded by Mitsuteru Kokubun, 2017/02/20

import processing.video.*;               // using "video" library
import jp.nyatla.nyar4psg.*;             // using "nyar4psg" library

Capture cam;                             // declaration of Capture object
MultiNft nft;                            // declaration of MultiNft object
PShape[] obj;                            // declaration of PShape array object

void setup() {
  // window and camera settings
  size(640, 480, P3D);                   // setting size of window with P3D mode
  String[] cameras = Capture.list();     // getting available camera devices
  printArray(cameras);                   // listing available camera devices
  cam = new Capture(this, cameras[0]);   // * Rewrite [x] with the device number you use.
  cam.start();                           // starting capture
  // NyARToolkit settings
  nft = new MultiNft(this,               // initial settings of NyARToolkit
             width,                      // width of the input image
             height,                     // height of the input image
             "camera_para.dat",          // camera calibration parameter file
             NyAR4PsgConfig.CONFIG_PSG); // configuration for Processing
  nft.addNftTarget("faucet", 160);       // adding NFT target[0] (name, target_width[mm])
  nft.addNftTarget("clock", 160);        // adding NFT target[1] (name, target_width[mm])
  // PShape setting
  obj = new PShape[2];
  obj[0] = loadShape("drop.obj");        // loading a 3DCG model named "drop.obj"
  obj[1] = loadShape("time.obj");        // loading a 3DCG model named "time.obj"
}

void draw() {
  // video capture
  if(cam.available() == false) {         // if camera is not available
    return;                              // do nothing and return
  }
  cam.read();                            // capturing image
  // Start of AR process
  nft.detect(cam);                       // detecting marker within captured image
  nft.drawBackground(cam);               // drawing captured image on background
  for (int i=0; i<2; i++) {              // repeating for two NFT targets
    if(nft.isExist(i) == false) {        // if target[i] is not exist within the image
      continue;                          // do nothing and find next target
    }
    nft.beginTransform(i);               // starting coordinate projection based on target[i]
      lights();                          // adding lights in the 3D scene
      translate(-80, 40, 0);             // adjusting the position of the 3DCG model
      rotateY(PI);                       // rotating the 3DCG model 180 degrees around the Y axis 
      shape(obj[i]);                     // displaying the 3DCG model
    nft.endTransform();                  // ending coordinate projection
  }
  // End of AR process
}

所感と今後

移行して大正解でした。
たいていの私の用途は初期のプロトタイピングのため、通常のマーカーを使っていてもなんの問題もないのですが、NFT のほうがやっぱり楽しいですね。
引き続きいろいろ遊んでみたいと思います。

14
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
16