5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Teachable Machineで画像認識! 棚卸時の注意点を表示するアプリっぽいものをつくってみた!

Last updated at Posted at 2024-09-23

半年に1度じゃ忘れるよなぁ・・・。

どうも、アラ還サラリーマンです。
とある地方の某小売業の会社で、店舗運営全般を統括する部署の管理部門の担当をしています。
管理部門では、店舗事務方のサポートやデータ管理などなど、多岐にわたる業務を担当しています。

わが社では年に2回の決算期に、各店舗で商品の棚卸を実施しています。
棚卸は会社の利益の確定のための重要業務です。
ですが、半年に1度のことということもあり、社内で決めた実施手順や監査手順を忘れてしまう人も結構います。
よし! 棚卸の時の注意点を表示するアプリっぽいものをつくってみよう!

というわけで、最近 Teachable Machine を少し触った機会があったので、今回はこれを試したいと思います。

実際にできた動画がこちら!

操作方法

  • 今回はサンプルとして、2種類の画像を認識させています。
  • スマホから【確認票】と【明細リスト】をカメラで認識させると、棚卸時の監査員の注意点をそれぞれ表示します。

今回使用したツール

  • Teachable Machine 機械学習モデルを簡単につくれます。
  • CodePen WEBアプリっぽいものがつくれます。
  • ChatGPT 兄さん───! 今回もお願いします!

Teachable Machine

  • 以下のリンク先から画像認識モデルを作成しました。

  • 【画像プロジェクト】を選択します。
    image.png
     
  • 【確認票】と【明細リスト】の2種類の画像ファイルをそれぞれ100枚ずつアップロード。
  • モデルをトレーニング後、モデルをエキスポートします。
    image.png
     
  • 【モデルをアップロード】を押してしばらく待つと、共有可能なリンク欄にリンクが表示されます。
  • 表示されたリンクと、その下にある【モデルを使用するコード スニペット】の p5.js をコピーしておきます。
    image.png

CodePen

  • 以下のリンク先からGoogleアカウントなどでログインします。(ログインしなくても使えますが、つくったものを保存できません)

  • Teachable Machine の【モデルをアップロード】時にコピーしておいた p5.js を HTML 欄に貼り付けます。
    image.png
    あれっ? p5.js のコードを貼っても動かない!
    カメラは動いてるみたいだけどなぁ。

ChatGPT

兄さん───! さっそく助けてください!
image.png

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<script src="https://cdn.jsdelivr.net/npm/@teachablemachine/image@0.8/dist/teachablemachine-image.min.js"></script>

image.png

let model, webcam, labelContainer, maxPredictions;

// モデルのURL
const URL = "your_model_url_here";

// モデルをロードして初期化
async function preload() {
  const modelURL = URL + "model.json";
  const metadataURL = URL + "metadata.json";
  model = await tmImage.load(modelURL, metadataURL);
  maxPredictions = model.getTotalClasses();
}

// ウェブカメラのセットアップと再生
function setup() {
  createCanvas(320, 260);
  webcam = createCapture(VIDEO);
  webcam.size(320, 240);
  webcam.hide();
  labelContainer = createDiv(''); // ラベルを表示する要素を作成
  labelContainer.position(10, 250); // ラベルの表示位置を調整
}

// フレームごとに予測を実行して描画
function draw() {
  background(220);
  image(webcam, 0, 0); // カメラ映像を描画
  predict(); // 予測を実行
}

async function predict() {
  const prediction = await model.predict(webcam.elt); // カメラ映像に対して予測を実行
  let resultText = '';
  for (let i = 0; i < maxPredictions; i++) {
    resultText += `${prediction[i].className}: ${prediction[i].probability.toFixed(2)}<br/>`;
  }
  labelContainer.html(resultText); // 予測結果を表示
}

なるほど! さすが、兄さん───!
さっそく素直に貼り付け実施!
image.png
おおっ! カメラもちゃんと写ってる!

おや? 気になることが書いてあるよ、兄さん───。
image.png
ウェブカメラの設定! さすが、兄さん───!
スマホで使用したいからインカメラじゃダメですよね!

あと追加したい点です、兄さん───!

  • 使うデバイスでパソコンの場合はWEBカメラ、スマホの場合はリアカメラに切り替える処理を加えたい。
  • Teachable Machineモデルの予測確率が90%以上の時だけ結果を反映させたい。それ以外の場合は非表示にしたい。

兄さんから教えてもらったコードに、【確認票】と【明細リスト】でそれぞれ表示させたい注意点を記載して出来上がり!

