Tutti Lab

元シリコンバレー在住のおっさん技術者、モバイルVRアプリ開発に挑戦中

iPhoneでTensorflow Liteを試してみる

先日モバイル向けのTensorflowである、Tensorflow Liteがリリースされました。
Tensorflow Liteは、フル機能のTensorflowと異なり、iOS/Androidデバイスにて、学習済みのモデルを高速・高性能で動作させるための仕組みであり、学習や、任意のモデルの構築(MobileNetsなどの一部のモデルしか利用できません)はできません。
しかし、Googleが提供する学習済みのMobileNetsなどを転移学習することで、任意の対象画像の分類が可能ですので、色々な用途に応用できそうです。
今回は、iOS向けのTenforflow Liteのサンプルを実行してみます。

f:id:tuti107:20171126172347p:plain

Tensorlow Liteを入手

Tensorflow Liteは、Githubより入手できます。git clone、もしくはzipで適当なフォルダにダウンロード・任意のフォルダへ展開します(以下、tfフォルダとします)。

下準備

Xcode 8とビルド用のコマンドラインツールをインストール

コマンドラインツールは、コンソールより以下のコマンドによりインストールできます。

xcode-select --install

次に、以下をコンソールでタイプして各種ツールをインストールします(要homebrew)

brew install automake
brew install libtool
Tensorflow Liteライブラリのビルド

コンソールにて、tfフォルダへ移動し、以下をタイプします。

tensorflow/contrib/lite/download_dependencies.sh
tensorflow/contrib/lite/build_ios_universal_lib.sh

これで、tensorflow/contrib/lite/gen/lib/libtensorflow-lite.aが生成されます。

cameraサンプルを実行

サンプルは、simple, cameraの2種類あります。simpleは本当にシンプルでつまらないので、ここではcameraを紹介します。
まず、cameraサンプルのプロジェクトを開く前に、以下を実行します。

cd tensorflow/contrib/lite/examples/ios/camera
pod install

なお、cocoapodsが未導入の場合は、こちらを参考に、cocoapodsを導入ください。

次に、/tensorflow/tensorflow/contrib/lite/examples/ios/camera/tflite_camera_example.xcodeprojをクリックして、XCodeを起動し、以下の操作を行います。

  1. General->Signingを正しく設定(Automatically manage signingをチェックすると楽)
  2. Build Phases->Link Binary With Librariesより、libPods-tflite_camera_example.aを削除
  3. Product->Cleanでクリーンする
  4. ビルド→実行

すると、以下のように、カメラを向けたものの分類がリアルタイムに行われます。

f:id:tuti107:20171126175605p:plain

当方の環境(iPhone X)では、30fps以上の性能が出ていました。また、身の回りのもので試しただけなのでまだなんとも、ですが、なかなかの精度で分類できていたように思います。

終わりに

最新のスマホ環境では、Tensorflow Lite(+MobileNet)による分類は、かなり快適に動作するようです。
次回は、UnityよりTensorflow Liteを利用し、簡単なアプリを作成してみようと思います。

Zap Boxを試してみた

Kickstarterで話題になった「紙」によるモバイルMRデバイス「Zap Box」が来ました!

https://ksr-ugc.imgix.net/assets/014/343/180/f83aa4de35e0f5a2dec70939e4fabf00_original.gif?w=680&fit=max&v=1478005546&auto=format&gif-q=50&q=92&s=23873e5c4c2129f91a95e1f8ef7e7951

ポジショントラッキングのためのマーカも、ハンドトラッキングのためのスティックもすべて紙でできています。

f:id:tuti107:20171009220049j:plain

この円形のマーカを部屋のあちこちに設置することで、モバイルデバイスのポジショントラッキングが可能となり、例えばARKitやARCore対応のアプリケーション相当のアプリが動きます。
ARKit/ARCoreは、特別なマーカ無しでポジショントラッキングができてしまっているので、Kickstarterでの応募当時はモバイルでMR!すごい、という感じでしたが、今となっては少し時代遅れ感は否めません・・

f:id:tuti107:20171009220512p:plain

ハンドトラッキング用のデバイスにはトリガーがついています。操作感はViveと同じ感じですが、少しオーバー気味に手を動かすとすぐにトラッキングをロストしてしまいます。
スマホカメラでマーカを認識するという制約上しかたがないのですが、カメラの視野角から外れるとトラッキング不能となります。
また、デバイスをゆっくり動かさないとトラッキング不能となります。
なお、専用のレンズを付けることで、視野角の問題はある程度解消されるようです(私は試せていません)。

なお、トリガーを引くと、マーカの一部が動きます。これを認識してアクションが起こるようです。

