またIDを間違えた…を防ぐ！　顔画像でIDを教えてくれるWebアプリ

　こんばんは！小売業で採用担当をしているミハタです
自社では通年で採用活動を行なっているのですが、3~5月と9~10月は新しく入社する方が増える傾向にあります
ちょうどこの時期、各事業所の人事担当者は入社対応で忙しい日々を送っているはず…

　そんな中、必須かつ超重要な業務があります
 それは**マイナンバーの登録**です
そこで今回は、マイナンバーの登録に関わる課題を解決する**Webアプリ**を作ってみました！

## マイナンバーの登録に関わる課題って？
　正しく税金を納めることを目的として、会社は従業員にマイナンバーを報告してもらっています
報告したことあるな～、と思いあたる方もいますよね
　マイナンバーは超重要書類であるため、自社では一つの事業所のうち、セキュリティ基準を満たしたパソコン1台でしかマイナンバー登録システムにログイン出来ないようしています

　マイナンバー登録システムにログインできる人事担当者は、各事業所に複数人います
複数人が同じパソコンを使ってシステムにログインするため、一人一人に電子証明書ID(以下証明書ID)が発行され、自分の証明書IDを選択してログインします
しかし証明書IDを選択する際に、**誤って別の人の証明書IDを選択してしまい、エラーになることが多い**のです

　誤った証明書IDを選択してもログインエラーになり、セキュリティ上は問題ありません
しかし証明書IDが誤っているとは思わず、何度もログインを試そうとうすると不正アクセスとみなされ強制的にログインができないようシステムからロックされてしまいます
そうなると各事業所の人事担当はわたしたち本部の人事にロックを解除するよう**依頼する手間がかかってしまうのです…**
しかも、本部の人事がすぐに対応できない場合は何日か待ってもらう必要があります
すぐに登録できない場合はいったん本人に返却しているため、**後日また持ってきてもらうと二度手間になってしまいます**
そこで、確実に自分の証明書IDを選択するような仕組みを考えたいと思いました！


## Webアプリの概要
　**Teachable Machine**を使って**顔認証**をすることで、マイナンバーを登録するためのシステムにログインする際に必要な証明書IDを教えてくれる**Webアプリ**をカンタンに作成する方法を紹介します
 
 :::note info
**Teachable Machine**とは？
 Googleが提供する機械学習のツールで、誰でも簡単に画像認識や音声認識のモデルを作成できます
:::

実際に使った顔認証アプリで判定している様子はこちら↓

https://x.com/ccchisssa/status/1840296921497567613



## 作成手順
### ステップ1. Teachable Machineで顔認証モデルを作成
1\. [Teachable Machine](https://teachablemachine.withgoogle.com/)のWebサイトにアクセスし、画像モデルを選択し、次の画面で「標準の画像モデル」を選択
　
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/668433fa-f687-614a-e61e-aed96fb08f4e.png)


2\.画像のサンプルをアップロードして、トレーニングを行います

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/cb10faee-6c7e-9db1-005c-6074042665f8.png)


3\.モデルをエクスポートして、URLを取得します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/55bd21a5-082c-75ea-d159-aa20a5d74d51.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/383bf765-b715-7254-dbf3-36c085b52401.png)



### ステップ2. CodePenでWebアプリを作成

1\. [CodePen](https://codepen.io/pen/)にアクセスし、右上の「Log in」からGoogleアカウントなどでログイン後、左上の鉛筆マークから名前を変更してください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/59687507-14d4-7475-f25e-720147b175e9.png)



2\.HTMLコードを入力します
　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/c74d4e40-5e24-63a8-f180-e767cc0d5278.png)

<details><summary>実際に入力したプロンプトはこちら</summary>
<pre><code>

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Teachable Machineで画像認証</title>
</head>
<body>
    <h1>Teachable Machine 画像認証アプリ</h1>
    <button type="button" onclick="init()">画像認証を開始</button>

    <div id="webcam-container">Webカメラがここに表示されます</div>
    <div id="label-container"></div>

    <!-- TensorFlow.js と Teachable Machineのスクリプト -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@teachablemachine/image@latest/dist/teachablemachine-image.min.js"></script>
</body>
</html>

