Interactive Programming 2015 – week 3,4

Collective Body ( Toshitaka Amaoka, 2008 )

 

ProcessingでKinectを使う。

Kinectとは?

Kinectで出来ること

  1. 奥行きを測定できる。(距離センサ)
  2. 骨格を追尾出来る。(映像センサ)
  3. 音声認識、音の方向を検出出来る。(4つの内蔵マイク)

Kinect記事 もう一つ

Kinect Specification

ハードウェア

  1. RGBカメラ
    1. カラー出力の場合
      • フレームレート30Hz、32Bitカラー
      • VGA解像度(640×480px)のRGB出力
    2. モノクロの場合
      1. 16bitカラー
      2. QVGA解像度(320×240px、感度は65536階調)
  2. 深度センサー
    1. センサーが感知する範囲は1.2〜3.5m
  3. マルチアレイマイクロフォン
  4. 専用ソフトウェアを動作させるプロセッサを内蔵したセンサー

ソフトウェア

  1. プレイヤーの身長
  2. 位置(縦横奥行きの3次元)
  3. 角度の自動調整
  4. プレイヤーの骨格などを読み取って合成するモーションキャプチャ

まとめると

最新モデルは、Kinect 2

Kinect2 vs Kinect1

3D Scanner & Motion Capture

3Dデータをミュージックビデオで#1

3D dataと可視化

3Dデータをミュージックビデオで#2

モーションキャプチャデータをプロモーションで

http://perfume-global.com/project.html

Kinectで取得した3Dデータを3Dプリンタで

https://vimeo.com/user1363263

その他

https://vimeo.com/24569304

Kinetic Skulptur

Mobility

art+com

Kinect向け開発

Processing

  1. openKinect – OpenNIやlibfreenect等をインストールしなくても使用できる
  2. simpleOpenNI – OpenNI等をインストールする必要がある

Openframeworks

  1. ofxOpenni
  2. ofxKinect

Windows

  1. Kinect SDK for windows

Windows + Mac

  1. OpenNI+libfreenect+sensorKinect

OpenKienct + Processing入門(Daniel Shiffman氏のGetting Started with Kinect and Processingより)

Processing用ライブラリを準備

  1.  Processing用OpenKinectライブラリをダウンロードする。
  2. ダウンロードしたファイルを”書類” -> ”Processing” -> “libraries”に移動する。

使い方

Sketchの最初に、openkinectライブラリを使用するために読み込むimport文を記述する。

import org.openkinect.*;
import org.openkinect.processing.*;

openKinectライブラリを使用するために、インスタンスを代入するためのKinect型の変数を用意する。

// Kinect Library object
Kinect kinect;

setup関数内で、初期化する。


kinect = new Kinect(this);
kinect.start();

ここまでで準備完了。 次にKinectのセンサーからデータを取得する Kinectから取得できるデータは以下の4つである。

    1. KinectのカメラからPImageとして、RGB画像
    2. KinectのIR(赤外線)カメラからPImageとして、グレースケール画像
    3. ピクセルの明度が深度に対応するグレースケール画像
    4. 生深度データ(0〜2048の11bit)int型の1次配列

1. KinectのカメラからPImageとして、RGB画像

Kinectのカメラから画像を取得するには、

  kinect.enableRGB(true);

として、データを取得する準備を行い、

  PImage img = kinect.getVideoImage();
  image(img,0,0);

として、画像データをPImageとして取得し、画面に表示させる。

2. KinectのIR(赤外線)カメラからPImageとして、グレースケール画像

赤外線カメラからデータを取得するには、

kinect.enableIR(true);

として、IRカメラの準備を行う。

3. ピクセルの明度が深度に対応するグレースケール画像

深度画像を取得するには、

kinect.enableDepth(true);

として、取得する準備を行い、

PImage img = kinect.getDepthImage();
image(img,0,0);

として、画像を取得する。

4. 生深度データ(0〜2048の11bit)int型の1次配列

生深度データを取得するには、

int[] depth = kinect.getRawDepth();

とし、生データのみ取得したい場合には、

kinect.processDepthImage(false);

とすると、生データのみ取得するため、効率的である。

Kinectの傾きを制御したい場合

float deg = 15;
kinect.tilt(deg);

とすると、15度傾けることが出来る。

Examples内のPointCloudの解説

生の深度データは、実世界の距離に対応していないため、

depthInMeters = 1.0 / (rawDepth * -0.0030711016 + 3.3309495161);

上記の式で、実際の距離に変換可能である。

深度データは、0〜2048の間のデータなのであらかじめ対応する配列を

float[] depthLookUp = new float[2048];
for (int i = 0; i < depthLookUp.length; i++)
{
 depthLookUp[i] = rawDepthToMeters(i);
} 

float rawDepthToMeters(int depthValue) {
  if (depthValue < 2047) {
    return (float)(1.0 / ((double)(depthValue) * -0.0030711016 + 3.3309495161));
  }
  return 0.0f;
}

として準備しておくと便利。

最終的に、

for(int x = 0; x < w; x += skip) {
  for(int y = 0; y < h; y += skip) {

    int offset = x+y*w; // Convert kinect data to world xyz coordinate
    int rawDepth = depth[offset];
    PVector v = depthToWorld(x,y,rawDepth);
    stroke(255); pushMatrix(); // Scale up by 200
    float factor = 200;
    translate(v.x*factor,v.y*factor,factor-v.z*factor); // Draw a point
    point(0,0);
    popMatrix();
  }
}

とすると、メータの単位に基づくポイントを描画することが出来る。

Examples内のAveragePointTrackingの解説

平均値を取るために、x, yの位置の合計とその合計に使用したデータ数を保存しておく3つの変数を用意する。

float sumX = 0;
float sumY = 0;
float count = 0;

ある、閾値以下のデータを先ほどの変数に加算していく。

if (rawDepth < threshold) {
  sumX += x;
  sumY += y;
  count++;
}

全画面処理した後、以下の処理で平均値を算出する。

if (count != 0) {
  float avgX = sumX/count;
  float avgY = sumY/count;
  fill(255,0,0);
  ellipse(avgX,avgY,16,16);
}