ゆにてく備忘録

Unityやその他学んだ事を忘れないために書くぶろぐ

【Unity】UnityでBarracudaを使ってMNISTの手書き文字認識をする

ディープラーニングで学習したOnnx形式のモデルをUnityで使う方法を説明します.

前回の記事でOnnx Runtimeを使用してOnnxのモデルを使用する方法を書きましたが,Unityの公式ライブラリのBarracudaでOnnxを使用することができるようになりました.

f:id:n_taku:20200808225653g:plain

unitech.hatenablog.com

Barracuda

Barracudaは軽量なニューラルネットの推論ライブラリで,CPUとGPUを用いた推論をすることができます.Burst Compilerを使用する設定もあります.

Onnx

Onnxはディープラーニングのモデルのフォーマットの代表的なフォーマットです.このOnnxファイルをInspectorで確認すると,モデルの情報が表示されます.Mnistのモデルは28x28の白黒画像を入力として0~9の10種類の値を出力するので,inputのshapeが(1,28,28,1),outputのshapeが(1,1,1,10)になっています.shapeの意味は(batch,width,height,channel)です.Onnxファイルはgithubなどにも落ちていますが,今回は適当に自分で学習させたモデルを使用しました.モデルによっては,Barracudaが対応していないものがあり,エラーログが出たものがありました.

f:id:n_taku:20200802130919p:plain

推論

推論部分のソースコードは長くないです.ONNXをロードをして,ONNXの入力の次元に合わせた,今回のMnistなら28x28の画像が入力なので,float[784]の配列からTensor型を作成して,それは関数に渡せば,推論できます.rendertextureを入力に使用することもできるので,カメラの描画をそのまま推論に使用できて便利です.

推論部分のソースコード

MnistInference.cs

UnityのBarracudaで推論するサンプル

--------

Sample

Unity2020.1.0fを使用して手書き文字認識のサンプルを作成しました.BarracudaはUnityのPackage Managerからinstallして使用できるようですが,Unity2020の影響なのか,BarracudaがPackageManagerのリストに表示されなかったので,Barracudaを使用しているUnityの強化学習フレームワークであるML-AgentsをinstallしてBarracudaを使用しました.

github.com

参考

Unityの推論エンジン『Barracuda』を試してみたのでそのメモ - e.blog

Unity Technologies製推論エンジン Barracudaがスゴイという話 - Qiita

Unity Barracuda - ニューラルネットワーク推論ライブラリ|npaka|note

Barracuda 1.0.0 - Unity用の軽量でクロスプラットフォームなニューラルネットワーク推論ライブラリ|npaka|note

【Unity】UnityでOnnx Runtimeを使ってMNISTの手書き文字認識をする

Unityの公式でOnnxを使用できるようになりました.

unitech.hatenablog.com

 

ディープラーニングで学習したOnnx形式のモデルをUnityで使う方法を説明します.

Onnx形式のモデルをUnityで使用するには,

  • Onnx Runtime
  • OpenCVSharp

が使えそうですが,今回はOnnx Runtimeを使用したいと思います.

Unityのバージョンは2019.3.1fを使用しています.

SampleとしてMnistの手書き文字認識をしています.

f:id:n_taku:20200229141158g:plain

ONNX Runtime

Microsoftオープンソースで公開しているクロスプラットフォームで高性能を目指している推論エンジンです.ONNXとはtensorflowやpytorchなどのフレームワークに依存しない,DeepLearningモデルのフォーマットです.

ONNXをUnityで使用するには以下のdllをUnityのPluginsフォルダに入れる必要があります.

Microsoft.ML.OnnxRuntimeはc#でonnx runtimeを使うためのラッパーで,その他のdllは依存パッケージです.NugetのパッケージをUnityで使用するには,ダウンロードした.nupkgファイルを.zipにリネームして解凍して,その中にあるdllをPluginsフォルダに入れる必要があります.詳細は

Unity で.NET 4.x を使用する - Visual Studio | Microsoft Docs

f:id:n_taku:20200229111950p:plain

libonnxruntimeはダウンロードするとlibonnxruntime.1.1.2.dylibのような名前になっています,1.1.2の部分を削除しないとエラーになるので,リネームしてlibonnxruntime.dylibをPluginsに入れます.自分の環境ではdylibのままで読み込めましたが,読み込みできないこともあるようです?

