なんかいろいろしてみます

Apr 11, 2018 - 2 minute read - HoloLens

HoloLensとWindowsMLとCustomVisionを使って手書き認識をしてみる(学習データ利用編)

前回の HoloLensとWindowsMLとCustomVisionを使って手書き認識をしてみる(データ収集編) の続きです. 今回は整理された画像をCustom Visionサービスを利用して機械学習を行い,作成した学習モデルを利用して手書きの数字を認識できるようにします.

準備

前回のデータ収集編で整理した画像データを確認します.

0から9までのフォルダの中に番号と同じ画像を入れておきます.

Custom Visionでの機械学習

プロジェクトの作成

  • アカウントの作成が完了したらプロジェクトを作成します.
  • Nameにプロジェクトの名前(今回は「PaintRecognition」にしています)
  • Domainsを「General(compact)」に設定してCreateProjectを押します.

画像データのアップロード

  • プロジェクトの作成が完了したら,画像の登録を行っていきます.
  • 以下の画像の「Add Images」を選択するとファイルのアップロードが行えるようになります.

  • 同じ番号の画像ファイルを選択してアップロードを行うと以下の画像のように画像のタグ登録が行えるようになります.(今回は番号で画像の整理を行ったので番号のタグをつける)

  • 0から9までのタグ付けが完了後手書き認識のための学習モデルの作成移ります.

機械学習の実行

  • 画面上部の緑色のTrainボタンを押すことで機械学習が行われます.

  • 学習が完了すると学習されたモデルデータの適合率と再現率が表示されます.

学習結果の確認

  • 学習モデルの結果を別の画像を入力した場合に認識できるかを確認することもできます.
  • 画面上部のQuick Testを選択して認識させたい画像をアップロードすることで学習結果を確認することができます.

学習モデルの出力

  • 作成した学習モデルをWindowsMLで利用するためにモデルのダウンロードを行います.
  • モデル作成完了画面のExportボタンからダウンロードできるモデルの種類を選択できます.
  • 今回は「iOS 11 (CoreML)」を選択してダウンロードを行ってください.

学習モデルの変換

Custom Visionからダウンロードした学習モデルはそのままではWindowsMLで利用することができません. WindowsMLで利用できるONNX形式に変換する必要があります. 変換方法には何通りかありますが,今回はWindowsにBash on Windowsを導入して変換していきます.

Bash on Windowsの利用準備

Bash on WindowsはWindows上でUbuntuなどのLinuxシステムが利用できる機能です. Linuxのシステムが利用できることで,Windows環境では機能しないor提供されていない機能を利用することができます. 標準状態ではこの機能は有効化されていないため,有効化して利用できるようにします.

Bash on Windowsの有効化とインストール

  1. Windowsの設定画面から「アプリと機能」選択し,関連設定の「プログラムと機能」を選択します.
  2. プログラムと機能を開いたら「Windowsの機能の有効化または無効化」を選択し,「Windows Subsystem for Linux」を有効化します.(再起動が必要になる場合があります)
  3. 「Windows Subsystem for Linux」を有効化後,「Microsoft Store」より「Ubuntu」をインストールします.
  4. インストール完了後Ubuntuを起動すると以下の画像のようにユーザー名とパスワードを入力すればインストール完了です.(ここでのユーザー名とパスワードはUbuntu内でのみ使われる新しいものです)

環境設定

続いて学習モデルを変換する環境を設定します. 以下のコマンドを順番に入力して環境をインストールします.

  1. sudo apt-get update
    • Ubuntu全体のアップデートを確認します.
  2. python3 -Vでバージョン(Python 3.5.2)が表示されることを確認
    • Python3がインストールされていることを確認します.
  3. sudo apt install python3-pip
    • Pythonのパッケージ管理ソフトpipをインストールします.
  4. pip3 install winmltools
  5. pip3 install coremltools
    • pipからONNX形式の学習モデルに変換するためのパッケージをインストールします.

インストールが無事に完了すれば環境設定は完了です.

CoreMLからONNX形式への変換

ダウンロードした学習モデルをWindowsMLで利用できるONNX形式に変換します. あらかじめダウンロードした学習モデルはわかりやすい名前に変更しておいてください(今回は PaintRecognition.mlmodel としています)

学習モデルの変換のためにPythonのコードを書きます. 以下のコードを適当な名前(今回はcoreml2onnx.py)として保存して学習モデルデータを同じところに保存します.

12345678
from coremltools.models.utils import load_spec
model_coreml=load_spec('PaintRecognition.mlmodel')
from winmltools import convert_coreml
model_onnx=convert_coreml(model_coreml,name='PaintRecognition')
from winmltools.utils import save_model
save_model(model_onnx,'PaintRecognition.onnx')
from winmltools.utils import save_text
save_text(model_onnx,'PaintRecognition.txt')

coremltoolsでmlmodelファイルの開き,winmltoolsでonnxに変換しています.

Pythonスクリプトを保存後,上記でインストールしたUbuntuを起動してcoreml2onnx.pyを実行します.

coreml2onnx.pyと学習モデルの場所がD:\にある時Ubuntuでのコマンドは以下のようになります. - cd /mnt/d/ + ファイルのある場所に移動 - python3 ./coreml2onnx.py + スクリプトの実行