</code></pre>
</details>


:::note info
Codepenに記載したコードは**Chat GPT**に書いてもらいました！
知識がなくてもプロンプトを真似してもらえば作成できます
一部、うまく作成できなかったプロンプトもそのまま＆修正依頼をそのまま記載しているので、合わせて見てみてください
:::



3\.CSSコードを入力します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/62ce116d-ed6e-df0b-1994-8a25c15cca30.png)

<details><summary>実際に入力したプロンプトはこちら</summary>
<pre><code>
body {
    font-family: Arial, sans-serif;
    text-align: center;
    background-color: #f0f0f5;
}

h1 {
    color: #333;
}

#webcam-container {
    margin: 20px auto;
    border: 2px solid #ddd;
    width: 200px;
    height: 200px;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #fff;
}

#label-container {
    margin-top: 20px;
}

button {
    padding: 10px 20px;
    font-size: 16px;
    color: #fff;
    background-color: #28a745;
    border: none;
    border-radius: 5px;
    cursor: pointer;
}

button:hover {
    background-color: #218838;
}

.label {
    font-size: 18px;
    margin: 5px 0;
}

</code></pre>
</details>

4\.JSコードを入力します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/77c8cff0-f6c7-270f-e88c-4990a2824593.png)


<details><summary>実際に入力したプロンプトはこちら</summary>
<pre><code>
// Teachable MachineのモデルURL
const URL = "Teachable Machineで作成しコピーしたURLを入力してください";

let model, webcam, labelContainer, maxPredictions;

// モデルとWebカメラのセットアップ
async function init() {
    const modelURL = URL + "model.json";
    const metadataURL = URL + "metadata.json";

    // モデルとメタデータを読み込む
    model = await tmImage.load(modelURL, metadataURL);
    maxPredictions = model.getTotalClasses();

    // Webカメラの設定
    const flip = true; // Webカメラの映像を反転するかどうか
    webcam = new tmImage.Webcam(200, 200, flip); // 幅, 高さ, 反転
    await webcam.setup(); // Webカメラのアクセスをリクエスト
    await webcam.play();
    window.requestAnimationFrame(loop);

    // HTMLにWebカメラを追加
    document.getElementById("webcam-container").appendChild(webcam.canvas);
    labelContainer = document.getElementById("label-container");
    for (let i = 0; i < maxPredictions; i++) {
        const labelDiv = document.createElement("div");
        labelDiv.classList.add('label');
        labelContainer.appendChild(labelDiv);
    }
}

// Webカメラの映像を更新して、モデルで予測を実行
async function loop() {
    webcam.update();
    await predict();
    window.requestAnimationFrame(loop);
}

// 予測を実行して、結果を表示
async function predict() {
    const prediction = await model.predict(webcam.canvas);
    for (let i = 0; i < maxPredictions; i++) {
        const classPrediction = prediction[i].className + ": " + (prediction[i].probability * 100).toFixed(2) + "%";
        labelContainer.childNodes[i].innerHTML = classPrediction;
    }
}

</code></pre>
</details


ここまでCodepenを順調に進めていましたが、いざカWebカメラを使おうとすると
**…ん？カメラがうまく起動しないぞ…？**
    よーく見るとHTMLタグの右下に赤丸の「！」マークがある。
クリックしてみると次の文言が↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/76a4980b-76c0-917c-db3f-6ebb8de1ccd3.png)

Chat GPT聞いてみたら、余分なタグを入れていたようで解決策を教えてくれました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/be40633a-14cb-7410-cc7e-36650af73095.png)

ということで、修正されたコードをHTMLタブに入力しなおします
ついでに、コードの中身も修正します

<details><summary>修正したHTMLのプロンプトはこちら</summary>
<pre><code>
<h1>Teachable Machine 画像認証アプリ</h1>
<button type="button" onclick="init()">画像認証を開始</button>

<div id="webcam-container">Webカメラがここに表示されます</div>
<div id="label-container"></div>

<!-- TensorFlow.js と Teachable Machineのスクリプト -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@teachablemachine/image@latest/dist/teachablemachine-image.min.js"></script>

</code></pre>
</details



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/36e8158b-0d6c-2c9b-8191-082ca3859091.png)