本デバイスに対応のアプリは、現状、公式アプリZapBox betaのみのようです。本アプリには、ミニゴルフ等のゲームが同梱されております。
ただ、上記のトラッキングの問題から、操作は結構大変です・・

f:id:tuti107:20171009221431p:plain

左上のCardboardアイコンをタップするとVRモードとなります。なお、立体視には対応していません。

総評

色々と文句を書きましたが、コンソール型のVR的なポジショントラッキング・ハンドトラッキングのUXを$30という低価格でモバイルに持ち込んだ、というのはすごいと思います。
現状SDKは公開されていないようですが、SDKが公開されれば、対応アプリも増え、低価格帯のモバイルVR市場の一角を担えるかもしれません。

SDKが公開されたら、色々と試してみたいと思います。

ARCoreでポジショントラッキング

過去、VuforiaKudanARKitにてモバイルVR向けのポジショントラッキングを実現する方法を書いてきました。
今回は、先日Googleより発表されたARCoreを利用したポジショントラッキングを実現します。

f:id:tuti107:20170916180729p:plain

ARCoreのインストール

ARCoreを利用するためには、以下が必要です。

現状ARCoreをサポートする端末は、Galaxy S8, Pixel, Pixel XLの三種類のみです。
これら端末でARCoreを利用するためには、arcore-preview.apkをダウンロードし、adbで端末に書き込む必要があります。

adb install -r -d arcore-preview.apk

UnityでARCoreのサンプルを実行する

まず、以下の手順でARCore SDK for Unityに付属のサンプルシーン(HelloAR.unity)を動かしてみます。

  • arcore-unity-sdk-preview.unitypackageをインポート
  • HelloAR.unityをダブルクリック
  • File->Build Settingsにて、PlatformをAndroidに切り替える
  • Edit->Project Settings->Playerにて、以下の通り設定
    • Other Settings > Multithreaded Rendering: Off
    • Other Settings > Package Nameに適当な名前を設定(例えばcom.example.helloAR)
    • Other Settings > Minimum API Level: Android 7.0以上
    • Other Settings > Target API Level: Android 7.0 か 7.1
    • XR Settings > ARCore Supported: On
  • 端末をUSB接続し、Build & Run

アプリを起動すると、数秒ほど「Searching for surfaces...」と表示され、その通り平面を探します。平面が見つかると、平面上にメッシュが表示されます。
メッシュの上をタップすると、そこにドロイドくんが配置されます。技術的にはARKitと同様の感じです。

ARCoreでポジショントラッキング

次に、ARCoreを利用してGoogle Cardboardにてポジショントラッキングを実現します。

まず、以下のスクリプトを作成します。

using UnityEngine;
using GoogleARCore;

public class PosiTra : MonoBehaviour {

  private Vector3 origPos;

  void Start () {
    origPos = gameObject.transform.position;
  }

  void Update () {

    if (Frame.TrackingState == FrameTrackingState.Tracking)
    {
      var pose = Frame.Pose;
      gameObject.transform.position = pose.position + origPos;
    }
  }
}

ARCoreには、カメラ位置・回転を取得するためのPoseクラスが用意されているため、非常に簡単にポジショントラッキングが実現できます。

次に、以下の通り、シーンを編集します。

  • GoogleARCore/Prefabs/ARCore Device.prefabをシーンに配置。Session ComponentのFirst Person CameraをNoneにする(カメラライブビュー表示を削除するため)
  • 空GameObjectを作成し(Playerとします)、PosiTraコンポーネントを追加
  • ARCore Deviceの子オブジェクトFirst Person CameraをPlayer配下へ移動


最後に、Edit->Project Settings->Player->XR Settings->Virtual Reality Supportedをチェックし、SDKsにCardboardを追加して、Build & Runします。

youtu.be

おわりに

ARCoreを使うと、ARKit同様の高品位なポジショントラッキングをGoogle Cardboardアプリで実現できます!・・が、対応機種が少なすぎます・・
ARCoreを活用したVRアプリが量産される、ためには、ARCoreの対応機種がもっともっと増える必要がありそうです。

Windows Mixed Reality向けヘッドセットが来ました

こちらで予約受付がされていた(現状品切れ)Acer製のWindows Mixed Realityヘッドセットが、本日届きましたので、さっそく試してみました。

f:id:tuti107:20170826155918j:plain

セットアップ

ハードウェアのセットアップは非常にシンプルです。他のコンソール型のVRヘッドセットのようなたくさんのデバイス群は存在せず、上記写真のヘッドセットのみ、です。
これをPCにHDMI、USB接続するだけで、デバイスのセットアップは完了です。すばらしい!!

