LoginSignup
7
0

More than 1 year has passed since last update.

Unity x 機械学習 で遊んでみた【Unity Barracuda】

Last updated at Posted at 2021-12-18

anim.gif

⊂二二二( ^ω^)二⊃ブーン

この記事ではBarracudaについてざっくり理解してから、上のように遊んでみます
Unityはある程度触れるけどBarracudaは知らない人向けの内容です

Barracudaとは

image_01.png

  • NETORONに対応しており、UnityにインポートしたONNXファイルをダブルクリックするとNETORONで開ける

Hello World

こちらを利用して、MNISTによる手書き数字の推論をやってみる
https://github.com/keijiro/MnistBarracuda

image_02.png

MNISTとは

  • 手書き数字画像の大規模なデータベース
  • 手書き数字がどの数字か推論するための学習モデルとして使える
  • Wikipedia : https://ja.wikipedia.org/wiki/MNIST

手順

  1. クローンする $git clone git@github.com:keijiro/MnistBarracuda.git
  2. Unityで開く
  3. MnistTestシーンを開く Assets/MnistTest.unity
  4. シーンを実行すると、推論結果が表示される

image_03.png

コードを読む

        // Convert the input image into a 1x28x28x1 tensor.
        using var input = new Tensor(1, 28, 28, 1);

        for (var y = 0; y < 28; y++)
        {
            for (var x = 0; x < 28; x++)
            {
                var tx = x * _image.width  / 28;
                var ty = y * _image.height / 28;
                input[0, 27 - y, x, 0] = _image.GetPixel(tx, ty).grayscale;
            }
        }
  • 入力画像_imageをテンソルTensorに変換する処理
    • テンソル = 多次元配列
  • 機械学習の分野ではy軸方向が上から下、UnityのUV座標のV軸方向は下から上なので、yを反転させている
  • モデルに入力するテンソルの形式はONNXファイルのインスペクタで確認可能 (下の画像参照)
    • n:バッチサイズ, h:高さ, w:幅, c:チャネル数
    • チャネル数1 = グレースケール、チャネル数3 = RGB画像

image_04.png

        // Run the MNIST model.
        using var worker =
          ModelLoader.Load(_model).CreateWorker(WorkerFactory.Device.CPU);

        worker.Execute(input);
  • MNISTの学習モデルを元に推論を行う
  • workerIDisposable
  • CreateWorkerメソッドの第一引数でCPU/GPU実行を指定可能 ここではCPUを指定
        // Inspect the output tensor.
        var output = worker.PeekOutput();

        var scores = Enumerable.Range(0, 10).
                     Select(i => output[0, 0, 0, i]).SoftMax().ToArray();
  • workerから推論結果outputを取得し、0~9のそれぞれのスコアを配列scoresに格納
  • SoftMax()メソッドは受け取ったIEnumerableの全要素を0~1に正規化した値に変換
SoftMax.cs
    public static IEnumerable<float> SoftMax(this IEnumerable<float> source)
    {
        var exp = source.Select(x => Mathf.Exp(x)).ToArray();
        var sum = exp.Sum();
        return exp.Select(x => x / sum);
    }

補足など

  • Mnistのテンソルは(1,28,28,1)と小さいためCPU側で作成しても問題ないが、基本的にはComputeShaderを利用してGPU側で処理した方がいい
  • BarracudaとONNXファイルを利用すれば、ユーザーがするのはモデルの入出力データの整形くらい
    • ONNXファイルはいろいろなものが公開されてるので探してみるといい
      • "model zoo" で検索するとたくさんでてくる
    • 実際にはそのままでは動作させられないONNXの方が多いらしい
      • Barracuda未対応の機能を利用している場合、ONNXの修正で動作させられる場合もある

遊んでみた

Barracudaについてざっくり理解したので、次は遊んでみます
こちらを利用 (またしてもkeijiroさん)
https://github.com/keijiro/UltraFaceBarracuda

手順

  1. クローンする $git clone git@github.com:keijiro/UltraFaceBarracuda.git
  2. Unityで開く
  3. こちらの画像をDLしてプロジェクトにimport
  4. Assets/Marker/SunglassesMarker.prefabを複製し、パラメータを変更
    RectTransform > Scale : (2,2,2)
    RawImage > Texture : 先ほどimportした画像
  5. Visualizerシーンを開く Assets/Visualizer.unity
  6. シーン上のWebcam Testオブジェクトを有効にし、パラメータを変更
    Visualizer > Marker Prefab : 先ほど作成したPrefab
    WebcamInput > DeviceName : 右のSelectを押し、プルダウンから入力デバイスを選択
  7. シーンを実行

anim.gif

補足など

  • 先ほどの後Mnistと異なり、UltraFaceBarracudaではGPU(ComputeShader)でモデルの入出力データを整形している
    • ONNXファイル : Packages/UltraFace/ONNX
    • ComputeShader : Packages/UltraFace/Shader
  • 各クラスについてざっくり
    • Visualizer : FaceDetectorの作成/更新
    • FaceDetector : ComputeBufferの作成/破棄、モデル実行と前後処理のコンピュートシェーダ実行
    • ResourceSet : FaceDetectorで実行するONNXファイルと、その入出力データに対して実行するGPU処理(コンピュートシェーダ)の参照を持つ
    • Detection : UltraFaceによる推論結果情報をもつ構造体
    • SunglassesUpdater : Detectionに応じた位置にサングラスを表示する更新処理

最後に

簡単に Barracuda x 機械学習 で遊ぶことができました
機械学習を知らなくてもゲームは作れるし、なんとなく難しそうだったので敬遠してきましたが、今回触れてみて一気に身近に感じるようになりました
ゲーム x 機械学習 でどんなことができるか、考えてみようと思います

参考

keijiroさんによるBarracuda紹介動画
ぶっちゃけこの動画見た方がはy (ry

7
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0