そしてできたものがこちら!(実は失敗例!)

あれれ? 注意点がチカチカするぞ!
あとこれも追加したいです、兄さん───!

  • 画面が落ち着かないので、3秒ごとに予測を行わせたい。

こんなお願いにも、当然応えてくれるわれらが兄さん───!

そして完成した 最終のコード がこちら!

let model, webcam, labelContainer, maxPredictions;
let lastPredictionTime = 0; // 最後に予測を行った時間を保存
const msg1 = [
  '【確認票 - 監査員の注意点】',
  '・担当者印の有無を確認!',
  '・監査印は2ヵ所に押印!',
  '・監査後、半券は回収表に貼付!'
].join('</br>');
const msg2 = [
  '【明細リスト - 監査員の注意点】',
  '・担当者印の有無を確認!',
  '・商品コードのエラーの有無を確認!',
  '・明細リストの監査行にレ点チェック!',
  '・監査後、監査印を忘れずに押印!'
].join('</br>');

// モデルのURL
const URL = "Teachable MachineでエクスポートされたモデルのURLを指定";

// モデルをロードして初期化
async function preload() {
  const modelURL = URL + "model.json";
  const metadataURL = URL + "metadata.json";
  model = await tmImage.load(modelURL, metadataURL);
  maxPredictions = model.getTotalClasses();
}

// デバイスがモバイルかどうかを判定
function isMobile() {
  const userAgent = navigator.userAgent || navigator.vendor || window.opera;
  return /android|iPad|iPhone|iPod/i.test(userAgent); // モバイルデバイスならtrueを返す
}

// ウェブカメラのセットアップと再生
function setup() {
  createCanvas(320, 260);

  // デバイスによってカメラの設定を変更
  let videoConstraints = {};
  if (isMobile()) {
    // モバイルデバイスの場合、リアカメラ(環境カメラ)を使用
    videoConstraints = {
      video: {
        facingMode: { exact: "environment" } // リアカメラを指定
      }
    };
  } else {
    // パソコンの場合、Webカメラ(インカメラ)を使用
    videoConstraints = {
      video: true // デフォルトのカメラ設定(Webカメラ)
    };
  }

  // カメラのキャプチャを作成
  webcam = createCapture(videoConstraints);
  webcam.size(320, 240);
  webcam.hide();

  // ラベルを表示するためのコンテナ
  labelContainer = createDiv('');
  labelContainer.style("background-color:#ffff00; font-weight:bold; width:320px;");
  labelContainer.hide(); // 初期状態では非表示
}

// フレームごとに描画し、3秒ごとに予測を行う
function draw() {
  background(220);
  image(webcam, 0, 0); // ウェブカメラ映像をキャンバスに描画

  // 3秒(3000ms)ごとに予測を実行
  if (millis() - lastPredictionTime >= 3000) {
    predict(); // 予測を実行
    lastPredictionTime = millis(); // 最後の予測時間を更新
  }
}

// 予測を行い、確率が90%以上の場合のみ「確認票」か「明細リスト」で表示
async function predict() {
  const prediction = await model.predict(webcam.elt); // カメラ映像に対して予測を実行

  // 予測確率の高い結果を取得
  let highestPrediction = prediction[0];
  for (let i = 1; i < maxPredictions; i++) {
    if (prediction[i].probability > highestPrediction.probability) {
      highestPrediction = prediction[i];
    }
  }

  // 確率が90%以上の場合にのみ結果を表示
  if (highestPrediction.probability >= 0.9) {
    if (highestPrediction.className === "確認票") {
      labelContainer.html(msg1);
    } else if (highestPrediction.className === "明細リスト") {
      labelContainer.html(msg2);
    }
    labelContainer.show(); // 結果を表示
  } else {
    labelContainer.hide(); // 確率が90%未満の場合は非表示
  }
}

簡単にスマホアプリっぽいものができた!

スマホを使用することが前提だったので、インカメラとリアカメラの切り替えの仕方を ChatGPT に教わりながら実装していきました。
また注意点を表示する時間も、3秒ごとに判定を行うことで、画面がチカチカしないようにしました。
今回は2種類だけの画像認識でしたが、種類を増やすことで、もっと充実したマニュアルがつくれそうです。
とにかく簡単なサンプルだけど、できた───! 兄さん───に感謝!!

ではでは、今日はこのへんで!

2024/09/29 下記を追記しました。

  • 画面に表示される注意点がチカチカして、落ち着かない失敗例の動画を追加。
  • 上記の動画の前後に説明文を若干追加。
5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?