次にソフトウェアのセットアップです。ハードウェアのセットアップが完了すると、以下のウィンドウが現れます。
f:id:tuti107:20170826160218p:plain

セットアップも非常にシンプルで、身長入力→フロアの認識(腰の高さでヘッドセットを持つだけ)→ガーディアンを設定して終了です。
ガーディアン設定時に体験できますが、OculusやViveのような外部デバイスがないにも関わらず、正確にポジショントラッキングが行われています。
f:id:tuti107:20170826182029p:plain

その後、以下のような空間が表示されます。
f:id:tuti107:20170826184050p:plain

動かしてみる

ヘッドセットは、Oculus等と比較して非常に軽く、装着感がよいです。
またヘッドセットをつけて部屋を歩き回ることで、空間内を自由に歩き回ることができます。若干のラグや、実モーションに対する空間内での動きの違和感を感じましたが、それでも外部デバイスなしでここまでのポジショントラッキングができていることに感動しました。

なお、本製品には(開発者用ということもありますが)一切の入力デバイスが同梱していません。また、HoloLensのようなジェスチャによる入力(タップ、ブルーム)もありません。
ただ、マウスを使って、テレポート(右クリックで写真の青カーソールを出し、離して移動)や、マウスを空間内で動かしてポインティング・クリックが可能です。このため、机に座ってVRするなら、まぁ問題ありません。

また、ヘッドセットの前方左右にカメラがついているため、てっきりこれで外部映像を入力し、立体視表示して、ホロレンズ的な体験ができる!と思っていたのですが、これは単にポジショントラッキング用のセンサーのようです。残念・・

MFT2017に出展したVRコンテンツ

f:id:tuti107:20170820085956j:plain

今年もMaker Faire TokyoにVRコンテンツを出展しました。

www.youtube.com

へなちょこCooking

Oculus Touchを活用したVR料理ゲーム(?)です。
食材をナイフでカットし、焼き色を付けて、皿に盛りつけます。
盛り付けが完成すると、AIがその料理に名前をつけてくれます。

食材のカット

Turbo Slicer 2を使用しました。
youtu.be

MeshRendererをもつオブジェクトに、Sliceableコンポーネントをセットするだけで、そのメッシュをスライスすることができます。
何点か、使用上の注意点ですが、

  • Sliceableのエディタ拡張のバグ?により、断面部分のテクスチャ領域の設定がうまくいきません(設定が無視され、デフォルト値となる)
  • 手のちょっとしたブレなどで、大量に細かくスライスされてしまいます。何十・何百の細かなオブジェクトが生成されてしまい、処理がものすごく重くなります。私は、スライス後のオブジェクトの体積が一定以下の場合は、そのオブジェクトを削除するようにしました。

人間っぽいキャラクタの動きの実現

定番ですがFinal IKのVRIKを使用しました。
www.youtube.com

  • Vive用の設定情報はあるのですが、Oculus Touch用が見つからず・・ただ、OVRCameraRigに簡単に設定できました。
  • Grounder IKを設定しないと、足が思うように動いてくれません(上記チュートリアルにはでてこない)。Grounder IKについては、_Demo/VRIK/VRIK(Grounder).unityが参考になります(というか、コピペ)

キャラクタの手の動き

OculusFingerを利用させていただきました。
eyln.hatenablog.com

お皿に食材を盛り付け

Unity 5より、Mesh ColliderはConvexにしなければならなくなり、お皿のように真ん中がくぼんた形状のMeshの当たり判定が、想定通りとなりません。そこで、多数のBoxColliderでMeshColliderをエミュレートする、Non Convex Mesh Colliderを利用しました。

youtu.be

使い方は簡単で、これまでMeshColliderを張り付けていたコンポーネントにNonConvexMeshColliderをセットし、Boxes Per Edgeを適当な数字として、Calculateボタンを押すだけです。Boxes Per Edgeを大きくすると、より細かなBoxColliderでエミュレートされますが、処理が重くなります。また、

  • Create Child Game Objectのチェックを外すと、NonConvexMeshColliderがセットされたオブジェクトに多量のBoxColliderがセットされます。
  • Create Child Game Objectのチェックをチェックした場合は、子オブジェクトが生成され、そこにBoxColliderがセットされます。この場合、衝突判定処理の修正(GetComponent→GetComponentInChildren)が必要かもしれません。

名前付け

im2txtを使用しました・・詳細は本作品を一緒に開発した友人にお任せだったため、よくわかりませんが・・
soralab.space-ichikawa.com

なお、im2txtは画像認識の結果を英語の文章で返すのですが、これを日本語化するために、Google Translateを使用しました。

肝試しVR