Unity x C++プラグインの連携【Windows/OSX】 - tecotec_engineer’s blog

ONNX

今回はMNISTの手書き文字認識のONNXモデルを使用して推論します.今回はgithubに上がっているモデルを使用します.

https://github.com/onnx/models/tree/master/vision/classification/mnist

model.onnxファイルをAssetsフォルダに入れます.

f:id:n_taku:20200229114045p:plain

推論

推論部分のソースコードは長くないです.ONNXをロードをして,ONNXの入力の次元に合わせた,今回のMnistなら28x28の画像が入力なので,float[784]の配列を変換したものを関数に渡せば,推論できます.

ONNX Runtimeの詳しい使い方は

onnxruntime/CSharp_API.md at master · microsoft/onnxruntime · GitHub

推論部分のソースコード

MnistInference.cs

UnityでOnnx Runtimeを使ってMnistの手書き文字認識をする

--------

手書き文字

Physics.Raycastを飛ばして,当たったオブジェクトのuv座標を取得して,対応する場所のtextureの色を書き換えることで文字を書いています.

ソースコード

Physics.Raycastを飛ばして,当たったオブジェクトのuv座標を取得して,対応する場所のt ...

--------

Sample

f:id:n_taku:20200229141158g:plain

github.com

参考

Unityでディープラーニングする方法調べた - Qiita

Unityでテクスチャにお絵描きしよう - おもちゃラボ

【Unity】UnityのProfilerのデータを取得してCSVに書き出す

Profiler

UnityのProfilerはCPU、Memory、Renderingなどの実行時のデータが表示できます。そのデータをスクリプトから取得する方法を書きます。Unity 2019.3.0f1で実行してます.

f:id:n_taku:20191222160628p:plain

取得したデータをcsvに書き出してgoogle データポータルで可視化すると下の画像みたいなグラフを作れます.可視化してチームで共有とかできれば,色々捗りそうです.

f:id:n_taku:20191222174008p:plain

CPU

CPU Usage

ProfilerDriver.GetGraphStatisticsPropertiesForAreaとProfilerDriver.GetStatisticsIdentifierForArea関数で取得できます

f:id:n_taku:20191222160752p:plain

CPUのProfilerデータ 

CPU Hierarchy

ProfilerDriver.GetHierarchyFrameDataView関数で取得できます

f:id:n_taku:20191222160803p:plain 

CPUのHierarchyのProfilerデータを取得 

Memory

ProfilerDriver.GetGraphStatisticsPropertiesForAreaとProfilerDriver.GetStatisticsIdentifierForArea関数で取得できます

f:id:n_taku:20191222161048p:plain

MemoryのProfilerデータ

Rendering

ProfilerDriver.GetGraphStatisticsPropertiesForAreaとProfilerDriver.GetStatisticsIdentifierForArea関数で取得できます

f:id:n_taku:20191222161059p:plain

RenderingのProfilerデータ

サンプル

https://github.com/n-taku/ProfileToCSV

このリポジトリではデータを実際にとって実際にそのデータをCSVとして書き出す機能を入れてます。 CSVにしてgoogleのデータポータルで可視化したりしてこの発表みたいなこともできそうです。

 

【Unity】uGUIのImageを変形して色々な形を作る

uuGUIのImageの頂点を追加したり削除したりして,色々な図形を作れます

使い方

https://github.com/n-taku/DeformationImage

このリポジトリのDeformationImage.csとDeformationImageVertex.csをプロジェクトに入れて,uGUIのImageにDeformationImageコンポーネントをつける.

DeformationImageのInspectorから頂点追加ボタンを押す.

頂点追加ボタンを押すと,DeformationImageの子供にDeformationImageVertexが追加される.

この子供のDeformationImageVertexがImageの頂点になるので,それを動かして任意の形を作る.

f:id:n_taku:20190511184950g:plain

f:id:n_taku:20190511183519p:plain

【Unity】LWRPの任意の場所にカスタムレンダーパスを追加する方法

Unity2019でのやり方は以下

Lightweight Render Pipeline(LWRP) のパイプラインを拡張する - Unity Connect

 

Unity 2018.3からLWRPの任意のタイミングでカスタムレンダーパスを追加することができるようになりました.Unity 2018.3 リリース – Unity Blog

