OpenCV 3.3.1 で Yolo v2 for object detection を動かしてみる (Windows)
OpenCV 3.3.1 に YOLO v2 がちゃんと入ってた!サンプルは samples/dnn/yolo_object_detection.cpp https://t.co/hiGGjpUaLN
— ミクミンP/Kazuhiro Sasao (@ksasao) 2017年10月24日
わーい!
というわけで、とりあえずサンプルを動かしてみました。今回は速報版ってことでご容赦下さい。
環境構築
環境
- Windows 10
- Visual Studio 2015
インストール
- Windows (vc14) 用にビルドされた物を落としてくる
- .exe だけど自己解凍するだけなので、適当な場所に置く
- 私の場合は
D:\develop\opencv331
となるように置いた
- 私の場合は
- OpenCVのいつもの儀式、パス通し。こちらの記事に習って行う
とりあえずサンプルを動かす
sources\samples\dnn\yolo_object_detection.cpp
を動かす。
サンプルのためのプロジェクトを作成
- Visual Studio 2015 > ファイル > 新規作成 > プロジェクト
- テンプレート > Visual C++ > 「空のプロジェクト」 を選択
サンプルコードの取り込み
$(ProjectDir)
直下に、上記sources\samples\dnn\yolo_object_detection.cpp
を配置- Visual Studio の ソリューションエクスプローラー上で、
ソースファイル
フィルタに、上記ファイルを投げ込む
インクルードとライブラリのリンク
- .dll にパスを通したときと同様、OpenCV3.2インストール方法(ビルドなし) - Qiita を参考にインクルードディレクトリ・ライブラリディレクトリ・利用ライブラリの指定を行う。
Debug 時と Release 時で使う .lib ファイルが異なる事に注意。
ビルド
- ビルド > ソリューションのビルド。 とりあえず Debug でやってみる。
コンフィグとモデルの用意
- 今回はとりあえず動けば良いので、用途や適正は考えずに、yolo 公式から最もベタっぽいやつを取ってくる。
yolo.cfg
yolo.weights
- Visual Studio 上でデバッグ実行する場合、作業ディレクトリは
$(ProjectDir)
となる。ので、そこに、yoloの cfg ファイルと weights ファイルを置く。 - ついでに、テスト画像も用意。Yolo の学習にも使っている COCO から適当に。
実行
- cfg と model が読まれるようコマンド引数を設定。たとえば以下の様な感じ。
-cfg=yolo.cfg -model=yolo.weights -image=3320359009_059880900a_z.jpg
- これは OpenCV の
CommandLineParser
の書式です。
- F5 デバッグ実行。
結果
見つけたオブジェクトに枠がついています。学習に使われたラベルはこちらです。
奥の車が見つかって無くて、ショルダーバッグだけで無く買い物袋も認識されていて、と言う結果です。良いのか悪いのかはわかりません。
それと、今のところ、提示されたクラスのIDと、その名称の紐付け方がよくわかっていません。他の結果も見た感じ、 Class:0 が人、 Class:2 が車っぽいって事はわかりました(笑)
次にやりたいこと
- Class の id から、クラス名を引く方法は?
- サンプルを元に、動画ファイルやウェブカムを食わせる
- Tiny YOLO はどうやら高速に動きそう、などモデルと設定の特性について学びたい
Raspberry Pi に VNC でアクセスする (2017/9版)
やりたいこと
- Raspberry Pi に毎回 HDMI・キーボ・マウスをつなぐのが面倒なので、MacとかからGUIで触れるようにしたい。
- Chromium や Visual Studio Code を、VNC アクセス中に起動したい。★ここがポイント
結論
最近のラズパイ…というか raspbian OS には、 RealVNC のモジュールがプリインストールされているので、サーバのサービスを入れてあげれば即VNCサーバ化する。
手順
ラズパイ側
RealVNC 公式に書いてあるとおり→ Docs | VNC Connect and Raspberry Pi | RealVNC
- 最新の Raspbian Jessie にする
sudo apt-get update && sudo apt-get upgrade
- RealVNC のサーバをインストール。
sudo apt-get install realvnc-vnc-server
- ラズパイの設定からVNCを利用可能に設定。これだけで、ラズパイ起動時のサービス自動起動設定までされます。
- ラズパイの ip を調べる。
ifconfig
または、RealVNC Server をインストールしたらタスクバーに出てくる RealVNC のアイコンをクリックすると表示される。例えば192.168.11.11
クライアント側(今回はMac)
- RealVNC のクライアントをインストール→ Download VNC Viewer for macOS | RealVNC
- 上で調べた対象ラズパイのIPを入力して接続。
というわけで簡単です。
事の顛末(チラ裏)
この件は誰でもまとめてそうだし、入門書の類に載ってそうなのでまとめるほどでは無い記事だと思ったのですが、自分がちょいとハマったのでまとめることにしました。以下その顛末メモ。なのである意味ここからが本編。
古い情報を鵜呑みにしない
特に最新のラズパイがどんなことになっているかをあまり調べないまま「TightVNC を入れて、Systemd に自動起動を登録しよう」という記事を読んでそのままやってみたところ、以下のような問題が起きました。
あげつらうのは感じ悪いけど、メモとしてはじめ参考にしていた記事を残しておく
Visual Studio Code が VNC 経由だと表示できない
VNC経由で Visual Studio Code (Code-oss) のインストールを済ませて、いざ起動しようと思ったら起動しない。インストール手順間違えたかな、とか思いながらラズパイに直接ログインして操作したら起動できる。あっれ~となって調べる。と、以下の記事を発見
TIghtVNC サーバを使うと、 Visual Studio Code だけじゃなく、Chromium ブラウザ他、 Electron っぽい奴らが全滅するらしい。 セキュリティとグラフィックの掛け算でのなんか問題なのでしょう。
代替手段の調査
- RealVNC と TigerVNC というのがあるらしい。(TigerVNC押し記事)
- よく読んでみると、RealVNC が raspbian に標準採用されているらしい。(完)
インストールしてしまった TightVNC を消す
- 起動しているサービスを停止
ps aux | grep vnc
で TightVNC のプロセスIDを調べてkill
- systemd に登録されている自動起動を解除する
- (参考→)自動起動・サービスの起動・停止 (systemdコマンド) [CentOS 7] - ex1-lab
systemctl list-unit-files
で、先に登録したvncserver@.service
が在ることを確認。sudo systemctl disable vncserver@.service
で解除
- TightVNC サーバのアンインストール
sudo apt-get purge tightvncserver
RealVNC サーバの構成
この記事の先頭に戻る。
TCPSpout + KlakSpout で Unity ソフト間動画転送
なにをやるのか
- 複数のウェブカメラや動画を、同期したり切り替えたりしながら、ネットワーク内の複数のコンピュータに渡して再生したい
- つまり VJ ソフトみたいなことしたい
- Unity で自作したい
- Windows。
概念図は以下の様な感じ
- マルチソースの録画再生機 兼MIXERとして、左側のマシンがあり、そこから、複数のクライアントに動画を送り出します。
- 複数のクライアントにどの映像をどのタイミングでどんな組み合わせで送るか、を左側のマシンで一括で管理します。
- クライアント側は受け取った動画を使ってよしなにやります。たとえば、VR-HMD を使ったりします。
調査
Spout
Mac でのプロジェクションマッピングとか VJ の界隈で Syphon という規格で動画データを渡すことは以前から知っていたのですが、その Windows 版が Spout です。Syphon と互換性があり、相互に送受信することも出来るみたいです。これを使いたい。
keijiro/KlakSpout
keijiro さんのこれを使うと、Unity で手軽に Spout が利用出来ます。使い方は GitHub に充分に書かれているので省略。
異なるカメラに二つ三つと SpoutSender コンポーネントをつけていくと、複数の映像を送り出すことも可能です。この様子を図に表すと以下の感じ。
ただし、このアセットだけだと、同一マシン内でのビデオデータ送受信しかできません。そこで次に続きます。
TCPSpout
Spout を、LAN内でPCをまたいで利用可能にしてくれるのが TCPSpoutです。
- Spout 準拠の映像出力を捕まえて送り出すサーバ
- 別PCのサーバを見つけて映像を受け取り内部で Spout の映像として利用可能としてくれるクライアント
のセットで利用します。図に示すと以下の感じ。この図の中で青い四角で描いてあるところを、Unityの KlakSpout にすれば、今回狙っている構成のできあがりです。Bonjour を使って、IP等打たなくてもLAN内のサーバを自動検出してくれるのが素晴らしいです。
開発
実際の利用法を見ていきましょう。
1. Sender スクリプトのアタッチ
送りたい映像を撮る Unity の Camera に、 SpoutSender スクリプトをアタッチする
2. Sender の確認
1.でSenderのスクリプトをアタッチしたことで、 Window/Klak/Spout Sender List に、Sender の名前が表示されるので確認する。この名称は、Senderスクリプトをアタッチしたゲームオブジェクトの名称になる。
3. TCPSpout サーバの立ち上げ
TCPSpoutServer.exe を起動して、Spout Sender List から、上記名称の Sender を選択する。ここではSenderとして上記 “MainCamera” を選択しています。
ここから先は、映像を受ける側(クライアント)側の設定です
4. TCPSpout クライアント立ち上げ
TCPSpoutClient.exe を起動して、Server List から、対象のサーバを選択します。Bonjour が自動でサーバを検出してくれるのが本当に素晴らしいです。私の例では名称が “TCPSpout FLAUROS” となっていますが、これは、TCPSpout が決めた、“TCPSpout” + “サーバマシン名” という形式で命名されており、Server を立ち上げているPCに私が “FLAUROS” と名付けているのから来ています。
5. Sender の確認
ここでTCPSpout がつないでくれたSenderが見えていることを確認しておきましょう。確認の仕方は Server 側でやったときと同じです。名称は、 “MainCamera” ではなく、ここでは 一個前で選んだ “TCPSpout FLAUROS” になります。
6. Receiver スクリプトのアタッチ
受け取るためのオブジェクトを作って、SpoutReceiver スクリプトをアタッチします。Sender として、先ほど確認した名称を記入します。受け取ったテクスチャを書き込む RenderTexture または、直接書き込む Renderer もここで登録します。詳細は公式のドキュメントを参照ください。
ここで映像を受け取った RenderTexture をよしなに活用出来るようになります。
複数ストリーム用意する
KlakSpout の SpoutSender を、Unity シーン内で複数用意したカメラにそれぞれアタッチすることで、複数の映像を送り出すことができます。その数に合わせて、TCPSpoutServer.exe を複数起動すれば、複数の映像を同時に TCP 上に送り出すことが可能です。
受け取り側も同様に、 TCPSpoutClient.exe を複数起動することで、複数の Server から送り出されている Spout 映像を受け取ることが出来ます。
この際に注意点が、 TCPSpout のクライアントがつける、Sender の名前が、 “TCPSpout” + “マシン名” + “ (n)” <nはサーバの起動数> となることです。例えば、上記の私の例で言うと、 “TCPSpout FLAUROS (2)” という名前で検出されます。あんまりイケてませんが、気をつければ実用上は問題無いでしょう。
所感
同じLAN内で有線で繋いで居ると、FullHD の動画でも結構安定して送れています。自分はウェブカムの分割兼配信機、のように使いたいのですが、遅延に関しては、TCPSpout による物より、ウェブカムそのもの撮影から表示までの遅延の方が大きいです。
それと、人によっては、サーバから出す映像をブロードキャスト/マルチキャスト したいと言う要望もあるかと思います。今回の TCPSpout を利用するケースだと対応出来ません。 サーバでカメラを必要数作って、 SpoutSender を必要個数アタッチすることで、ワークラウンド的には対処出来るかと思います。
いずれにせよなかなか便利なので、積極的に使っていきたいと思います。
Ovrvision Pro を VIVE で使う
つかいかた
Unity 標準の VR 対応 + OvrvisionProSDK for Unity
- 新しいプロジェクトを作る
- VR セットアップにする (OpenVR)
- Ovrvision Pro SDK for Unity を入手する
- OvrvisionPro/Resources/Prefabs/OvrvisionProCamera.prefab をつっこむ
- LeftCamera, RightCamera の
Target Display
を、Game Window の Display 番号とあわせる(なぜかずれていることが多い) - なぜかLayerを何も設定しなくても左右の目に正しく描かれるけど、気持ち悪いので以下の設定をする (*1)
- Layer 8 を “LeftEye”, Layer 9 “RightEye” という名前で登録する
- OvrvisionProCamera/LeftCamera/LeftImagePlane を、 Left Eye に登録する
- OvrvisionProCamera/RightCamera/RightImagePlane を、 Right Eye に登録する
- OvrvisionProCamera/LeftCamera の CullingMask から、 RightEye レイヤーを外す(左目には左カメラの映像が見える)
- OvrvisionProCamera/RightCamera の CullingMask から、 LeftEye レイヤーを外す(右目には右カメラの映像が見える)
蛇足ですが、私の環境だと、OvrvisionProCamera の Ovrsition コンポーネント中、 Camera Mode を 960x950@60:Default
のままにしておくと、盛大にジャダります。 640x480@90
にするとスムースに見ることができます。
SteamVR Plugin を利用する
上のままだとVIVEコンが使えないので、SteamVR Plugin を利用します。
- Asset Store から StreamVR Plugin をインポートする
- StreamVR/Prefabs/[CameraRig].prefab をつっこむ
- [CameraRig]/Camera (head)/Camera (eye) の
Target Display
を Game Window の Display 番号と合わせる (なぜかずれていることが多い) - [CameraRig]/Camera (head)/Cemera (eye) に、
SteamVR_UpdatePoses
スクリプトをアタッチする(こりんさん情報)
これでVIVEコンも表示されるようになります。
OvrvisionPro SDK 内の camimage_demo
サンプルを動かす
上記でも何度も同じことをやっていますが、このサンプルだけを動かしたいなら、以下のあたりを気をつけましょう
- VR対応せずにただカメラ映像を正しく取れることを確認したいなら、MainCamera のTargetDisplayを、Game Window の Display 番号と合わせるだけでOK
- VR対応させるなら、追加で以下の手続きが必要
- LeftCamera, RightCamera の
Target Display
を、Game Window の Display 番号とあわせる(なぜかずれていることが多い) - LeftImagePlane, RightImagePlane を適切なレイヤにあてて、各目のカメラの Culling Mask を正しく設定する(*1 の手続き)
- LeftCamera, RightCamera の
ビデオシースルーとCGを組み合わせる難しさ
まだあまり追っていないのですが、Unity で描画する3Dの世界と、Ovrvision のカメラ映像の世界が、頭を振っているとずれる感じがします。
Ovrvision 公式としては、 ArUco を使ったビジョン(マーカ)ベースのAR開発環境を提供しています。これはカメラ映像を基準としてCGを描くのでずれないのですが、できればマーカベースじゃないARをやりたいです
ちょっと解決法を模索したいです。(未来の自分に期待)
HTC VIVE で頭の位置を固定する
どういうこと?
向きは固定しません。振り向くことはできます。
言い換えると、ヘッドトラックはしているのだけど、毎フレーム必ず、頭の座標を指定の位置に戻します。
なにがしたいの?
THETA などの全天球動画を、撮影位置からぴったり見たいです。
実際やってみてわかったこと
残念なことにこの処方は酔うことが確認できました。THETA を見るようなケースの場合は、動画像を Skybox に貼り付けるなど、十分に大きくしてしまえば実質同じなので、そのほうが良いと思います。
やりかた
前調査
こちらの記事様でやられていましたが、 2017年5月時点の SteamVR SDK を利用した場合、これだけでは不充分であることがわかりました。
SteamVR Plugin を利用する場合
SteamVR/Scenes
に入っている Example
シーンの頭の位置を固定してみます。今回は、原点正方向を基準位置とします。
この example
シーンのカメラでは、Main Camera (origin)
のなかに Main Camera (head)
さらにその中に Main Camera (eye)
という構造になっていますが、Play してみると、Main Camera (eye)
が (origin)
の直下に展開されます。
この (eye)
の座標を0に固定すれば良いと思うのですが、どこかのタイミングで強制的にヘッドトラッキングに基づく座標に上書きされてしまうので、ここでは 親のcameraの座標を相対的に戻るようずらす という解決策を取ります。
Play前
Play中
もう2工夫必要です。
example
シーンでは、Main Camera(head)
が Scale 0.1 倍にされています。そこで、Main Camera (origin)
を相対的にずらす際に、そのスケール分戻して上げる必要があります。- カメラがY軸中心で180度回っているので、これを戻して上げる必要があります。(これはEditor上で行います)
以上のことをやるためのスクリプトは以下のもので、これを Main Camera (origin)
に貼り付ければOKです。
// FixHMDPosition.cs using UnityEngine; using UnityEngine.VR; public class FixPosition : MonoBehaviour { void LateUpdate() { Vector3 trackingPos = InputTracking.GetLocalPosition(VRNode.CenterEye); transform.parent.position = -trackingPos * 0.1f; } }
カメラの方向をY軸180度戻したので、それに合わせてシーンも修正する必要があります。
弊害
このハックで頭の位置を固定すると、 一見 Unity で作った世界に対して頭部位置が固定されたように描画されますが、 HTC VIVE で言うところの「シャペロン境界」は、メインカメラとの位置関係で決められているらしく、頭を動かした結果シャペロン境界が表示されるエリアに入ると、表示されて、結果自分が動いていることが露見します。これは、世界の中に動いているものと動いていないものが混在する状態になるので、気持ち悪さの大きな原因になります。
そこで、今回の手法で頭部位置を 「Unityで作る世界の中で」固定したい場合は、別の方法でシャペロン境界を非表示にする必要があります。
こりんさんが過去にまとめてくださっていたのですが、今やってみると少し仕様が変わっていたようで、steamvr.vrsettings
にもう一行追加する必要があります。
{ "collisionBounds" : { "CollisionBoundsColorGammaA" : 0, "CollisionBoundsStyle": 4 // Developer モードにしないと非表示にはできない }, ... }
言うまでもないことですが、これに加えてまずはじめに、体験者がシャペロン境界に届かないよう、プレイエリアの中心に座ってもらって始めるのが前提になります。
SteamVR の [Camera Rig] を使わない場合
基本は SteamVR Plugin を利用する場合と同じなのですが、以下の手順となります。
- Player Settings で
Virtual Reality Supported
にチェックを入れ、OpenVR
対応とします Main Camera
を、空のゲームオブジェクトで一層包みます。仮にこれをCameraParent
とします。- その
Main Camera
に対し、先程と 「ほぼ」 同様のFixHMDPosition.cs
をアタッチしますが、先程のサンプルとは異なりCameraParent
はスケールが等倍のままなので、FixHMDPosition.cs
でスケールをかけた部分を消します。
// 前略 transform.parent.position = -trackingPos; // * 0.1f しない // 後略
さいごに
最初に書きましたが、 THETA の全天球動画を見る、という用途には向いていない気がしました。ヘッドトラッキングに慣れた体からはもう戻れないのね。。。。
東京大学五月祭 VR関連展示一覧
前書き
- (まだ)行ってないです
- これから行くので自分のために作りました
- 間違ってたり足りなかったら教えて下さい
地図
展示一覧
UT-Virtual / Tokyo VR Cafe
- 場所:工学部1号館2階17講義室
- 整理券制
- ウェブ: 五月祭2017 – UT-virtual
いよいよ第90回五月祭が始まります。
— UT-virtual(東大VRサークル) (@2017utvirtual) 2017年5月19日
Tokyo VR Cafeは20日、21日共に9時から18時の間、ご利用いただけます。場所は工学部1号館2階17講義室です。https://t.co/TD6GgSKYB6#utvirtual #五月祭
(響) pic.twitter.com/ll0Qr3EQYM
東京大学温泉サークル「おける」/ VR 足湯カフェ
- 場所:医学部前A1
- 整理牽制
いよいよ五月祭が明日に迫ってきました!OKRは医学部前で「VR足湯カフェ」を出店します♨️
— 東大温泉サークルOKR(おける) (@UT_okr) 2017年5月19日
信州・渋温泉の本物のお湯を味わいに、是非お立ち寄りください✨
(VR体験の整理券配布は9:00〜と13:00〜に行います) pic.twitter.com/mapO7Y0u3C
上記 UT-Virtual とのコラボ企画
東京大学 工学部電子情報・電気電子工学科 / 近未来体験2017
- 場所:工学部 2・3・13号館
- ウェブ:近未来体験2017
5月20日(土)・21日(日)に行われる第90回五月祭に電気系は「近未来体験2017」として出展します!今流行りのVRをはじめ、プログラミング、電子工作、銀ナノインクなどをワークショップで体験したり、最先端の研究に触れたりできます!ぜひご来場ください! pic.twitter.com/UzRRvYhFR4
— 東京大学電気系(EEIC)学生広報 (@eeic_studentadv) 2017年4月14日
VR企画では、現在のVRシーンを彩る3つのヘッドマウントディスプレイを使って、EEIC学生によるオリジナルコンテンツを展示します。大人から子供まで楽しめるような、3種類のコンテンツを用意しました。バーチャルを体験して、“現実”をアップデートしてください! pic.twitter.com/ygWUcwzCIE
— 東京大学電気系(EEIC)学生広報 (@eeic_studentadv) 2017年5月19日
Techno Factory / 機械系二学科
- 場所:工学部2号館・3号館
- ウェブ ut-mech.com
- 補足:東大廣瀬谷川研関連の出展あり(たぶん)
講演他
工学博覧会2017 企画「応物の今を語る」座談会に稲見昌彦先生が参加 / 東大工学部応用物理系
終了しました
- 場所:工学部 6号館 63教室
- 日時:20(土) 14時
- ウェブ: 応物の今を語る。 | 工学博覧会2017
本日14時から登壇します。工学部6号館63教室です。 https://t.co/FTt1ED3Bwp
— 稲見昌彦 Masahiko Inami (@drinami) 2017年5月20日
EEIC*find Vol.2 に苗村健教授がご登壇
現実拡張+表現拡張=体験拡張 / 苗村 健 教授
- 場所:工学部2号館4F 246講義室
- 日時:21(日)13:00~14:30
- ウェブ:EEIC*find
明日の五月祭の片隅で,13時から電気系学科の先生方による講演会があります。川原 圭博 (Yoshihiro Kawahara) 先生企画で,苗村も登壇します。お気軽にどうぞ。... https://t.co/Np5fS4SbzE
— 苗村健 (@naemura) 2017年5月20日
公開講座 -憧れ- / 「あこがれを現実に変える - VRの仕組みと応用 -」 鳴海拓志先生
- 場所:工学部8号館1階教授会室
- 日時:21(日) 15:30-17:00
- ウェブ: gogatsusai.jp
HoloToolkit-Unity の InputManager の使い方
はじめに
HoloLens を入手して楽しそうなアプリを一通り試して、Academy をやってみたりしてそろそろ自分でアプリを作ってみようかなというところなのですが、ちょっと一息ついて便利な HoloToolkit-Unity 様を調査してみようと思いました。
Academy では、3分クッキング的と言うか「これとこれを足して、ここだけ手作業ね☆」 みたいな感じであまり頭に入らなかった + HoloToolkit-Unity はAcademy でやっていることをほぼラップして使いやすくしてくれているようだったので、HoloToolkit-Unity を実際に触りながら多少試行錯誤的に調べてみた内容をまとめてみます。
HoloLensCamera
の次に、HoloLens開発をしていたら間違いなく使うだろう、 InputManager
について、本記事ではまとめたいと思います。
InputManager の概要
ソースコード中 Input/Readme.md
に、 InputManager
の概説がまとめてあります。 基本的なとこを抜き出すと
Scripts that leverage HoloLens input features namely Gaze, Gesture and Voice.
This contains a fully-featured input module, which allows you to handle various types of input and send them to any game object being currently gazed at, or any fallback object. It also includes a cursor similar to the HoloLens shell cursor that fully leverages the Unity’s animation system.
訳
HoloLens のインプット機能(すなわち Gaze, Gesture, Voice) を活用するためのスクリプト。
各種インプットをハンドルして、注視しているオブジェクトに対しそれらインプットを送ります。(注視対象がない場合はフォールバックのターゲットに送ります) また、HoloLens標準と似た挙動をするカーソルも用意しています。
InputManager
を使うと、視線、ジェスチャ、音声コマンドを使えるようになるし、視線カーソルも使えるようになる、ってことですね。なんて素敵!
内容
多くの部分は先人達が探索して下さってますので、この記事ではそのまとめをしつつ、説明があまりなかった辺りを調査してみた結果をまとめます。
- HoloToolkit-Unity の基本的な使い方
- InputManager の基本的な使い方
- InputManager の使い方の少しだけ詳細
- HandDraggable の使い方
- SpeechInputManager の使い方
- InputManager が他にやっていること
HoloToolkit-Unity の基本的な使い方
大前提として。 @kaorun55 大先生がまとめてくださっています。間違いなし。
InputManager の基本的な使い方
@noshipu さんがまとめてくださっています。こちらの記事では、InputManager
がさばくイベントのうち、 FocusedObjects
に対するイベントについてに説明されています。視線を向けた対象にタップや音声コマンドなどを紐付ける方法についてです。
InputManager のやっていること少しだけ詳細
多くの場合は、@noshipu さんのまとめて下さっている情報で足りると思うのですが、せっかくなのでもう少し InputManager.cs を読んでみて、中でやっていることをざっくりと調べてみました。
InputManager が管理するインプットのハンドラは大まかに5種類
GlobalListeners | いかなるときも呼ばれる。カーソルの状態を切り替えたりするのに使われている |
ModalInputStack | FocusedObjectsに先んじて呼ばれる。ある特定のモード(例えばドラッグ中)に入っているときに処理される |
FocusedObjects | 上記で @noshipu さんが説明してくださっている内容。専用のinterfaceを実装することで、ゲームオブジェクトを注視した状態でクリックや音声コマンドなどを入れることができる |
UnityUIPointerEvent | uGUIで消費する。uGUIを置くだけで使えるので便利 |
FallbackInputStack | ModalにもFocusedObjectsにもUnityUIにも引っかからなかった場合に呼ばれる。どんな場所でも何かしら特定のインタラクションが起きたこと自体を拾いたい場合に使う |
GloblListeners の使い方
ざっくり読んでみたところ、HoloToolkit-Unityとして提供されている中では、GlobalListeners
はカーソルの状態制御にのみ利用されています。(オブジェクトの注視状態に関わらず)手の上げ下げというインプットを受けてカーソルの状態を変えたりしています。
それ以外の使い出としては、たとえば 「リスナーを備えた対象物があってもなくてもとにかくタップした回数を数えたい」 みたいなときには、以下の様なスクリプトを作って、空のオブジェクトに貼り付けると可能です。
using UnityEngine; using HoloToolkit.Unity.InputModule; namespace HoloToolkit.Unity { public class GlobalInputListener : Singleton<GlobalInputListener>, IInputClickHandler { public void OnInputClicked(InputClickedEventData eventData) { Debug.Log("Call Global Listener"); // ここでなんか数字をカウントアップしたり。 } void Start() { InputManager.Instance.AddGlobalListener(gameObject); } } }
GlobalListener
の解除用に、 InputManager.Instance.RemoveGlobalListener()
と言う関数も用意されています。
ModalInputStack の使い方
ModalInputStack
は HandDraggable.cs
中でドラッグでの consume にのみ使われているようでした。 HandDraggable.cs
をちょっと改良すると、つまんでドラッグする事で物体を回転させるスクリプトも簡単に書けそうです。そんなときに ModalInputStack が使えるでしょう。
HoloToolkit-Unity/HandDraggable.cs at master · Microsoft/HoloToolkit-Unity · GitHub
ModalInputStack
へのリスナーの登録/解除関数は以下です。
- 一つ追加:
InputManager.Instance.Push()
- 一つ解除:
InputManager.Instance.Pop()
- 全部解除:
InputManager.Instance.Clear()
ModalInput を利用するには、そのモードへの入り・終わりを定義する必要があるので、上記の追加・解除関数をモードの入り終わりに呼ぶ事になります。その辺は HandDraggable.cs
を読むと何となく分かります。
UnityUI の使い方
通常通り GUIを作って、WorldSpace にするだけでOKです。特定の interface 等の実装は必要ありません。
そういえば、HoloLens で OnScreen な GUI を作るのってできないっすね。(カーソル = ディスプレイ中心、なので)
FallbackInputStack の使い方
FocusedObjects
のように実体があって collision を持つゲームオブジェクトが、タップ等のイベントを consume しなかった場合、FallbackInputStack
にハンドラを登録しておくことで、そいつが受け取ってくれるようになります。フォールバックですね。
InputManager
には PushFallbackInputHandler
という、フォールバックのハンドラを登録するための関数が用意されているのでそれを用います。たとえば下記のようなスクリプトを用意して、空のオブジェクトにアタッチしておくと、@noshipu さんの記事で扱った手順で登録されたゲームオブジェクトのいずれにも視線を向けずに (つまり空振りの) タップしたときに限り、「fallback input」とログが出ます。
using UnityEngine; using HoloToolkit.Unity.InputModule; namespace HoloToolkit.Unity { public class FallbackInputManager : Singleton<FallbackInputManager>, IInputClickHandler { public void OnInputClicked(InputClickedEventData eventData) { Debug.Log("fallback input"); // はずれ!って表示したりとか。 } void Start() { InputManager.Instance.PushFallbackInputHandler(gameObject); } } }
HandDraggable の使い方
詳しくはこちらの記事で説明されています。オブジェクトに HandDraggable.cs
をくっつけたら、手でつかめます、以上。
SpeechInputManager の使い方
FocusedObjects
で消費できるインプットイベントのうち、speech に関しては、まずそれが認識対象のワードである(意図のある入力操作である)、ということを事前に登録していないことには、HoloLensも認識のしようがありません。それを司るのが SpeechInputManager.cs
です。使い方は先程の @noshipu さんの記事にあります。
KeywordManager との住み分け
SpeechInputManager
+ ISpeechHandler
と似た機能を提供する KeywordManager
というのがいます。 KeywordManager
の使い方に関しては、こちらの記事が詳しく説明してくださっています
思想の違い、って感じなのですが、 SpeechInputManager
+ ISpeechHandler
では、ISpeechHandler
を実装した スクリプトをゲームオブジェクトにアタッチすることで、そのオブジェクトを注視している際にイベントを発行(音声コマンドを言う)すると、そのゲームオブジェクトが音声に応じて反応させることができるのに対し、KeywordManager
の場合、gazeとは関係なく、音声コマンドと物や処理を一対一で対応付けていくことができるようになっています。
InputManager が他にやっていること
InputManager.prefab
には、(細かいことをしない限りは)我々が直接触らないいくつかのスクリプトがアタッチされていますが、ざっくりと以下の様な感じになっています
InputManager
にアタッチされているスクリプト
GazeManager | 結構重要。視線に関して色々情報がとれる。後述 |
GazeStabilizer | 視線情報のスタビライズ |
StabilizationPlaneModifier | ここがよく分からないのですが、空間中に平面を仮定してその上で視線座標を動かすことで、視線をスタイビライズするような事をしている、、のかな。このページにそれっぽいことが書いてある |
InputManager
の子
RawInteractionSource | 手の検出などプリミティブなイベントの検出をし、 InputManager に対してイベントを上げる |
EditorHandsInput | Editor実行時にジェスチャをエミュレートする。個人的にはあまり使い出がないと感じている |
GesturesInput | HoloLens の基本API群である UnityEngine.VR.WSA.Input に含まれる GestureRecognizer のラッパで、InputManager に対して各種 input イベントを上げてくる |
GazeManager の便利メンバ
GazeManager.Instance.HitObject
- 視線が当たっているゲームオブジェクトへの参照GazeManager.Instance.HitPosition
- 視線が当たっている衝突点の座標GazeManager.Instance.HitInfo
- 上二つを含む、RaycastHit 情報全部GazeManager.Instance.IsGazingAtObject
- Raycast 対象にしたレイヤー中に含まれて居る物体に当たっているか否か。GazeManager.Instance.GazeOrigin
- 起動時を原点とした視点(頭部)位置GazeManager.Instance.GazeNormal
- 視線方向
あたり。使える。
最後に
便利に使わせていただこうと思います。
初めに挙げた Input/Readme.md 中に、以下の様な記述があって、今後どのように WindowsHolographic もとい、Windows Mixed Reality が進化していくのかわくわくします。
and new input sources can be created to support different input devices.
The focus can be triggered by the user’s gaze or any other gaze source.
Currently, that gaze is always coming from the GazeManager class, but this could be extended to support multiple gaze sources if the need arises.