Gear VR/Daydream/Google Cardboard向けのホラーVRゲーム(?)です。
ライド型のお化け屋敷アトラクションであり、プレーヤは歩いたりしなくても、乗り物が動いて勝手に進んでいきます。
特段のゲーム性はなく、ひたすら怖いモンスターや超常現象を見て楽しむ、コンテンツです。

お化け屋敷のセットには、Abandoned Hospitalを使用しました。
youtu.be

・・何も出てこなくても十分に怖いです・・
なお、モバイル向けのアセットではないので、そのまま使用すると、GearVR等では全然性能が出ません。涙ぐましい性能調整が必要でした・・

本コンテンツは、近々(秋になる前に)Oculus Store等に載せたいな、と画策中です。

ラズパイZero WでMovidius NCSを動かす

f:id:tuti107:20170819110519j:plain

前回は、苦戦しながらもラズパイ3にUbuntuをインストールし、Movidiusを動かしました。
今回は、ラズパイ3ではなく、より安価・小型(でも非力)なラズパイZero Wで、Movidiusを動かしてみます。

なお、ラズパイZero Wはラズパイ2・3とARMアーキテクチャが異なるため、ラズパイZero W向けのUbuntuイメージは提供されておりません。
しかし、以下のサイトに記載の通り、Movidius向けのモデル生成にはUbuntuが必要だが、生成したモデルを利用してMovidiusを動かすだけであればRaspbianで問題ないとのこと。

flow-developers.hatenablog.com

このサイトはラズパイ2向けですが、基本ラズパイZero Wでも大差ないだろうと考え、試してみました。

結論から言うと、ラズパイZero Wでも一応動作しました。

手順

基本、上記サイトに記載の通りです。異なる点といえば、

  • RASPBIAN STRETCH LITEを使用した
  • 今回はUSBカメラを接続できなかったため、前回参考した手順サイトの「ねこの認識」で動作確認をした

ことくらいです。
ただ、一度Movidiusのデバイスが認識されず、ncs-fullcheckが失敗したことがあったのですが、その後なぜか、ncs-fullcheckを実行しても何も起こらなくなってしまいました。再度makeすることで治りましたが、原因はよくわかりません。

ラズパイにUbuntu 16.04 LTSをインストールし、Movidius NCSを試す

話題のMovidius NCSを入手しました。

f:id:tuti107:20170818072407j:plain

非常に安価で、かつUSBポートに差すだけで、Deep Learningによる認識処理を高速に実行できる、ということで、
ラズパイにMovidius NCSを接続すると色々面白いことができそう。

ラズパイでMovidius NCSについては、以下に手順が詳細記載されております。
qiita.com

基本「上記の手順の通り」なのですが、色々と苦戦・・ちゃっちゃと環境を作って色々試したいと思っていたのですが、「まずは動かす」ことで精いっぱいでした。

以下、はまった点などの備忘録です。

ラズパイにUbuntuを入れる

上記サイトに記載の通り、https://wiki.ubuntu.com/ARM/RaspberryPiからイメージを取得し、SDカードに書き込み、という手順を試みたのですが、何度やっても(上記手順サイトには記載はないが、イメージDLサイトに記載のある)Optional PPAをインストールすると、Ubuntuが起動不能になってしまいました。

途方にくれていたところ、以下のサイトを発見。
tiryoh.com

本サイトの「初期設定済み版」を利用させていただきました。

なお、WindowsにてイメージをSDカードに書き込む方法ですが、
入手したイメージを、7-Zipなどで展開し、Win32 Disk Imager等で、SDカードに書き込めばOKです。

f:id:tuti107:20170818065928p:plain

ツールキットのインストール

上記手順サイトの通り、

cd bin
./setup.sh

とすると、数時間のインストール作業のの後、「c++: internal compiler error: Killed」でエラー終了・・

UbuntuをGUI版にしたせいでしょうか?どうやらメモリー不足によるエラーのようです。そこで、

dd if=/dev/zero of=/var/swap.img bs=1024k count=1000
mkswap /var/swap.img
swapon /var/swap.img

としてスワップ領域を追加して再度インストールしました。

f:id:tuti107:20170818071037p:plain

なお、この状態でmake checkすると、Import Errorが表示されますが、パスの問題のようで、再度bash立ち上げれば消えます。
また、ttyでmake checkすると、今度は「Gdk-CRITICAL **: gdk_cursor_new_for_display: assertion 'GDK_IS_DISPLAY (display)' failed」が表示されます。ただ、GUIでのコンソール(MATE Terminal)では表示されないし、とりあえずよしとしました。

その後の手順

その後の手順は、手順サイトに記載のとおりうまくいきました。