AI機械学習で、マスクチェッカ―(不織布マスク着用・布マスク・マスクなし・マスクずらしを判定し、LINE Botへ注意喚起)

##【新型コロナウィルス感染防止対策】
新型コロナウィルス感染拡大に伴い、マスク着用が日常化されましたね。
私の会社では、不織布マスクの着用が義務付けられており、防疫プロトコルを徹底しております。
しかし、気温上昇に伴い、ある問題が発生、、、（；^ω^）

【ある問題とは、、、、、】
不織布マスク着用は、徹底されてきたのですが、気温上昇に伴い、マスク外しやマスクをずらした会話が散見されるようになりました。この身近な課題に対して、AI機械学習×LINE Botを活用し、解決しようと考えました。

##【今回制作した仕組み】
マスクチェッカー
不織布マスク着用の場合=ＯＫです！
布マスク、マスクなし、マスクずらし=注意喚起メール配信(マスクをつけて下さい！)

##【仕組みの動画】
■CodePen
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">マスクチェッカ―！<br>連携させるのが難しい！汗<br>何とかできたが、まだまだ、、（；^ω^）<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://twitter.com/hashtag/Java?src=hash&amp;ref_src=twsrc%5Etfw">#Java</a> <a href="https://twitter.com/hashtag/nodered?src=hash&amp;ref_src=twsrc%5Etfw">#nodered</a> <a href="https://twitter.com/hashtag/lINEBot?src=hash&amp;ref_src=twsrc%5Etfw">#lINEBot</a> <a href="https://t.co/CTLz8P2BJF">pic.twitter.com/CTLz8P2BJF</a></p>&mdash; YE0905 (@EgashiraYosuke) <a href="https://twitter.com/EgashiraYosuke/status/1424708162624516096?ref_src=twsrc%5Etfw">August 9, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

■LINE Botメール配信
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">LINE Botと連携<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://t.co/h2hDdoTrjp">pic.twitter.com/h2hDdoTrjp</a></p>&mdash; YE0905 (@EgashiraYosuke) <a href="https://twitter.com/EgashiraYosuke/status/1424709466159665159?ref_src=twsrc%5Etfw">August 9, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

##【開発環境の準備】
・Teachable Machine
・CodePen
・Node-Red
・Heroku
・LINE Bot

##【システム構成】
Teachable Machineで画像を取り込み
■不織布マスク着用時
■マスク外し
■マスクずらし
■布マスク
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/581826b0-1bb7-297e-ddde-bb5fdfe83d43.png)

##【お試しURL】
https://codepen.io/egashirayosuke/pen/gOWQywP

##【CodePenの構成】
[image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/53dd8f68-3c36-8283-033f-5ad4c679ef7e.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/bae4c153-b813-0fd9-e0fe-9d5c8229138e.png)



■HTML

```
<div class="wrapper">
  <div class="title">
    <h1>マスクチェッカー</h1>
  </div>
  <div class="camera">
    <button onclick="start()" class="button start">開始</button>
    <br>
    <video id="webcam" width="320px" height="240px" muted autoplay playsinline></video>
  </div>
  <div class="result"><p id="result"></p></div>
</div>
```

■CSS

```
#webcam {
  transform: scaleX(-1);}
.wrapper {
  display: flex;
  justify-content:center;
  align-items: center;
  flex-direction: column;
  width: 100vw;
  heigth: 100vh;}
.camera {
  text-align: center;
  width: 100vw;
  heigth: 100vh;}
.button {
  width: 100px;
  height: 50px;
  margin-bottom: 30px;}
.start {
  margin-rigth: 30px;}
```

■JS

```
//作成したモデルのURL
const imageModelURL = 'teachablemachineURL';
// メインの関数（ここでは定義しているだけでボタンクリックされたら実行）
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 loop() {
    // 推論を実行し、エラーがあればerrに、結果をresultsに格納して、
    // 推論が完了次第 { } の中身を実行します
    classifier.classify(async (err, results) => {
    // 結果のresultsは配列ですが、先頭に中身があれば以下の処理を実行します
    if (results[0]) {
      // 自分の顔の画像を取得
      const myFace = results[0].label;
      // 判定結果を入れる変数を用意
      let judge = '';
      const result = document.getElementById("result");
      // 判定
      if (myFace == 'マスクあり') {
      // マスクあり
        result.style.color = 'green';
        judge = 'OKです！';
      } else {
        // マスクなし
        result.style.color = 'red';
        judge = 'マスクをつけて下さい！';
      }
      // HTML表示に反映
      result.textContent = judge;
      axios.post('https://nodered-egashira.herokuapp.com/receiver', {judge: judge});
    }
    // 推論終了0.5秒後に自分の関数を実行(ループになる)
    setTimeout(loop, 500);
　　});
  }
  // 最初の繰り返し処理を実行
  loop();
}
```

###【Node-RED構成】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/b779da93-014f-37c4-d26b-851c17d62abe.png)

###【各ノード詳細】
「http inノード」:ラインサーバーから送信されたメッセージ取得
メソッド:```POST```
URL:```/receiver```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/2d171870-884d-20ec-fb3b-bb2d697e2228.png)

「functionノード」:ノード(左側):受け取ったメッセージ格納

```
const message = msg.payload.judge;
msg.url="https://api.line.me/v2/bot/message/push";
msg.method="POST";
var ACCESS_TOKEN = "アクセストークン記載";
msg.headers={
   "Authorization":`Bearer ${ACCESS_TOKEN}`,
   "Content-Type":"application/json"
};
msg.payload={ 
	"to":"ユーザーID記載", //誰に送るか指定
	"messages":[　//メッセージ内容を指定
		{
           "type":"text",
           "text": message}]};
return msg;
```

「http requestノード」:受けっとったメッセージをLINEに通知を配信
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/e1783d5d-aff2-794f-ea91-6a54a1c1a4f9.png)


「debugノード」:サーバー稼働を確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/05024e5d-082f-b147-98e4-1a097730146b.png)

###【まとめ】
今回AI機械学習＆Node-RED＆LINE Botを連携させ、
マスク着用の判断を実際に制作してみました。
マスク多種類をTeachable Machineに登録させ、判定する事が出来なかった点が課題です。
今後は、アルコール消毒状況なども反映させる仕組みや売場管理を把握できるシステムなどを制作していきたいと思っております。

###【今後作成していきたい５つの業務課題】
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">俺がやる！成長させる！<br>ニューリテール企業へ！<br>日々の業務課題５つ深掘りしてみました！<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://twitter.com/hashtag/%E6%A5%AD%E5%8B%99%E8%AA%B2%E9%A1%8C?src=hash&amp;ref_src=twsrc%5Etfw">#業務課題</a><a href="https://twitter.com/EgashiraYosuke?ref_src=twsrc%5Etfw">@EgashiraYosuke</a> <a href="https://twitter.com/hashtag/note?src=hash&amp;ref_src=twsrc%5Etfw">#note</a> <a href="https://twitter.com/hashtag/%E7%A7%81%E3%82%89%E3%81%97%E3%81%84%E3%81%AF%E3%81%9F%E3%82%89%E3%81%8D%E6%96%B9?src=hash&amp;ref_src=twsrc%5Etfw">#私らしいはたらき方</a> <a href="https://t.co/Aweu9dB169">https://t.co/Aweu9dB169</a></p>&mdash; YE0905 (@EgashiraYosuke) <a href="https://twitter.com/EgashiraYosuke/status/1424586585085943811?ref_src=twsrc%5Etfw">August 9, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>