8_2_1 coco-ssd 物体検出アプリ

ブラウザ画面のボタンをクリックして写真を指定し、物体検出を行うアプリの作例です。

HTML:

<input type="file" id="input-file">
<img src="" alt="Image preview...">
<div id="image-container"></div>

CSS:

/* ページに読み込む画像用<img>要素は表示しない */
img {
    display: none;
}

JavaScript:

const inputFile = document.getElementById('input-file');
// ページには表示されない<img>要素
const preview = document.querySelector('img');
// [ファイルを選択]ボタンで画像を選択したら
inputFile.addEventListener('change', (e) => {
    // 取得したファイル
    const imageFile = e.target.files[0];
    // ファイルの読み取りに成功したら、readPromise.then()を実行する
    new Promise((resolve, reject) => {
        const reader = new FileReader();
        // ファイルの読み取りに成功したら解決する
        reader.onload = (e) => {
                resolve(e.target.result);
            }
            // ファイルを画像として読み取る
        reader.readAsDataURL(imageFile);
        // 成功したら、<img>要素に画像を割り当てる
    }).then((img) => {
        // 画像が読み込まれたら
        preview.onload = () => {
            // 読み込む画像の幅と高さ用変数
            const imageWidth = preview.naturalWidth;
            const imageHeight = preview.naturalHeight;
            // <canvas>を作成して、それに画像のイメージデータを割り当てる
            const canvas = document.createElement('canvas');
            canvas.width = imageWidth;
            canvas.height = imageHeight;
            const context = canvas.getContext('2d');

            // 画像に重ねて表示する矩形の色と線幅、文字の色、フォントの設定
            context.strokeStyle = "lightgreen";
            context.lineWidth = 2;
            context.fillStyle = "red";
            context.font = "30px 'MS ゴシック'";
            // キャンバスに画像を描画する
            context.drawImage(preview, 0, 0);
            // イメージデータを取得
            const imageData = context.getImageData(0, 0, imageWidth, imageHeight);
            // キャンバスをページに表示 = 写真が見えるようになる。
            document.getElementById('image-container').appendChild(canvas);

            // モデルを読み込む
            // 現在cocoSsdはcoco-ssdでオブジェクト化されているようなので、変数cocoSsd(サンプル通り)に代入している。
            const cocoSsd = window['coco-ssd'];
            cocoSsd.load().then(model => {
                // model.detect()にイメージデータを渡し、物体検出する
                model.detect(imageData).then(predictions => {
                    // console.log(predictions);
                    for (let i = 0; i < predictions.length; i++) {
                        // キャンバス(読み込んだ写真)の上に、物体を囲む矩形とクラス名を描画する
                        drawBox(context, predictions[i]);
                    }
                });
            });
        }
        preview.src = img;
    });
}, false);

/*
{
  bbox: [x, y, width, height],  // 物体を囲む境界ボックスのx値、y値、幅、高さ
  class: "person",              // 分類名
  score: 0.8380282521247864     // そうである確率
}
*/
// キャンバスの上に、物体を囲む矩形とクラス名を描画する
const drawBox = (ctx, pred) => {
    //console.log(pred.bbox);
    const box = pred.bbox;
    // 薄緑の矩形で物体を囲む
    ctx.strokeRect(box[0], box[1], box[2], box[3]);
    // 赤い文字でクラス名を描く
    ctx.fillText(pred.class, box[0], box[1] + 10, 80);
}

なお、上記コードを試すときには、cross-origin制約に引っかからないように、Webサーバー上で行う必要があります。

コメントを残す

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

CAPTCHA