Tokyo MotionControl Networktech-café Vol.01
~ Leap in the Cloud / LeapMotionで学ぶ3Dセンサー開発~
Day2:誰もがつまづく3D認識の課題
2
自己紹介
・仙台出身、広島育ち、3年前に東京へ転勤してきました。
・Tokyo MotionControl Network 発起人の一人
・業務アプリケーション開発、学校向けグループウェア開発をはじめ、ARスマートフォンアプリやコンシューマー向けWebサービスなどを担当しています。NUI分野では3年以上前からKINECTを使った開発を行っています。
・たまにエア書道ではテレビ出演をしています2013年1月6日 東京MX TV 「Tokyo, Boy」 新年スペシャル2013年8月26日 日本テレビ 「NEWS ZERO」
3
プログラマー的自己紹介
• プログラマー歴: もうちょっとで24年
• わかる言語・環境:
アセンブラ、C、C++、BASIC、Visual Basic、Delphi(Object Pascal)、Perl、PHP、
Java、JavaScript、C#、Objective-C、Unity
これまでやったちょっと変わった仕事
• Windowsのファイルシステムフィルタドライバ開発
Windowsのカーネル付近に踏み込みましたw
シ○ンテックさんのドライバと競合したりなど。
• とある自動車メーカーで使ってるWebシステム用Javaフレームワーク開発
綺麗な(理想的すぎる?)オブジェクト指向を鍛えられました。
4
会社紹介
・所在地:広島県広島市と東京都。
・現在の中心事業はOSSによるECサイト構築、グループウェア構築。
・先進分野として、NUI・KINECTアプリ開発、Windows8アプリ開発、ARを使ったスマートフォンアプリ開発( iOS/Android/Windows Phone)など行っています。
・書籍の執筆を行っています。
・ASCII.jpでインタビュー記事が掲載されています
・CodeZineに連載を寄稿しています。
5
作品紹介
エア書道 (KINECT)KOFUDE (Leap Motion)
6
誰もがつまづく3D認識の課題
センサー買ってきた!
↓サンプルうごいた。すげー!
↓アプリ作ろう。SDKもばっちり!
↓、、、、えっとここからどうしたらいいの(´・ω ・`)
7
誰もがつまづく3D認識の課題
ここまでがDay1の段階
ここを乗り越えて次のステージへいきましょう!
8
想定されるはまりポイント
1. センサーから入ってくるデータの単位・座標軸の方向がわからない
2. 体(指)を動かすと座標値がどう動いていくかウォッチできない
3. 特定のモーションをアプリ内のイベントに変換するにはどうすれば、、
9
センサーの座標軸とか
じゃん!答えw
ドキュメントにセンサーを中心にした図解があります。https://developer.leapmotion.com/documentation/csharp/devguide/Leap_Overview.htmlhttp://blogs.wankuma.com/hatsune/archive/2013/07/30/328028.aspx
10
センサーの座標空間とか
Leapソフトウェアは検出した物体を分析し、手、指、ツールなどの位置関係、ジェスチャー、および動きを認識します。Leapの検出範囲は、装置の中心を頂点とした逆ピラミッドです。 検出距離は約25~600ミリメートルなっています。
25mm
600mm
11
座標の動きをウォッチしたい
センサープログラミングというのは常にセンサーから高速にデータが流入している状態なのでデバッグが難しいです。
ブレークポイントを使ってプログラムをストップさせた場合はその瞬間のデータは確認できますが、1秒前の状態からどれだけ値が変化したか、という情報はわかりません。
C#でいえばConsoleに対してログ出力をしてもこれも高速すぎて、超人並みの動体視力でなければ読めないですよね(笑)
おまけにキネクトの場合はPCから少し離れなければ体が反応しないので、ログを見るためにPCに近づくと認識が外れてログが出ないというトラップもw)
12
座標の動きをウォッチしたい(C#)
1. using System.IO;2. using System.Text;3. using Leap;
4. namespace MotionLogger5. {6. public class CSVExporter7. {8. static private readonly string FilePath = "log.csv";9. static private readonly string Delimiter = ",";
10. // コンストラクタ、ヘッダ出力11. public CSVExporter()12. {13. StreamWriter writer = new StreamWriter(FilePath);
14.writer.WriteLine("id,timestamp,hands,fingers,tools,gestures,position_x,position_y,position_z");
15. writer.Close();16. }
例)Frame情報をログファイルにCSV出力してみる
13
座標の動きをウォッチしたい(C#)1. // CSVレコード出力2. public void Export(Frame frame)3. {4. StringBuilder sb = new StringBuilder();5. sb.Append(frame.Id).Append(Delimiter);6. sb.Append(frame.Timestamp).Append(Delimiter);7. sb.Append(frame.Hands.Count).Append(Delimiter);8. sb.Append(frame.Fingers.Count).Append(Delimiter);9. sb.Append(frame.Tools.Count).Append(Delimiter);10. sb.Append(frame.Gestures().Count).Append(Delimiter);11. if (!frame.Hands.IsEmpty)12. {13. Hand hand = frame.Hands[0];14. FingerList fingers = hand.Fingers;15. if (!fingers.IsEmpty)16. {17. Vector avgPos = Vector.Zero;18. foreach (Finger finger in fingers)19. {20. avgPos += finger.TipPosition;21. }22. avgPos /= fingers.Count;23.
sb.Append(avgPos.x).Append(Delimiter).Append(avgPos.y).Append(Delimiter).Append(avgPos.z);24. }25. }
26. StreamWriter writer = new StreamWriter(FilePath, true);27. writer.WriteLine(sb.ToString());28. writer.Close();29. }30. }31. }
14
座標の動きをウォッチしたい(JS)
https://github.com/TMCN/TechCafe-Vol-01/blob/master/Day2/js/MotionLogger.html
15
座標の動きをウォッチしたい
-400
-300
-200
-100
0
100
200
300
400
5.522E+09 5.524E+09 5.526E+09 5.528E+09 5.53E+09 5.532E+09 5.534E+09 5.536E+09 5.538E+09
position_x
position_y
position_z
CSVをExcelでグラフにしてみる
これは手を左右に動かしたときのグラフ。Xの値が上下しているのがわかる。座標の動きがわかると、イベントにする特徴を掴める。
時間軸
16
モーションをイベントへ
モーションを何かのイベントにするには、まず人ってどう動くかを改めて考えてみることがスタートです。
例えば、じゃんけんでチョキを出すとき皆さんはどうしますか?
17
モーションをイベントへ
手 指
1 じ 上げる グ
2 ゃ ー
3 ん 下げる グー
4 け 上げる グー
5 ん 下げる グー
6 ぽ 上げる グー
7 ぉ 下げる チョ
8 ん 止める キ!
チョキを出すとはこういうこと!
※さいしょはグーには非対応※人によっては2回手は振らないかも?
この間3秒程度?
18
モーションをイベントへ
人の動きの流れがつかめたら、センサーの座標データを調べて特徴的な座標の動きのパターンが判定に使えないか調べます。
例えば手を左右に振ると、一定時間内にXの値は上下しますが、YやZは変化しません。→Xの値の変化を判定に使おう、というように考えます。
-400
-300
-200
-100
0
100
200
300
400
5.522E+09 5.524E+09 5.526E+09 5.528E+09 5.53E+09 5.532E+09 5.534E+09 5.536E+09 5.538E+09
position_x
position_y
position_z
19
モーションをイベントへ(C#)
1. //前回チェック時間とその時のFrame2. private DateTime checkedTime = DateTime.MinValue;3. private Frame checkedFrame = null;
4. public override void OnFrame(Controller controller)5. {6. // Get the most recent frame and report some basic information7. Frame frame = controller.Frame();
8. if (!frame.Hands.IsEmpty)9. {10. if ((DateTime.Now - checkedTime) > new TimeSpan(0, 0, 0, 0, 500))11. {12. // 500ミリ秒ごとに前回位置との差分を求める13. // 移動量がしきい値を超えていたらイベントとして認識するする14. if (this.checkedFrame != null)15. {16. Vector diff = frame.Hands[0].Translation(this.checkedFrame);17. //SafeWriteLine("X移動量: " + diff.x);18. if (diff.x > 150)19. {20. SafeWriteLine("右フリックしました! :" + diff.x);21. }22. if (diff.x < -150)23. {24. SafeWriteLine("左フリックしました! :" + diff.x);25. }26. }27. this.checkedTime = DateTime.Now;28. this.checkedFrame = frame;29. }30. }31. }
例)左右フリックを判定してみる
Leapには一定時間
内の動きの差分を求めるAPIが用意されています。
20
モーションをイベントへ(JS)
https://github.com/TMCN/TechCafe-Vol-01/blob/master/Day2/js/EventDetector.html
21
モーションをイベントへ(JS)
このサンプルには下記の課題があります。
・判定のしきい値が固定なので、手がセンサーに対してY方向に近いと認識範囲を外れて誤動作することが多い
・地味w(モーションへのフィードバックはNUIのUXで重要)
22
まとめ
1. センサーから入ってくるデータの単位・座標軸の方向がわからないドキュメントを見る。日本語訳もある。
2. 体(指)を動かすと座標値がどう動いていくかウォッチできないログやグラフで動きを可視化する。
3. 特定のモーションをアプリ内のイベントに変換するにはどうすれば、、人間の動きを分解して考える。動きを座標の特徴的な動きのパターンで掴む。
Tokyo MotionControl Networktech-café Vol.01
~ Leap in the Cloud / LeapMotionで学ぶ3Dセンサー開発~
day2:誰もがつまづく3D認識の課題
ありがとうございました!この後さっそく一緒に開発をしてみましょう。