【Unity】UnityでBarracudaを使ってMNISTの手書き文字認識をする
ディープラーニングで学習したOnnx形式のモデルをUnityで使う方法を説明します.
前回の記事でOnnx Runtimeを使用してOnnxのモデルを使用する方法を書きましたが,Unityの公式ライブラリのBarracudaでOnnxを使用することができるようになりました.
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が対応していないものがあり,エラーログが出たものがありました.
推論
推論部分のソースコードは長くないです.ONNXをロードをして,ONNXの入力の次元に合わせた,今回のMnistなら28x28の画像が入力なので,float[784]の配列からTensor型を作成して,それは関数に渡せば,推論できます.rendertextureを入力に使用することもできるので,カメラの描画をそのまま推論に使用できて便利です.
推論部分のソースコード
Sample
Unity2020.1.0fを使用して手書き文字認識のサンプルを作成しました.BarracudaはUnityのPackage Managerからinstallして使用できるようですが,Unity2020の影響なのか,BarracudaがPackageManagerのリストに表示されなかったので,Barracudaを使用しているUnityの強化学習フレームワークであるML-AgentsをinstallしてBarracudaを使用しました.
参考
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を使用できるようになりました.
ディープラーニングで学習したOnnx形式のモデルをUnityで使う方法を説明します.
Onnx形式のモデルをUnityで使用するには,
- Onnx Runtime
- OpenCVSharp
が使えそうですが,今回はOnnx Runtimeを使用したいと思います.
Unityのバージョンは2019.3.1fを使用しています.
SampleとしてMnistの手書き文字認識をしています.
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
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フォルダに入れます.
推論
推論部分のソースコードは長くないです.ONNXをロードをして,ONNXの入力の次元に合わせた,今回のMnistなら28x28の画像が入力なので,float[784]の配列を変換したものを関数に渡せば,推論できます.
ONNX Runtimeの詳しい使い方は
onnxruntime/CSharp_API.md at master · microsoft/onnxruntime · GitHub
推論部分のソースコード
手書き文字
Physics.Raycastを飛ばして,当たったオブジェクトのuv座標を取得して,対応する場所のtextureの色を書き換えることで文字を書いています.
Sample
参考
【Unity】UnityのProfilerのデータを取得してCSVに書き出す
Profiler
UnityのProfilerはCPU、Memory、Renderingなどの実行時のデータが表示できます。そのデータをスクリプトから取得する方法を書きます。Unity 2019.3.0f1で実行してます.
取得したデータをcsvに書き出してgoogle データポータルで可視化すると下の画像みたいなグラフを作れます.可視化してチームで共有とかできれば,色々捗りそうです.
CPU
CPU Usage
ProfilerDriver.GetGraphStatisticsPropertiesForAreaとProfilerDriver.GetStatisticsIdentifierForArea関数で取得できます
CPU Hierarchy
ProfilerDriver.GetHierarchyFrameDataView関数で取得できます
Memory
ProfilerDriver.GetGraphStatisticsPropertiesForAreaとProfilerDriver.GetStatisticsIdentifierForArea関数で取得できます
Rendering
ProfilerDriver.GetGraphStatisticsPropertiesForAreaとProfilerDriver.GetStatisticsIdentifierForArea関数で取得できます
サンプル
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の頂点になるので,それを動かして任意の形を作る.
【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つあります.
- 追加するパスを定義するScriptableRenderPassを継承したクラス
- レンダリング順番を制御する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を使用したステンシルを用いたアウトラインの例
RenderTransparentForwardPass2
CustomRendererSetupにRenderTransparentForwardPass3のパスも追加したソースコード
【Unity】UGUIのImageで波エフェクトを作る
UGUIのImageで波エフェクトを作りました
使い方
https://github.com/n-taku/WaveEffectImageこのリポジトリの中の4つのファイル,ListPool.cs,ObjectPool.cs,Subdivide.cs,WaveMeshEffect.csを自分のプロジェクトにコピーする.
WaveMeshEffectコンポーネントを波エフェクトさせたいImageなどにつけて,コンポーネントのインスペクタからWaveInfoを編集する.
demo
スクリプト
WaveMeshEffectコンポーネントはBaseMeshEffectを継承していて,ModifyMesh関数で頂点を上下にoffsetしている.offset量はWaveInfoで指定したSin波を合成している
ListPool.cs,ObjectPool.csはUnityのInternalな非公開クラスで,Listを使い回すのに使っている
Subdivide.csはImageの頂点を増やして分割している.【Unity】「モダンなUIの提案と実装」 - テラシュールブログで使われていたクラスを少し直したもの
【Unity】追尾レーザー,誘導ミサイルの実装
Unite2018の誘導ミサイル完全マスターのスライドの追尾レーザーと誘導ミサイルのスクリプトを実際に動かしてみました.
追尾レーザー
現在の速度,到達時間,ターゲットの位置を元に加速度を計算して動かします. 加速度に制限をかけない限り絶対に当たります.
誘導ミサイル
ターゲットの位置,トルクの強さを用いて,ターゲット方向に向きを変えて,その方向に移動する.係数によってはバネのようにゆらゆらしながら飛んで行きます
参考URL