皆さん、こんにちは。Naoki-su と申します。
小売業に勤め、デジタルの勉強中です。
今回は TeachableMachine (ML) を使ってメニュー提案ツールを作成します。
今日の晩ご飯は何にしよう…
私の今日の晩ご飯は、さつまいもご飯でした。
皆さん、さつまいもご飯好きですか?
以前は何の興味もありませんでしたが、食べてみてその美味しさに驚きました。
ナメてましたね。
さつまいもには「十三里」という別名があります。まあ、言葉遊びです。
江戸の焼き芋屋さんが「栗(九里)より(四里)うまい十三里」と謳って販売したのが由来と言われているそうです。
納得の美味しさです。栗ご飯の手間暇や値段を考えると相当なコスパですね。
私自身も料理をするので、お気に入りのレシピがいくつかあります。
皆さんも今日の晩ご飯でお悩みではないですか?
そんな時に従業員イチオシの美味しい料理レシピを、お客様におすすめのメニューとして簡単に提案出来る様にならないかと、TeachableMachine を使用したツールを作成しました。
私はもちろん、他の従業員が使っても良いですし、お客様が直に使用しても良いかと思います。
完成品
使用ツール
・ TeachableMachine
・ codepen
・ ChatGPT
・ GoogleSpreadSheet
製作過程
①TeachableMachineで画像を機械学習
TeachableMachineを開いて、「使ってみる」をクリック。
新しいプロジェクトの「画像プロジェクト」をクリック。
新しいイメージプロジェクトの「標準の画像モデル」をクリック。
Classに項目を入力していきます。Classが足りなければ「クラスを追加」をクリックして必要な量を足します。
今回は
・さつまいも
・ごぼう
・たまねぎ
・じゃがいも
・対象無し
の5つです。
各項目の「ウェブカメラ」をクリックするとカメラが起動します。
「長押しして録画」を押して対象のサンプル写真を連続撮影します。
すべてのサンプル収集が完了したら 真ん中のトレーニングの「モデルをトレーニングする」をクリックします。
しばらく時間がかかる場合があります。
トレーニングが終わると右のプレビューに完成品が映し出されます。 何も写ってなければ「対象無し」、さつまいもを写すと「さつまいも」のパーセンテージが ちゃんと上がる様になりました。
プレビューの「モデルをエクスポートする」をクリックし、 出てきたウィンドウの「モデルをアップロード」を選択します。 完了するとリンクが出来るのでコピーしておきます。
画面左のメニューから「ドライブにプロジェクトを保存」もしておきましょう。
②GoogleSpreadSheetに必要項目を入力
GoogleSpreadSheetを開いて、野菜名・おすすめメニュー名・レシピURLを入力します。
おすすめメニュー名にはリンクを設定し、クリックすると該当のサイトに移動できるようにします。
TeachableMachineの時と同様に対象無しを作成し、
該当時には「野菜を映してください。」と表示されるようにします。
③ChatGPT でコードを作成
私が最初に入力したプロンプトが以下です。
ChatGPT作成のソースコードはこちら
Click!!(ソースコードが開きます)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>おすすめメニュー表示</title>
<style>
body {
background-color: #e0f7df; /* 淡い緑色の背景 */
font-family: Arial, sans-serif;
text-align: center;
margin: 0;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
h1 {
color: red;
background-color: white; /* 白い背景 */
border: 2px solid white;
display: inline-block;
padding: 10px;
margin-bottom: 20px;
font-size: 24px; /* スマホに合わせてサイズを調整 */
}
#menu-name {
color: yellow;
background-color: #8b0000;
padding: 10px;
border: 2px solid black;
display: inline-block;
text-decoration: none;
font-size: 16px; /* メニューのリンク文字サイズ */
max-width: 90%; /* 画面幅に合わせてリンクサイズ調整 */
}
/* カメラ映像の反転設定を制御 */
.mirror {
transform: scaleX(-1); /* PC用の反転設定 */
}
</style>
<script src="https://unpkg.com/ml5@latest/dist/ml5.min.js"></script>
</head>
<body>
<h1>おすすめメニュー提案</h1>
<video id="webcam" autoplay playsinline width="430" height="320"></video>
<p><a id="menu-name" href="#" target="_blank"></a></p>
<script>
const modelURL = 'https://teachablemachine.withgoogle.com/models/lXk8mCHOJ/'; // Model URL from Teachable Machine
let classifier;
let video;
let modelLoaded = false;
async function init() {
classifier = await ml5.imageClassifier(modelURL + 'model.json', () => {
document.getElementById('menu-name').innerText = 'Model loaded';
modelLoaded = true;
});
video = document.getElementById('webcam');
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: 'environment' } // 背面カメラを指定
});
video.srcObject = stream;
// スマホまたはPCを判定し、反転を適用
if (window.innerWidth < 768) {
// スマートフォンなどの場合は反転しない
video.classList.remove('mirror');
} else {
// PCの場合は反転
video.classList.add('mirror');
}
} catch (err) {
console.error('Webcam access error:', err);
}
classifyVideo();
}
async function classifyVideo() {
if (modelLoaded) {
const results = await classifier.classify(video);
const recognizedItem = results[0].label;
fetchMenu(recognizedItem);
}
setTimeout(classifyVideo, 500); // 500msごとに認識
}
function fetchMenu(vegetable) {
const sheetId = "1astJRs2hnAvAKB0_3f1Kf_dOUbejoYPzCw22iA-X4KY"; // Replace with your actual Sheet ID
const sheetName = "シート1";
const url = `https://docs.google.com/spreadsheets/d/${sheetId}/gviz/tq?tqx=out:json&sheet=${sheetName}`;
fetch(url)
.then(response => response.text())
.then(data => {
const json = JSON.parse(data.substr(47).slice(0, -2));
const rows = json.table.rows;
let menuFound = false;
rows.forEach(row => {
if (row.c[0].v === vegetable) {
const menuName = row.c[1].v;
const recipeUrl = row.c[3] ? row.c[3].v : "#";
document.getElementById("menu-name").textContent = menuName;
if (vegetable === "対象無し") {
document.getElementById("menu-name").href = "#"; // No link for "対象無し"
} else {
document.getElementById("menu-name").href = recipeUrl;
}
menuFound = true;
}
});
if (!menuFound) {
document.getElementById("menu-name").textContent = "該当するメニューが見つかりません";
document.getElementById("menu-name").href = "#";
}
})
.catch(error => console.error("Error:", error));
}
init();
</script>
</body>
</html>
④CodePenに作成したコードを貼付
CodePenを開き、ChatGPTで作成したコードを左側のHTML部分に貼り付けます。
野菜が映されていない為、ちゃんと「野菜を映してください」が表示されています。
スマホでの操作
スマホでCodePenを開いてログインし、作成したコードを開きます。
カメラへのアクセスを求められるので許可します。
画面上のメニューをタップし、Debug mode
をタップします。
全画面表示されるようになりました。
しっかりと背面カメラで起動し、各々の野菜もちゃんと認識し、リンクも出来ています。
さいごに
TeachableMachineを使用することにより、画像認識を容易に使用することが出来ました。
ポーズ認識など他の機能も活用すれば、売場案内やレジ待ちの監視ツールなど幅広い活用が考えられます。
今回はよりアプリらしく仕上げる事が出来ましたが、料理画像を表示する所は改善点かと思います。対応出来る野菜の品目増加や複数の選べるおすすめレシピなど、他にもまだ改善の余地はあります。今後もアップデートを続けて行きたいと思います。
最後まで読んで頂きありがとうございます!