WEBカメラが表示され、「画面認証を開始」ボタンを押すとカメラが起動し
写した顔から自分の証明書IDを判断して教えてくれました！


## 職場の方に試してもらった！
　今回、作成にあたり職場のSさんとYさんに協力してもらいました
 Sさん・Yさん・わたしの3人ともそれぞれ証明書IDが発行されています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/15242bb2-07eb-6608-0461-5e75f6e475ff.png)

　たしかに、「あなたの証明書のIDは○○です」と断言してくれる方がわかりやすく、より確実に間違いを防止できます
そこで、ChatGPTの力を借りて、JSタブのコードを書き換えることにしました

<details><summary>修正したJSのプロンプトはこちら</summary>
<pre><code>

// Teachable MachineのモデルURL
const URL = "Teachable Machineで作成しコピーしたURLを入力してください";

let model, webcam, labelContainer, maxPredictions;

// モデルとWebカメラのセットアップ
async function init() {
    const modelURL = URL + "model.json";
    const metadataURL = URL + "metadata.json";

    // モデルとメタデータを読み込む
    model = await tmImage.load(modelURL, metadataURL);
    maxPredictions = model.getTotalClasses();

    // Webカメラの設定
    const flip = true; // Webカメラの映像を反転するかどうか
    webcam = new tmImage.Webcam(200, 200, flip); // 幅, 高さ, 反転
    await webcam.setup(); // Webカメラのアクセスをリクエスト
    await webcam.play();
    window.requestAnimationFrame(loop);

    // HTMLにWebカメラを追加
    document.getElementById("webcam-container").appendChild(webcam.canvas);
    labelContainer = document.getElementById("label-container");
}

// Webカメラの映像を更新して、モデルで予測を実行
async function loop() {
    webcam.update();
    await predict();
    window.requestAnimationFrame(loop);
}

// 予測を実行して、最も高い確率のクラスを表示
async function predict() {
    const prediction = await model.predict(webcam.canvas);
    
    // 最も確率の高いクラスを見つける
    let highestPrediction = prediction[0];
    for (let i = 1; i < prediction.length; i++) {
        if (prediction[i].probability > highestPrediction.probability) {
            highestPrediction = prediction[i];
        }
    }

    // 「IDは○○です」と表示
    labelContainer.innerHTML = `IDは ${highestPrediction.className} です`;
}

</code></pre>
</details


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842443/04b2b8ae-de26-c8d8-ab5a-255a99bd4f7c.png)

　JSタブのコードを書き換えが成功し、より理想のUIに近づけることができました！
 Yさんから、「自分の証明書IDが瞬時にわかるから、間違いが減るね(⌒∇⌒)」とほめてもらえました◎

　実際に使用してもらった感想をもらえると改善点が見つかって、よりよいプロトタイプを作成することができるのでいいスパイラルを回せますね★
SさんとYさん、ご協力ありがとうございました！


## まとめ

　Teachable MachineとCodePenを使って、簡単に顔認証Webアプリを作成できました
今後はこのシステムを上手く活用してもらうための方法を考えたいです
例えば、Microsoft Edgeであれば**Redirector拡張機能**をインストールすることで、マイナンバー登録システムのログインページをクリックしたらこのWebアプリが起動するようにすれば、確実に顔認証をして正しい証明書IDを教えてくれるはずです

　また、Teachable Machineを応用すれば、さらにいろいろなツールを作成できそうです
例えば、自社では安心・安全を担保するために食品コーナーで勤務する従業員にたいして出勤時に体温など体調チェックを行っています
Webカメラで顔の表面温度を測定しながら顔認証をすることで、一人一人の体温が何℃なのか自動で登録してくれたら便利ですよね！ 

　Teachable Machineのような機械学習のツールは大量のデータを登録することでさまざまなデータが結びつき、認識ができるようになります
この特徴を活用し、「たくさん教えれば判断ができるようになる」という身近な課題の解決に役立てたいと思います！


今回もお付き合いありがとうございました！　お疲れ様でした♪

### 参考記事はこちら


https://qiita.com/M8nEl0s0v8/items/738d175390d4630bfb06


https://qiita.com/yui214391/items/520281d2603a955d37e7