正常に実行できればスクリプトファイルと同じ場所に「PaintRecognition.onnx」と「PaintRecognition.txt」が生成されます.

ONNX形式クラスの生成

onnxはそのままでもUWPプロジェクトで利用することもできますが,より使いやすくするためのツールも提供されています.

以下のコマンドをONNXファイルのある場所で実行するとC#でONNXを利用するためのクラスファイルが生成されます.

  • このコマンドはWindowsのコマンドプロンプトから実行してください
  • コマンド内の10.0.17115.0の部分はインストールしているWindows10 SDK Insider Previewのバージョンにあわせてください
    1
    "c:\Program Files (x86)\Windows Kits\10\bin\10.0.17115.0\x64\mlgen.exe" -i PaintRecognition.onnx -l CS -n PaintRecognition -o PaintRecognition.cs

学習モデルのUnityプロジェクトへの導入

WindowsMLを利用すためのONNX形式の学習モデルとC#で利用するためのクラスファイルを作成できたので,実際にUnityプロジェクトに組み込んで利用してみます.

今回も引き続きHoloLens用手書きアプリを使用します. - https://github.com/akihiro0105/WindowsMLDemo_PaintRecognition

  • PaintRecognition.onnx
    • UnityのStreamingAssetsフォルダにインポートします.
  • PaintRecognition.cs
    • Assets/Scripts内にインポートします.

PaintRecognition.csをインポートしたときにスクリプトのエラー発生するので修正します.

PaintRecognition.csの修正

  1. PaintRecognition.csにはONNXファイルに記述されている認識結果のタグ情報が入力されていません.このためタグ情報を追加してWindowsML利用時に何が認識されたかわかるようにします.
    • 今回は数字の認識モデルなので数字のタグを追加しておきます.
 1 2 3 4 5 6 7 8 9101112131415
public PaintRecognitionModelOutput()
        {
            this.classLabel = new List<string>();
            this.loss = new Dictionary<string, float>();
            loss.Add("0", float.NaN);
            loss.Add("1", float.NaN);
            loss.Add("2", float.NaN);
            loss.Add("3", float.NaN);
            loss.Add("4", float.NaN);
            loss.Add("5", float.NaN);
            loss.Add("6", float.NaN);
            loss.Add("7", float.NaN);
            loss.Add("8", float.NaN);
            loss.Add("9", float.NaN);
        }
  1. Unityでは標準では最新のC#に対応していないため,PaintRecognition.csのコードはエラーが表示されています.UnityEditor上ではWindowsMLは利用せずHoloLensの動作するUWP環境のみで動作するようにします.
    • #if UNITY_UWP#endifを追加してUnityEditor上ではコードが有効にならないようにします.
 1 2 3 4 5 6 7 8 9101112131415
#if UNITY_UWP
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Media;
using Windows.Storage;
using Windows.AI.MachineLearning.Preview;

// PaintRecognition

namespace PaintRecognition
{
  // 略
}
#endif
  1. 元からプロジェクトで利用していた学習モデルから今回作成した学習モデルに切り替えて利用するため「PaintML.cs」も修正します.
    • 手書きデータの保存は行わないため1行目はコメントにします.
    • usingの numberを今回利用する PaintRecognitionに変更します.
 1 2 3 4 5 6 7 8 910111213141516
//#define ACTIVE_IMAGECAPTURE

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.UI;
using System;
#if UNITY_UWP
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Media;
using Windows.Graphics.Imaging;
using System.Runtime.InteropServices.WindowsRuntime;
using PaintRecognition;
#endif
  • 読み込むONNXファイル名を変更します.
1234567
 public RenderTexture renderTex;
    public Text TextData;

    private Texture2D tex;
    private byte[] bytes = null;
    private int TexWidth, TexHeight;
    private string onnxName = "PaintRecognition.onnx";
  • 変更されたクラス名に応じて関数名も変更します.
 1 2 3 4 5 6 7 8 91011121314151617181920
private async Task MachineLearningTask()
    {
        var ModelInput = new PaintRecognitionModelInput();
        var ModelGen = new PaintRecognitionModel();
        var ModelOutput = new PaintRecognitionModelOutput();
        try
        {
            StorageFile modelFile = await ApplicationData.Current.LocalFolder.GetFileAsync(onnxName);
            ModelGen = await PaintRecognitionModel.CreatePaintRecognitionModel(modelFile);
        }
        catch (Exception e)
        {
            UnityEngine.WSA.Application.InvokeOnAppThread(() =>
            {
                TextData.text = e.ToString();
            }, true);
        }
      // 略

    }

修正後UWP用にビルドを行いVisualStudioにてHoloLensに配置,実行を行うと自分で作成した学習モデルで手書き認識ができるようになります.

まとめ

  • 学習用画像データを用いてCustom Vision内で機械学習を行い学習モデルを作成できた
  • 学習モデルをダウンロードしてWindowsMLで利用するためにONNX形式に変換できた
  • 変換した学習モデルをUnityプロジェクトにインポートして自作の学習モデルでの手書き認識ができた
  • 数字以外にもひらがな,カタカナ,アルファベット,記号などなんでも行けると思うので,時間があれば画像データを集めてみてください