そのやり方を書こうと思います.

Unity2018.3.1f1 LWRPのバージョンは4.6.0を使用してます.

必要クラス

Transparentのパスを追加する例で説明します.必要なクラスは2つあります.

  1. 追加するパスを定義するScriptableRenderPassを継承したクラス
  2. レンダリング順番を制御するIRendererSetupとMonoBehaviourを継承したクラス

追加するパス

追加するパスのクラスを以下ではRenderTransparentForwardPass2とする.

RenderTransparentForwardPass2は以下のように作成

  • LWRPのRenderTransparentForwardPassクラスをコピーして作成.
  • LWRPではShaderのLightModeタグで描画するShaderを決めています.作成したコンストラクタでそのタグの名前を定義しているので RenderTransparentForwardPassで使用している文字列"LightweightForward"とは別のものにします. ここでは"LightweightForward2"とします

RenderTransparentForwardPass2のソースコードは記事の最後

レンダリング順番を制御

LWRPではDefaultRendererSetupというクラスをデフォルトで定義しています.DefaultRendererSetupでは,パスの描画順を制御しています.

そのクラスを丸々自分で作成したクラスに置き換えることでパスを追加します.

レンダリング順番を制御するクラスを以下ではCustomRendererSetupとする.

CustomRendererSetupは以下のように作成

  • LWRPのDefaultRendererSetupのクラスをコピーして作成(※CustomRendererSetupはMoneBehaviourを継承させる)
  • 他のパスと同じようにRenderTransparentForwardPass2を宣言してnewを追加
  • 追加したいタイミングでRenderTransparentForwardPass2のSetUp関数をよび,renderer.EnqueuePassに追加

CustomRendererSetupのソースコードは記事の最後

使い方

上のクラスを作成して,パスを追加したいカメラに対してCustomRendererSetupコンポーネントをつけるだけで,カスタムレンダーパスを追加できます.

demo

上記を用いて3Pathを使用したステンシルを用いたアウトラインの例

github.com

f:id:n_taku:20190112183357p:plain

RenderTransparentForwardPass2

LWRPに追加するカスタムパス(Transparent)

CustomRendererSetupにRenderTransparentForwardPass3のパスも追加したソースコード

LWRP のレンダラーを上書きするためのカスタムしたRendererSetup

【Unity】UGUIのImageで波エフェクトを作る

UGUIのImageで波エフェクトを作りました

使い方

https://github.com/n-taku/WaveEffectImageこのリポジトリの中の4つのファイル,ListPool.cs,ObjectPool.cs,Subdivide.cs,WaveMeshEffect.csを自分のプロジェクトにコピーする.

WaveMeshEffectコンポーネントを波エフェクトさせたいImageなどにつけて,コンポーネントのインスペクタからWaveInfoを編集する.

f:id:n_taku:20180825194305p:plain

demo

f:id:n_taku:20180825194316g:plain

スクリプト

WaveMeshEffectコンポーネントはBaseMeshEffectを継承していて,ModifyMesh関数で頂点を上下にoffsetしている.offset量はWaveInfoで指定したSin波を合成している

UGUIのImageで波エフェクト

ListPool.cs,ObjectPool.csはUnityのInternalな非公開クラスで,Listを使い回すのに使っている

Subdivide.csはImageの頂点を増やして分割している.【Unity】「モダンなUIの提案と実装」 - テラシュールブログで使われていたクラスを少し直したもの

【Unity】追尾レーザー,誘導ミサイルの実装

Unite2018の誘導ミサイル完全マスターのスライドの追尾レーザーと誘導ミサイルのスクリプトを実際に動かしてみました.

追尾レーザー

現在の速度,到達時間,ターゲットの位置を元に加速度を計算して動かします. 加速度に制限をかけない限り絶対に当たります.

f:id:n_taku:20180729154356g:plain

追尾スクリプト

誘導ミサイル

ターゲットの位置,トルクの強さを用いて,ターゲット方向に向きを変えて,その方向に移動する.係数によってはバネのようにゆらゆらしながら飛んで行きます

f:id:n_taku:20180729154403g:plain

誘導スクリプト

参考URL

【Unite Tokyo 2018】誘導ミサイル完全マスター