Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kinectを用いたヘッドトラッキング

 Kinectを用いたヘッドトラッキング

12/2に開催したARコンテンツ作成勉強会の資料
https://togetter.com/li/1177453

TakashiYoshinaga

December 03, 2017
Tweet

More Decks by TakashiYoshinaga

Other Decks in Technology

Transcript

  1. CGの詳細情報の編集:位置の指定 クリック 【解説】  オブジェクトの詳細は Inspectorで確認・変更  詳細情報の例としては 位置・回転・スケールの他 にもマテリアル(外見)、

    スクリプト(挙動)など様々。 【演習】  モニタの内側に置くことを 想定した位置とサイズに。 ※モニタの位置はz=0とする  Positionを 0, 0, 0.1  Scaleを全て 0.05 ※単位はm z x y
  2. スクリプトの記述 public class CtrlScript : MonoBehaviour { // Start関数は初期化のために一度だけ実行される void

    Start () {"R obot Kyle"); } // Update関数は毎フレーム実行される void Update () { } } 頭の位置は時々刻々と変化するのでUpdateに位置取得スクリプトを記述
  3. スクリプトの記述 void Update () { KinectManager kinect = KinectManager.Instance; if

    (kinect != null) { uint playerID = kinect.GetPlayer1ID(); if (playerID > 0) { //人が認識されていれば Vector3 head = kinect.GetJointPosition(playerID, 3); head.Set(head.x, head.y, -head.z); Camera.main.transform.position = head; } } } 3は頭を意味する zの符号を反転 【今回のセットアップでは】 Unity: モニタ奥方向のzが+ Kinect: モニタ手前方向のzが+
  4. 描画判定(開発者側の仕事)  left, right, top, bottom, near, farを使って描画領域を決定する  カメラを原点にした3次元座標(x

    c ,y c ,z c )を、描画領域の座標系での 座標(x s ,y s ,z s )に変換するためのルール(式)をコンピュータ側に教える top bottom left right near 1 top -1 1 0 z x y near -1 bottom 1 right left -1 (xs ,ys ) zs
  5. CGの3D座標 xc , yc , zc 描画判定用の座標系 xs , ys

    , zs 変換式 【数式で書くと】 【やりたいこと】 いい感じに変換 1 top -1 1 0 z x y near far -1 bottom 1 right left -1 変換ルールをUnityがわかる形(数式)で表現 1 = 座標変換 1 − 1 2 ℎ − 0 ℎ + ℎ − 0 0 2 − + − 0 0 0 − + − − 2 − 0 0 −1 0 4×4の行列で表現 ←さっきの6パラメータで作れる
  6. 変換式を使って・・・ 2 ℎ − 0 ℎ + ℎ − 0

    0 2 − + − 0 0 0 − + − − 2 − 0 0 −1 0 CameraのInspectorでパラメータをいじる代わりに スクリプトで変換行列をカメラに割り当てる リアルタイムかつ 柔軟な画角変更を実現
  7. 変換行列作成スクリプト Matrix4x4 PerspectiveOffCenter(float left, float right, float bottom, float top,

    float near, float far) { float x = 2.0F * near / (right - left); float y = 2.0F * near / (top - bottom); float a = (right + left) / (right - left); float b = (top + bottom) / (top - bottom); float c = -(far + near) / (far - near); float d = -(2.0F * far * near) / (far - near); float e = -1.0F; Matrix4x4 m = new Matrix4x4(); m[0, 0] = x; m[0, 1] = 0; m[0, 2] = a; m[0, 3] = 0; m[1, 0] = 0; m[1, 1] = y; m[1, 2] = b; m[1, 3] = 0; m[2, 0] = 0; m[2, 1] = 0; m[2, 2] = c; m[2, 3] = d; m[3, 0] = 0; m[3, 1] = 0; m[3, 2] = e; m[3, 3] = 0; return m; } 事前配布したテキストファイルに 書いてあるのでコピペでOK 2 ℎ − 0 ℎ + ℎ − 0 0 2 − + − 0 0 0 − + − − 2 − 0 0 −1 0
  8. スクリプトのコピペ public class CtrlScript : MonoBehaviour { void Start ()

    {"R obot Kyle"); } void Update () { /*Kinectで取得した頭部位置をカメラ位置に反映*/ /*スペースの都合により省略*/ } ここにPerspectiveOffCenterを貼り付ける }
  9. リアルタイムに視野角を変更 float halfWidth = 0.52f * 0.5f; //0.52はモニタの物理的な幅(各自変更) float halfHeight

    = 0.32f * 0.5f; //0.32はモニタの物理的な高さ(各自変更) void Update () { KinectManager kinect = KinectManager.Instance; if (kinect != null) { uint playerID = kinect.GetPlayer1ID(); if (playerID > 0) { //人が認識されていれば Vector3 head = kinect.GetJointPosition(playerID, 3); head.Set(head.x, head.y, -head.z); Camera.main.transform.position = head; Matrix4x4 m = PerspectiveOffCenter( -halfWidth - head.x, halfWidth - head.x, //left, right -halfHeight - head.y, halfHeight - head.y, //bottom, top -head.z, -head.z + 1); //near, far (スクリーンはz=0にあるため頭との距離がnear) Camera.main.projectionMatrix = m; //カメラに変換行列を反映 } } }
  10. 微調整(例) void Update () { KinectManager kinect = KinectManager.Instance; if

    (kinect != null) { uint playerID = kinect.GetPlayer1ID(); if (playerID > 0) { Vector3 head = kinect.GetJointPosition(playerID, 3); //モニタの上にKinectを乗せている場合にはその高さ分だけ補正 head.Set(head.x, head.y - 0.25f, -head.z); Camera.main.transform.position = head; Matrix4x4 m = PerspectiveOffCenter( -halfWidth - head.x, halfWidth - head.x, //left, right -halfHeight - head.y, halfHeight - head.y, //bottom, top -head.z, -head.z + 1); //near, far (スクリーンはz=0にあるため頭との距離がnear) Camera.main.projectionMatrix = m; //カメラに変換行列を反映 } } }