Custom Vision Serviceから出力したモデルを使ってWindowsML上で物体認識をする（その３　UWPアプリの作成）

[前回](https://qiita.com/linyixian/items/65e979fa3714a6f1b8af)に生成したモデルクラスと、モデルデータを使ってUWPアプリを作成します。

##onnxモデルを組み込んでUWPアプリを作成する

・VisualStudio2017で「ファイル」＞「新規作成」＞「プロジェクト」＞「空白のアプリ（ユニバーサルWindows）」を選んで新規プロジェクトを作成します。

・ソリューションエクスプローラー内のAssetsフォルダを右クリックして「追加」＞「既存の項目」を選択し、「vegetable.onnx」をフォルダに追加します。
・追加した「vegetable.onnx」ファイルのプロパティのうち「ビルドアクション」を「コンテンツ」に、「出力ディレクトリにコピー」を「新しい場合はコピーする」に設定します。
![16.PNG](https://qiita-image-store.s3.amazonaws.com/0/62606/3f7c2fd1-5ba2-4226-bfbd-149a9add3457.png)

・プロジェクト名を右クリックし、「追加」＞「既存の項目」を選択し、「vegtables.cs」をプロジェクトに追加します。

・「vegtables.cs」を開き、25行目以降に次の文を追加します。現時点ではmlgen.exeで生成したモデルクラスではtagをディクショナリに追加してくれないので手動で追加する必要があります。

``` C#:vegetable.cs
                :
                :
24:    this.loss = new Dictionary<string, float>();
25:    //以下を追加
26:    this.loss.Add("cabbage", float.NaN);
27:    this.loss.Add("cucmber", float.NaN);
28:    this.loss.Add("onion", float.NaN);
29:    this.loss.Add("poteto", float.NaN);
30:    this.loss.Add("tomato", float.NaN);
                :
                :
```

・UIを作成します。「MainPage.xaml」を開き、CaptureElementとTextBlockを適当に配置します。CaptureElementのサイズは縦横を同じにします。

・「MainPage.xaml.cs」は部分的に説明します。140行目以降がモデルクラスにデータを渡しています。

``` C#:vegetable.cs
                :
                :
140:  using (VideoFrame previewFrame =new VideoFrame(BitmapPixelFormat.Bgra8, 227, 227))
141:                  {
142:                      await this.mediaCapture.GetPreviewFrameAsync(previewFrame);
143:  
144:                      if (previewFrame != null)
145:                      {
146:                          inputData.data = previewFrame;
147:  
148:                          //AIモデルにデータを渡すと推定値の入ったリストが返る
149:                          outputData = await vegetableModel.EvaluateAsync(inputData);
150:  
151:                          //UIスレッドに結果を表示
152:                          var ignored = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,  () =>
153:                             {
154:                                 string result = "";
155:  
156:                                 result = " cabbage: "+outputData.loss["cabbage"].ToString("P")+"\n";
157:                                 result = result + " cucumber: " + outputData.loss["cucumber"].ToString("P") + "\n";
158:                                 result = result + " onion: " + outputData.loss["onion"].ToString("P") + "\n";
159:                                 result = result + " poteto: " + outputData.loss["poteto"].ToString("P") + "\n";
160:                                 result = result + " tomato: " + outputData.loss["tomato"].ToString("P");
161:                            
162:                                 this.msgTbk.Text = result;
163:                             });
164:                      }                    
165:                  }
                :
                :
```
・140行目でVideoFrameのサイズとフォーマット指定していますが、これはCoreMLから変換した際に出力した「vegetable.txt」に
　指定すべき内容が書かれています。

・ファイルの後半に以下のような記述があります。dim_valueは渡すべき画像サイズを、
　doc_stringには指定すべきフォーマットが記述されています。
　Custom Visionで作成したモデルデータはすべて共通でした。他のCoreMLモデルを変換した場合には違う値になることもあります。

``` :vegetable.txt
                :
                :
input {
    name: "data"
    type {
      tensor_type {
        elem_type: FLOAT
        shape {
          dim {
            dim_param: "None"
          }
          dim {
            dim_value: 3
          }
          dim {
            dim_value: 227
          }
          dim {
            dim_value: 227
          }
        }
      }
    }
    doc_string: "Image(s) in BGR format. It is a [N, C, H, W]-tensor. The 1st/2nd/3rd slices along theC-axis are blue, green, and red channels, respectively."
  }
                :
                :
```

アプリを実行した様子です。[https://youtu.be/PA-VsVtDSs4](https://youtu.be/PA-VsVtDSs4)

その他のプログラムは[GitHub](https://github.com/linyixian/WindowsML_sample)にてプロジェクトを公開していますので参照してください。

##最後に

いかがでしたでしょうか。WindowsMLとCustom Visionの組み合わせではAIについてそれほど詳しくなくても、リアルタイムで物体認識するアプリを作成することができました。
もちろんAIモデルはCustomVisionだけではなくonnx形式であれば利用できるものが多いと思いますので、物体認識以外にもアプリを作成できると思います。
次はDeveloper Dayでデモされていたリアルタイム画風変換アプリを作ってみたいと思っています。