機械学習で商品認証+移動通知/管理

「A店からB店」への商品移動を伴う会社業務で紙の印刷が毎回不可欠になっている部分を
想像して機械学習で作ってみました。<br>

<B>商品移動をする時の業務流れ：</B>
ハンディーで商品を一つ一つ認証させ⇒データをPCに読み込ませ⇒<b>商品詳細を紙で印刷</b>⇒紙を移動する商品と配送。<br>

商品詳細を印刷する事がマストになっているため、
<b>紙の減少</b>を実現するために機械学習を使って改善出来ればと思い制作に至りました。

<B>★機械学習で作りたい流れ：★
機械学習で商品を認証
↓
認証商品の品番・数量をLINE Botに自動でお知らせ
+
Spreadsheetで品番・数量を自動的に管理</B>

この流れによって紙の印刷が不要になり、
商品を移動する際の業務の部分で印刷する流れが無くなるので業務負担が軽減され、紙の使用も減少。


#1.過程の流れ(動画)
![修正版.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/ac7ee825-6f5f-4555-424a-3f6261899616.gif)

機械学習のモデルは今回[Teachable Machine](https://teachablemachine.withgoogle.com/)を使用しました。
ちなみに、[YouTube](https://youtu.be/sFLllVT5U04)でも過程の流れを限定公開しています。

#2.活用
- [Teachable Machine](https://teachablemachine.withgoogle.com/)<br>
- [Codepen](https://codepen.io/)<br>
- [Node-Red](https://nodered.org)<br>
- [Line Bot](https://developers.line.biz/ja/services/bot-designer/)<br>
- [Spreadsheet](https://www.google.com/intl/ja_jp/sheets/about/)<br>

#3.作業の流れ
##①Teachable Machine
![teacheble matchine.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/39b3d37c-f574-25c5-db6a-c063ecf82cb9.png)
[Teachable Machine](https://teachablemachine.withgoogle.com/)では2つの方法で画像サンプルを作成する事が出来ます。
①ウェブアップロードの場合は100枚程度の画像を取ると認証がスムーズにいきます。
②今回はオンラインショップの商品画像を使用しPCからアップロード形式で作成しました。
　5-6枚の画像ですが、正常に認証する事が出来ました。


##②Codepen
[Codepen](https://codepen.io/)では実際に商品認証の部分を作成していきました。
作成したCodepenのURLを使用して試してみて下さい。

<B>流れ：
下記のURLより商品認証ページへ入る
↓
認証開始ボタンを押す
↓
consoleでモデルの読み取り完了を確認
↓
商品画像をカメラにかざしながら読み取りボタンを押す
※読み取りボタンを押す数分だけ数量として「〇点」と認証されます。
↓
認証終了後、完了ボタンを押す</B>

###■【認証商品画像】
- 画像１⇒品番：14-1082-021
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/98d8e66b-6a4e-1ca3-3397-1c723bab59af.jpeg)
- 画像2⇒品番：14-1082-022
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/5ba3540a-8c63-7f2c-6bbe-85f866d84872.jpeg)

###■【URL】
上記の画像を使用して下記のURLより画像認証を試してみてください！

https://codepen.io/yudiramaruyama/pen/abWaNjE

###■【使用コード】
- <b>HTML</b>

```html
<h1>商品認証</h1>
<button onclick="start()">認証開始</button><br>
<video id="webcam" width="320" height="240" muted autoplay playsinline></video>
   
<table>
<tr>
<td>品番：<p id="result"></p></td>
</tr>
</table>

<button onclick="read()">読み取り</button><br><br>
<button onclick="send()">完了</button><br>
```

- <b>CSS</b>

```css
#webcam {
  transform: scaleX(-1);
}
```


- <b>JS</b>

```js
// 作成したモデルのURL
const imageModelURL = 'https://teachablemachine.withgoogle.com/models/1-U8E3Ggg/';
let classifier;
let data = {};
// メインの関数（ここでは定義しているだけでボタンクリックされたら実行）
async function start() {
  // カメラからの映像ストリーム取得
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: false,
    video: true,
  });
  
  // 「id="webcam"」となっているパーツ（videoタグ）を取得
  const video = document.getElementById('webcam');
  
  // videoにカメラ映像ストリームをセット
  video.srcObject = stream;
  
  // Googleのサーバーにアップロードした自作モデルを読み込みにいきます
  classifier = ml5.imageClassifier(imageModelURL + 'model.json', video, () => {
    // 読み込みが完了次第ここが実行されます
    console.log('モデルの読み込みが完了しました');
  });

// 繰り返し処理
  function read() {
    // 推論を実行し、エラーがあればerrに、結果をresultsに格納して、
    // 推論が完了次第 { } の中身を実行します
    classifier.classify(async (err, results) => {
      // 結果のresultsは配列ですが、先頭に中身があれば以下の処理を実行します
      if (results[0]) {
     if (!data[ results[0].label ]) data[ results[0].label ] = 0;
data[ results[0].label ] += 1;  
        console.log(data); 
        // コンソール表示
        
      }
      
      document.getElementById("result").textContent = results[0].label;
      // 推論終了1秒後に自分の関数を実行（ループになる）
    });
async function send(){
  await axios.post('https://nodered-yudiramaruyama.herokuapp.com/receiver', data);
data={};
}
```





##③Node-Red
###■【全体のフロー構成】
![Inkednode-red全体フロー_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/b22c4762-68dc-b610-bcd5-8ee879fabe86.jpeg)
`http in`ノードでCodepenから認証した情報を`receiver`(受取）、
各WEBアプリに送っている流れになります。

####<b>基本ノード</b><br>
最初に基本として3つのノードを組み合わせ作成。

①`http in`ノード
　詳細：`メゾット:POST`,`URL:/receiver`

②`httｐ response`ノード
　※詳細はそのまま

③`msg.payload`ノード
　※詳細はそのまま

####<b>LINE Bot<b></br>
LINE Botに繋げるために2つのノードを組み合わせる。
①`function`ノード
　コード：　

```js
  let slip = "伝票番号"
 for (let i = 0; i < 3; i++) {
   console.log("現在" + (i+1) + "回目の処理です。");
 }

// 品番＋数量詳細
 const items = Object.keys(msg.payload);
let message = '商品移動のお知らせ!\n'; // 返信メッセージ
items.forEach(item => {
 message += '品番：'+ item + '\n' + '数量：' + msg.payload[item] + "点\n";
});

message=message.replace(/\n$/,'');

msg.payload = slip;
msg.payload = message;
return msg;
```


②`Bloadcast Message`ノード
　Node-REDのパレットにまだない場合はパレット管理より追加する事が出来ます。
　詳細：`Secret`,`Acces Taken`のIDを入力して完了。
　※`Secret`,`Acces Taken`には[LINE Developers](https://developers.line.biz/ja/)でLINE Botを作った時にもらえるID入力。

####<b>Spreadsheet<b></br>
Spreadsheetに繋げるために2つのノードを組み合わせる。
①`function`ノード
　コード：

```js
// 品番＋数量詳細
const items = Object.keys(msg.payload);
let message = ''; // 返信メッセージ
items.forEach(item => {
  message += '品番：'+ item + '\n' + '数量：' + msg.payload[item] + "点\n";
});

message=message.replace(/\n$/,'');
msg.payload = {"A":message };
return msg;
```

②`Stein addrows`ノード
　Node-REDのパレットにまだない場合はパレット管理より追加する事が出来ます。
　詳細：`API name`,`API URL`,`sheet name`を入力して完了。
　※`API name`,`API URL`は[Stein](https://dashboard.steinhq.com/login)で作成しURLをゲットする出来ます。

####最後には
`http in`ノードから基本ノードとLINE Botをつなけるための`function`ノートと
Spreadsheetを繋げるための`function`ノードのワイヤーを繋げて、
デプロイボタン押すと<b>完了</b>です。

#4.まとめ
以上が機械学習で商品認証+移動通知/管理の制作流れになります。
会社内で紙の削減をするための案でした。

今回はWEBアプリを繋げる際に`function`ノードを使用する必要がありました。
`function`ノードなしでもWEBアプリと繋げる方法ありますか？
あれば、ぜひ教えて頂きたいです。

[teratail](https://teratail.com/)でも同じ質問をしています。

https://teratail.com/questions/353075