Unity Barracuda に入門しやすいイメージ変換までの流れ

Unity Barracudaに入門しました。
他にも入門したい人がいると思うので、自分と同じ轍を踏まないように、
インストールから実行までの手順を残しておいたので参考にどうぞ。

最新版のv2.1.0-previewを使用しています。
旧版と最新は取扱方法が少し違うところもあるので、ご注意ください。

# はじめに
## Barracudaって何？ONNXって何？って方はこちら
そういう方はこちらの説明が非常にわかりやすいです。
18分46秒ありますが、ぜひ一度見てみてください。（丸投げですいません）

https://www.youtube.com/watch?v=dMgm4ZYfaUI

## 作業環境
- Mac M1 Big Sur
- Unity 2020.3.2f1
- Barracuda v2.1.0-preview
- [UniTask](https://github.com/Cysharp/UniTask) v2.2.5
- WebCamera （を使っていますが、RenderTexture でも代用できます）

## 対象者
* Unityを触ったことがあり、プログラムを書いて普通に実行できる人。
* UniTask 使っていますが、async/await 知らなくても大丈夫です。メインでは使っていません。

# インストールからイメージ変換までの手順
Unityプロジェクトは[こちら](https://github.com/machidyo/Hello-Barracuda)。

## 1. Barracuda のインストール
Unityで新しいプロジェクトを作って、Barracuda のインストールです。
[公式マニュアル](https://docs.unity3d.com/Packages/com.unity.barracuda@2.1/manual/Installing.html#github)を参考に、私は manifest.json を編集して入れました。

```json
  "dependencies": {
    "com.unity.barracuda": "https://github.com/Unity-Technologies/barracuda-release.git"
  }
```

## 2. ONNX モデルを準備します
1. [ONNX Model Zoo](https://github.com/onnx/models)（GitHub） からダウンロード  
このリポジトリにはONNX形式で事前トレーニング済みのモデルがたくさん格納されています。  
今回はこの中から [candy-8.onnx](https://github.com/onnx/models/tree/master/vision/style_transfer/fast_neural_style/model) をダウンロードしておきます。（※1）
2. Project の Assets 配下に Models みたいなフォルダを作り、candy-8.onnx をドラッグアンドドロップします。
3. Inspector にこんな感じで表示されていれば成功です。  
<img width=240 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/96fd4f11-6d6f-006d-4dea-e3079d8e957c.png" >

### ※1 補足
基本的には .onnx となっているものであれば他のものでも使用できるはずなのですが、現実的にはそこまでではなく、
使用しようとするとカスタマイズしてあげてないといけないケースが多いのが現状のようです。

## 3. プログラムの準備
1. GitHubの [Scripts](https://github.com/machidyo/Hello-Barracuda/tree/master/Assets/Scripts) 配下に、StyleChange.cs、Converter.cs、WebCamera.cs があるので、それぞれ作成してください。
2. StyleChange.cs が重要なので、一部を抜粋してコメントを入れて説明の代わりとさせてください。  
処理的には WebCamera を入力とし、modelAsset に設定したモデルを利用し、outputTexture に結果を表示するだけです。

```C#
    void Start()
    {
        // モデルをロード
        runtimeModel = ModelLoader.Load(modelAsset);
        // GPU設定、CPUもでできる
        var workerType = WorkerFactory.Type.Compute; 
        // モデルを実行するワーカーを作成
        worker = WorkerFactory.CreateWorker(workerType, runtimeModel);
    }

    async void Update()
    {
        // WebCamera の情報（イメージ）を、モデルが利用できるようにリサイズ
        var input = await Converter.ProcessImage(webCamera.Texture, IMAGE_SIZE);
        Inference(input);
    }

    private void Inference(Tensor input)
    {
        // 実行
        worker.Execute(input);
        // イメージ変換した結果を取得
        var output = worker.PeekOutput();
        // イメージ変換した結果を表示
        output.ToRenderTexture(outputTexture, 0, 0, 1 / 255f);
    }
}
```

## 4. Hierarchyの設定
1. 最終イメージはこのような感じです。  
<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/40ef0b67-bbd3-1506-618a-25ddd535b509.png" >
2. 変換したイメージを出力するのに RenderTexture が必要なので、準備しておいてください。Color Format に要注意です。  
<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/35db27b5-bced-374b-b4cd-d4575c2b78e0.png" >
3. 入力となる WebCamera を表示  
<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/6062def7-0a27-ec92-49b6-a2de7ce84186.png" >
4. 最後に StyleChange です。  
<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/77473a9f-cf54-0cf7-c92f-cf13e55b3f20.png" >

## 5. イメージ変換 〜後は実行するだけ〜
実行して正常に動作すればこのような感じで結果が表示されるはずです。

https://twitter.com/machidyo/status/1431274000538234888



# その他
## AssertionException が出る
以下のエラーが出るのは、利用しているモデルが必要としている入力と、
実際に入れている入力の次元があっていないケースです。
上記 Converter を使ってサイズ変更していれば大丈夫なはずですが、そうでないとエラーが出ます。

```
    AssertionException: Assertion failure. Values are not equal.
    Expected: 3 == 4
```

## 参考リンク集
1. [Unity 公式ドキュメント](https://docs.unity3d.com/Packages/com.unity.barracuda@2.1/manual/Installing.html)
2. [ONNX Model Zoo](https://github.com/onnx/models)
3. [Unity Technologies製推論エンジン Barracudaがスゴイという話](https://qiita.com/highno_RQ/items/478e1145f0eb868c0f2e)  
私自身はこちらの記事を参考にして実施しました。  
上述した通り、旧版と異なるところがあるので、補足を入れながらの手順となります。
4. [Unityの推論エンジン『Barracuda』を試してみたのでそのメモ](https://edom18.hateblo.jp/entry/2020/07/25/094400)  
Hello Burracuda としてはイメージ変換を選べたのはこのメモがあったからです。  
とっつきやすくさせてもらって非常に助かりました。
5. [Unity Barracuda 入門 / 画像分類](https://note.com/npaka/n/nedd82a5fd9bd)  
イメージの Tensor を揃えるコードはこちから拝借しています。  
ついでにWebCameraのコードもこちらから拝借しています。  
AssertionExceptionが出て終わったと思っていましたが、こちらのおかげで助かりました。