2_1_1:MobileNetとp5.jsを使った画像分類サンプル ml5.js JavaScript

以下は、ml5-examples/p5js/ImageClassification/ImageClassificationで公開されているサンプルのコード解説です。

次のリンクをクリックすると、このサンプルの動作が確認できます。
MobileNetとp5.jsを使った画像分類サンプル

HTML

<!--
 Copyright (c) 2018 ml5

 This software is released under the MIT License.
 https://opensource.org/licenses/MIT
-->

<html>

<head>
  <meta charset="UTF-8">
  <title>Image classification using MobileNet and p5.js</title>
  <link rel="shortcut icon" href="../../favicon.ico">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/p5.min.js"></script>
  <!-- https://p5js.org/reference/#/libraries/p5.dom -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/addons/p5.dom.min.js"></script>
  <script src="https://unpkg.com/ml5@0.1.2/dist/ml5.min.js" type="text/javascript"></script>
</head>

<body>
  <h1>MobileNetとp5.jsを使った画像分類</h1>
  <p id="status">モデルのロード...</p>
  <p>MobileNetモデルは<span id="probability">...</span>の信頼度で<span id="result">...</span>と分類しました。 </p>
  <script src="sketch.js"></script>
</body>

</html>

sketch.js

// Copyright (c) 2018 ml5
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

/* ===
ml5サンプル
MobileNetとp5.jsを使った画像分類
このサンプルでは、分類器の作成にコールバックパターンを使用している。
=== */

let classifier = null;
// 分類したい画像を保持する変数
let img = null;

// エラーと結果を得たとき実行する関数
const gotResult = (err, results) => {
    console.log('gotResult()が呼び出された');
    // コンソールにエラーを表示する。
    if (err) {
        console.error(err);
    }
    // 結果を保持する配列の要素数
    //console.log(results.length);
    // 配列内のオブジェクトが持つクラス名と確率を出力
    for (let i = 0; i < results.length; i++) {
        //console.log(results[i].className);
        //console.log(results[i].probability);
    }

    // 結果は、確率(probability)順に並んだ配列に保持されている
    select('#result').html(results[0].className);
    // https://p5js.org/reference/#/p5/nf
    // 数値を文字列にフォーマットするためのユーティリティー関数
    select('#probability').html(nf(results[0].probability, 0, 2));
    console.log('結果を表示した');
}

// 画像の読み込みが完了したら、その画像に関する推測を得る。
const imageReady = () => {
    console.log('imageReady()が呼び出された');
    // https://ml5js.org/docs/ImageClassifier
    // .predict(input, ?callback)
    // 与えられた画像やビデオについて、クラス名と確率を含むオブジェクトの配列を返す
    classifier.predict(img, gotResult);
    console.log('分類器による推測開始を開始し、結果が出たらgotResult()を呼び出す');
    // クラスの量は希望するだけいくつでも指定できる。
    // classifier.predict(img, 10, gotResult);
}

// モデルが読み込まれたら状態を変更する
const modelReady = () => {
    console.log('modelReady()が呼び出された');
    // https://p5js.org/reference/#/p5/select
    // 与えられたID、クラス、タグ名を持つ要素を検索し、それをp5.Elementとして返す
    // https://p5js.org/reference/#/p5.Element/html
    // 引数が与えられた場合には、要素のinnerHTMLを設定し、既存のhtmlを置き換える。
    // ID値がstatusの要素を検索し、innerHTMLプロパティ値を設定する。
    select('#status').html('モデルのロード完了');
    // https://p5js.org/reference/#/p5/noCanvas
    // p5スケッチ用のデフォルトキャンバスは要らないので、削除する。
    noCanvas();
    // イメージをロード
    // https://p5js.org/reference/#/p5/createImg
    // createImg(src, [alt], [successCallback])
    // 与えられたsrcとalternateテキストで、DOMに<img>要素を作成する。
    img = createImg('images/bird.jpg', imageReady);
    // https://p5js.org/reference/#/p5.Element/size
    // 要素の幅と高さを設定する
    img.size(400, 400);
    console.log('<img>の作成後、imageReady()を呼び出す');
}

// https://p5js.org/reference/#/p5/setup
// プログラムのスタート時、1回だけ呼び出される関数。constは使えない
function setup() {
    console.log('setup()が呼び出された');
    //const setup = () => {
    // ml5.imageClassifier()メソッドをMobileNetで初期化、コールバックを渡す必要がある。
    // ml5.imageClassifier(model, ?callback)
    // 訓練済MobileNetモデルを使った画像分類器をロードする。
    // ロードが終わったらmodelReady()関数を呼び出す。
    console.log('分類器の読み込み後、modelReadyを呼び出す');
    classifier = ml5.imageClassifier('MobileNet', modelReady);
}

1_2:Promiseとコールバックの使用に関する留意点」でも述べられているように、ml5.jsを使った機械学習アプリでは、「作業が終わるのを待つ」ことがポイントで、このサンプルでは、下図に示す順番で関数が呼び出されます。

setup()関数はp5.jsで定義されている特別な関数で、プログラムのスタート時に1回だけ呼び出されます。この関数の定義にはconstは使えません。setup()ではimageClassifier()を使って、訓練済MobileNetモデルによる画像分類器をインターネット経由で読み込み、それが終わったらmodelReady()関数を呼び出します。

modelReady()関数では、p5.dom.jsのcreateImg()を使って、p5.jsで扱える<img>要素を作成し、それが終わったらimageReady()関数を呼び出します。

imageReady()関数では、分類器のpredict()を使って画像を推測し、それが終わったら、gotResult()関数を呼び出します。

gotResult()には分類器による推測結果の配列(results)が渡されるので、それを処理してページに表示します。

resultsは配列なので、その要素数はlengthプロパティで分かります。resultsの要素はオブジェクトで、MobileNetのモデルが分類した名前(className)とその確率(probability)をプロパティとして持っています。これは次のようなコードで確認できます。

// 結果を保持する配列の要素数
console.log(results.length);
// 配列内のオブジェクトが持つクラス名と確率を出力
for (let i = 0; i < results.length; i++) {
    console.log(results[i].className);
    console.log(results[i].probability);
}

このサンプルではまた、p5.jsやp5.dom.jsの関数が多く使用されています。

  • select() – 与えられたID、クラス、タグ名を持つ要素を検索し、それをp5.Elementとして返す。
  • html() – 引数が与えられた場合には、要素のinnerHTMLを設定し、既存のhtmlを置き換える。
  • noCanvas() – p5用のデフォルトキャンバスは要らないので、削除する。
  • createImg() -与えられたsrcとalternateテキストでDOMに要素を作成する。createImg(src, [alt], [successCallback])

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA