ML.NET を利用したシンプルな画像判定プログラム - C#

ML.NET を利用したシンプルな画像判定プログラムを作成します。

作成するプログラム

Windows Vista, Windows 7, Windows 8, Windows 10, WIndows 11 の壁紙を学習させて、与えられた画像がどのWindowsの壁紙かを判定するプログラムを作成します。
こちらの記事で作成したプログラムのML.NET版です。

データの準備 (学習用画像)

以下の画像を準備します。壁紙の画像を縮小したり、一部分のみを切り出した画像です。
学習画像がクラスごとに5-6個必要です。(1,2個でも試してみましたが、結果がかなり悪いです)
Windows Vista
Windows 7
Windows 8
Windows 10
Windows 11

トレーニング、学習モデルの作成

Visual Studio を起動しWindows Formプロジェクトを作成します。


画像はimgフォルダ内に、分類クラスごとにフォルダを作成して配置します。


ソリューションエクスプローラーでプロジェクトのノードをクリックして選択し、右クリックします。 ポップアップメニューの[追加]サブメニューの[機械学習モデル]の項目をクリックします。


[新しい項目の追加]ダイアログが表示されます。[Machine Lewarning Model (ML.NET)]の項目が選択された状態になっています。 [名前]のテキストボックスにモデルのファイル名を入力して、モデルを作成します。今回はデフォルトの名称の "MLModel1.mbconfig" を利用します。


モデルファイルが作成され、下図の画面が表示されます。


[シナリオの選択]画面が表示されます。今回は[画像の分類]のタイルをクリックして選択します。


[トレーニング環境の選択]画面が表示されます。今回は [ローカル (CPU)] をクリックして選択します。画面下部の[次の手順]ボタンをクリックします。


[データの追加]画面が表示されます。[入力]セクションの[フォルダーの選択]のテキストボックスの右側の[...]ボタンをクリックし、画像を配置したフォルダを選択します。 今回は先に配置したプロジェクトのディレクトリの "img" フォルダを選択します。


フォルダが選択できると、[データのプレビュー]セクションに画像ファイルのサムネイルが表示されます。
画面下部の[次の手順]ボタンをクリックします。




[トレーニングする]画面が表示されます。[トレーニングの開始]ボタンをクリックします。


トレーニングが始まります。


トレーニングが完了すると下図の画面が表示されます。[次の手順]ボタンをクリックします。


[評価]の画面が表示されます。[独自のモデルを試す]セクションの[画像の参照]リンクをクリックし、検証用の画像を読み込みます。


検証用の画像を読み込むと判定処理が始まります。


結果が表示されます。99%のスコアでWindows 8の壁紙と判定されました。問題なさそうなので画面下部の[次の手順]ボタンをクリックします。


[使用]画面が表示されます。学習モデルを利用するコードが表示されます。[次の手順]ボタンをクリックします。


[次の手順]画面が表示されます。今回はモデルのデプロイは不要ですので、以上で終了です。

学習モデルを利用するプログラムの作成

Windows Formアプリケーションを実装します。
Windows FormアプリケーションにはML.NETのパッケージをインストールします。 ML.NETのインストールの手順はこちらの記事を参照してください。

UI

下図のフォームを作成します。テキストボックスを1つ、MultilineプロパティをTrueに設定した複数行テキストボックスを1つ、ボタンを2つ配置します。

コード

下記のコードを記述します。
using Microsoft.ML;
using Microsoft.ML.Data;

namespace SImpleImageClassified
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void button1_Click(object sender, EventArgs e)
    {
      if (openFileDialog1.ShowDialog() == DialogResult.OK)
      {
        textBox1.Text = openFileDialog1.FileName;
      }
    }

    private void button2_Click(object sender, EventArgs e)
    {
      //Load sample data
      var imageBytes = File.ReadAllBytes(textBox1.Text);
      MLModel1.ModelInput sampleData = new MLModel1.ModelInput()
      {
        ImageSource = imageBytes,
      };

      //Load model and predict output
      var result = MLModel1.Predict(sampleData);

      textBox2.Text += String.Format("この画像は : {0} / スコア: {1:f} \r\n", result.PredictedLabel, result.Score.Max());

      DataViewSchema.Column? col = MLModel1.PredictEngine.Value.OutputSchema.GetColumnOrNull("Score");
      VBuffer<ReadOnlyMemory<char>> value = default;
      col.Value.Annotations.GetValue("TrainingLabelValues", ref value);


      textBox2.Text += "スコア\r\n";
      for (int i = 0; i < result.Score.Length; i++)
      {
        textBox2.Text += String.Format("Label : {0}  Score : {1:f}\r\n", value.GetItemOrDefault(i).ToString(), result.Score[i]);
      }
    }
  }
}

解説

Machine Learning Model作成画面の[使用] 画面で生成されたコードを利用しています。
入力データは、画像ファイルをFile.ReadAllBytes で開きバイト配列を取得します。 ModelInputクラスを作成し、画像ファイルのバイト配列を ImageSource プロパティに代入します。 判定処理は、モデルクラスの Predict メソッドで実行します。引数に入力データの ModeiInput オブジェクトを与えます。
結果は、ModelOutput オブジェクトがPredictメソッドの戻り値で戻ります。PredictedLabel プロパティに判定結果のLabelの値が設定されます。 ScoreプロパティにそれぞれのLabelのスコアが設定されています。判定されたLabelのスコアは、Max() メソッドで値を取得できます。

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


テキストボックスを編集する。 または、[button1]をクリックしてファイルを開くダイアログで判定したい画像を選択してテキストボックスに画像のパスを入力します。
選択後[button2]ボタンをクリックします。


今回は下図の画像を選択しています。


下部のテキストボックスに結果が表示されます。画像は Windows 8 の壁紙と判定されたことがわかります。


次に下図の画像で結果を確認します。


Windows Vista の壁紙と判定できました。正しく判定できています。


下図の画像で結果を確認します。Windows 10の壁紙と似ていて、判定が難しめの画像です。


スコアが低いですが、Windows 11 の壁紙と判定できました。正しく判定できています。Windows Vistaのスコアが高いため、マシンラーニングのエンジン的にはWindows Vistaの画像と迷ったようです。


ML.NETを利用して、シンプルな画像判定プログラムを作成できました。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2022-01-13
作成日: 2022-01-08
iPentec all rights reserverd.