Closed8

Unity Barracudaについてぼちぼち調査をしてみる

ぼいちぼいち

動画を見た学び

Tensorflowなどのニューラルネットワーク→ONNX→Unity Barracudaの順の開発って考えるとタスク整理のイメージがつく

マシンパワーがあればComputePrecomplied
https://github.com/keijiro/MnistBarracudaGpu

全プラットフォームに対応させたいのであればCSharp C#実装(IL2CPP)
https://github.com/keijiro/MnistBarracuda

ONNXがうまく動くモデルは多くない

  • 互換性
  • ONNX opsetの整合性
  • 未対応オペレーター
  • カスタムオペレーター
  • 未実装機能・バグ
ぼいちぼいち

公開されている処理を読み解いてみる


こんな感じのシーンがあって、

インスペクター上で代入した画像に対して予測される数字の確率が表示されている。

典型的なsoftmaxを用いた全確率出す系のタイプっぽい挙動をしていた

ぼいちぼいち

ソースコードを読んでみる

流れはざっくり入力を作る→NNに入れて出力を持ってくる→UI表示

入力

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;
            }
        }

これなんで1,28,28(枚数、縦、横)じゃないんだろう?
入力がそう制限されているから?

画像から一ピクセルずつ持ってきてグレースケールにしてfloat型で代入しているっぽい。

NNに入れて出力を持ってくる


using var worker =
          ModelLoader.Load(_model).CreateWorker(WorkerFactory.Device.CPU);

        worker.Execute(input);

        // Inspect the output tensor.
        var output = worker.PeekOutput();

入力して特にawaitとかしなくても取ってこれるのだろうか
これはさすがに同期処理だからUpdate化するときは非同期処理なのだろうか

出力


var scores = Enumerable.Range(0, 10).
                     Select(i => output[0, 0, 0, i]).SoftMax().ToArray();

        // Show the results on the UI.
        _imageView.texture = _image;
        _textView.text = Enumerable.Range(0, 10).
                         Select(i => $"{i}: {scores[i]:0.00}").
                         Aggregate((t, s) => t + "\n" + s);

ちなみにソフトマックス関数は独自で実装されていた。
対応がうまくいかない場合Unity上で自作するみたいな逃げ方もある

ぼいちぼいち


識別された!

動画を入れてみてもリアルタイムでマーカー表示された

ぼいちぼいち

クラスは3つ
Visualizer.cs
Marker.cs
IndirectDraw.cs

ぼいちぼいち

Visualizer.cs
ここでUpdate内でマーカーの管理をしているっぽい

void Update()
    {
        _detector.ProcessImage(_source.Texture, _threshold);

        var i = 0;
        foreach (var d in _detector.Detections)
        {
            if (i == _markers.Length) break;
            _markers[i++].SetAttributes(d);
        }

        for (; i < _markers.Length; i++) _markers[i].Hide();

        _preview.texture = _source.Texture;
    }
このスクラップは2023/12/01にクローズされました