MENU

Soracom

Users

サンプルアルゴリズム「Image Classification(Face)」を使用した顔認識モデルの作成

はじめに

Image Classification (Face) は、S+ Camera Basic で取得した顔画像を元に学習した顔認識モデルを簡単に作成できるサンプルアルゴリズムです。作成したモデルを使用することで、S+ Camera Basic 上で顔認識を行うことができます。当ガイドでは Image Classification (Face) で作成した顔認識モデルを S+ Camera Basic にインストールして、顔認識の結果を SORACOM Lagoon 上のダッシュボードに表示させる設定手順を解説します。 SORACOM Mosaic を初めて利用する場合は、 Getting Started with SORACOM Mosaic をご確認ください。

事前準備: SORACOM Harvest Data の設定を有効にする

顔認識モデルの判定結果は SORACOM Harvest Data に送信されるので、利用している S+ Camera Basic に取り付けた SIM にて設定を有効にする必要があります。既に SORACOM Harvest Data が有効になっている場合はこの手順はスキップしてください。

  1. SORACOM ユーザーコンソール の[Menu]>[SIM 管理]とクリックして SIM 管理画面を開く。

  2. S+ Camera Basic に取り付けた SIM に割り当てたグループ名をクリックする。

    img

  3. [SORACOM Harvest Data 設定]をクリックする。

    img

  4. SORACOM Harvest Data の設定を ON にして [保存] をクリックする。

    img

ステップ 1: S+ Camera Basic を使って学習用の顔画像を収集する

S+ Camera Basic に Image Classification (Face) をインストールする

SORACOM Mosaic の コンソール にログインして、デバイス詳細画面の App(CameraApp0) タブから、Install new algorithm… ボタンをクリックすると以下のようにアルゴリズムを選択するダイアグラムが表示されます。Image Classification(Face) を選択肢、Install ボタンをクリックしてアルゴリズムをインストールしてください。

img

インストール後、以下のように、CURRENT ALGORITHMImage Classification(Face) と表示されていることを確認してください。

img

学習用の顔画像を収集する

S+ Camera Basic を学習させたい顔に向けると、顔画像が SORACOM Harvest Files に送信されます。

利用前に必ず契約約款をご確認ください。S+ Camera Basic での撮影時には個人情報及びプライバシーに配慮し、被撮影者の同意を得る等必要な措置をとってください。

撮影された顔画像は以下の手順で確認できます。

  • SORACOM の ユーザーコンソール にログインし、画面左上の [Menu] > [データ収集・蓄積・可視化] > [SORACOM Harvest Files] をクリック。

img

  • 以下のように /image_classification/{MOSAIC ID}/yyyy/mm/dd/ ディレクトリに webp 形式で顔画像が保存されています (顔画像は SORACOM_ENV_WAIT 秒毎に撮影されます)。

img

顔画像が SORACOM Harvest Files に送信されない場合
  • 当アルゴリズムでは顔を斜めから撮影している場合には顔が認識されません。当社での検証では、正面を向いた状態から上下左右に 30 〜 45 度以上の角度をつけると顔を認識しませんでした。なるべく正面で顔を捉えるよう画角を調整してください。
  • 日光などが強く当たった場合に認識精度が下がる事例が報告されております。適宜設置場所を調整してください。

次の値は、SORACOM Mosaic コンソール のデバイス詳細画面の App(CameraApp0) タブにあるアルゴリズム (Image Classification(Face)) の環境変数 SORACOM_ENV_FREE_PARAM から変更可能です。

引数名説明
UInvintegerデータの送信間隔 (この間のデータは破棄)。Default 60 秒
SIntintegerSORACOM Harvest Data/Files への送信間隔 (秒)。Default SORACOM_ENV_WAIT (60) 秒
UInvintegerSORACOM Harvest Data/Files へのデータの送信間隔 (この間のデータは破棄)。Default SORACOM_ENV_WAIT (秒)
SIntintegerこの期間は同一の顔と判定されたデータを破棄 (秒)。Default SORACOM_ENV_WAIT (秒)
SDatabooleantrue の場合、モデル作成用のデータを作成する。Default true

ステップ 2: Image Classification (Face) のコンソールを使って顔認識モデルを作成する

モデル作成に必要なデータの作成

モデルを作成するためには SORACOM Harvest Files の /face_detection_v1/detections にモデル作成用のデータを保存する必要があります。モデル作成用のデータは Image Classification(Face) をインストールした S+ カメラにおいて、顔認識ができない場合もしくは SData を true に設定している場合は、顔認識の結果に関わらず全ての顔についてモデル作成用のデータが作成されます。

新しいモデルを作成する

SORACOM Mosaic コンソール にログインして、画面右上の Support から Mosaic Classifier をクリックすると Image Classification (Face) のコンソールに遷移します。

img

まず、「New model」をクリックして学習用の新しいモデルを作成します。

img

NAME にモデル名を入力し TYPE は「Face Detection v1」を選択して [Create model] をクリックします。ここではモデル名を my_model としています。

img

モデルの作成は数秒で完了し、ステップ 1 で収集した顔画像が古いものから順に 100 枚読み込まれます。読み込まれた顔画像はモデルにより人物ごとに分類されます。ただし、学習前のモデルのためこの段階では判定精度が悪く顔画像をうまく分類できません。以下の画面に表示されている青枠の分類結果を見ると、異なる人物の顔写真が混ざっていることが分かります。

img

なお、画面上部のプログレスバーでは以下が確認できます。

  • Saved:学習済の顔画像の枚数
  • Pending:コンソール上に読み込んだ顔画像の枚数
  • Remaining:ステップ 1 で収集した顔画像の枚数

分類結果を手動で変更してモデルに学習させる

次に、より精度を向上させるためモデルの分類結果を修正します。具体的には以下の 3 つのアクションがあります。

  1. 異なる人物にも関わらず同一人物として分類された顔画像を分離する。(偽陽性への対応)
  2. 同一人物にも関わらず異なる人物として分類された顔画像を統合する。(偽陰性への対応)
  3. 画質の悪い顔画像を学習対象から除外する。

異なる人物にも関わらず同一人物として分類された顔画像を分離する

同一人物として誤って分類してしまった顔画像 (青枠で囲った顔画像) をクリックし Create new person をクリックします。(既にグループが作成されている場合は Move to {統合したいグループのラベル} をクリックします。)

img

クリックした顔画像は同一人物と判定された他の顔画像と共に元のグループから消えて新しいグループが作成されます。

img

img

同一人物にも関わらず異なる人物として分類された顔画像を統合する

下の画面では、同一人物が異なる人物として分類されています。

img

img

この誤りを修正するためには、顔画像をクリックし Move to {統合したいグループのラベル} をクリックします。

img

クリックした顔画像は以下のように同一人物として正しく分類されます。

img

画質の悪い顔画像を学習対象から除外する

モデルの判定精度を向上させるためには、画質の良い画像を学習させる必要があります。例えば以下のような暗い画像などは学習させるとかえって判定精度が低下する可能性があるため、モデルの学習対象から除外します。

img

モデルの学習対象からするためには、顔画像をクリックし Ignore this face をクリックします。

img

クリックした画像は Image Classification (Face) のコンソール上から削除されます。(SORACOM Harvest Files 上からは削除されません。)

顔画像の分類結果を表すラベルを付ける

読み込んだ 100 枚の顔画像に対して上記の修正を実施したら、顔画像の横にある入力ボックスに該当の人物のラベルを入力します。

img

学習結果を反映し、次の顔画像を読み込む

「Save and load more faces」をクリックすると学習結果がモデルに反映されると同時に、顔画像 (次の 100 枚) が読み込まれます。新しく読み込んだ顔画像に対して上記の作業を繰り返します。

img

作成したモデルは SORACOM Harvest Files の /face_detection_v1/models/ 下に <ランダムな文字列>-<作成したモデル名>.json という名前で保存されます。

img

  • 収集した全ての顔画像の分類結果を学習していない状況でもモデルは使用できますが、判定精度を向上させるためにはより多くの顔画像で学習する必要があります。
  • 学習に必要な顔画像の枚数は画像の画質、判定する人物の数、S+ Camera Basic の設置環境、求めている精度などにより異なりますので、ユースケースに応じてご調整ください。

ステップ 3: 作成した顔認識モデルを S+ Camera Basic に反映して顔認識結果を確認する

作成した顔認識モデルを S+ Camera Basic に反映する

SORACOM Mosaic コンソール のデバイス詳細画面の App(CameraApp0) タブからアルゴリズム (Image Classification(Face)) の環境変数 SORACOM_ENV_URI に作成したモデルのパスを指定して、Apply をクリックします。

img

モデルのパスは http://harvest-files.soracom.io/face_detection_v1/models/cjxen9kaiid-my_model.json というような形式で指定してください。

以下のように Parameters have been updated. と表示されれば、反映完了です。

img

モデルによる顔認識を行う

S+ Camera Basic を顔に向けると、判定結果が SORACOM Harvest Data に送信されます。 SORACOM ユーザーコンソール の SIM 管理画面から S+ Camera Basic に取り付けた SIM にチェックを入れ、[操作]>[データを確認]をクリックしてください。

img

顔認識モデルの判定結果が以下のように出力されます。青枠の label に判定した人物のラベルが出力されます。以下の画面では S+ Camera Basic に写った顔画像は jed であると判定されています。なお、学習した顔画像のどの人物にも該当しない場合は null と出力されます。

img

認識がうまくいかない場合には、Device control からデバイスの再起動 (Restart Device) を試してみてください。それでもうまくいかない場合には、 PC を用いたアルゴリズムの開発 を参照してください。

ステップ 4: 顔認識結果を SORACOM Lagoon 上で表示する

今回はモデルの出力結果を SORACOM Lagoon 上にも表示します。SORACOM Lagoon を用いることで、撮影した顔画像などもあわせて表示できます。

SORACOM Lagoon を有効化する

SORACOM のユーザーコンソール にルートアカウントでログインし、サイドメニューの「データ収集・蓄積・可視化」>「SORACOM Lagoon」メニューをクリックします。

注意
SAMユーザーでLagoonの利用開始はできません。必ずメールアドレス・パスワードでログインするルートアカウントで実施してください。

img

SORACOM Lagoon を有効化する

「SORACOM Lagoon の利用を開始する」ボタンをクリックします。

img

プランを選択後、「続行する」をクリックします。なお、本ガイドの手順はどのプランを選択いただいた場合でも実行可能です。

img

パスワードを設定します。 このパスワードは SORACOM コンソールのルートアカウントのメールアドレスで Lagoon へログインする時に必要なパスワードとなります。

img

SORACOM Lagoon へログインする

「SORACOM Lagoon にアクセス」ボタンをクリックします。

img

ルートアカウントのメールアドレスと先ほど設定したパスワードを入力しログインします。

img

以下のような画面が表示されていれば Lagoon の有効化・ログインは成功です。

img

SORACOM Lagoon ダッシュボードを作成する

サンプルダッシュボードの設定をインポートする

当ガイドではダッシュボードの全てのパネルを自身で作成するのではなく、JSON 形式で記述された定義ファイルをインポートすることで以下のようなサンプルダッシュボードを作成します。

img

上記のサンプルダッシュボードの各パネルに表示されるデータは以下のとおりです。

  • Face Image: S+ Camera Basic で撮影された顔画像
  • Mask: マスクの有無
  • Confidence: 学習済の顔画像との類似度
  • History: SORACOM Harvest Data に保存されたデータ

SORACOM Lagoon の画面左の + にカーソルを合わせて、[インポート]をクリックします。

img

[Or paste JSON] の欄に 本ページ末尾 の JSON を貼り付けて、[Load] をクリックします。

img

[Import] をクリックします。

img

サンプルダッシュボードのテンプレート (値が表示されないパネル) が表示されます。

img

S+ Camera Basic の出力結果を表示するように設定を変更する

Face Image のパネル名から、[編集]をクリックします。

img

メトリックタブから S+ Camera Basic に取り付けた SIM の IMSI を選択して、顔画像が表示されることを確認してください。顔画像が表示されない場合は、パネル右上の表示期間中に顔画像が存在することを確認してください。

img

画面上部の保存ボタンをクリックしてパネルを保存します。

img

画面右上のボタンをクリックしてダッシュボードに戻ります。

img

同様に Mask パネルのメトリックを設定します。項目は mask を選択します。

img

Confidence パネルのメトリックを設定します。項目は distance を選択します。

img

History パネルのメトリックを設定します。

img

以下のように全てのパネルに顔画像或いは値が表示されます。

img

当ガイドの手順は以上で終了です。

サンプルダッシュボードの定義ファイル

{
  "annotations": {
    "list": [
      {
        "builtIn": 1,
        "datasource": "-- Grafana --",
        "enable": true,
        "hide": true,
        "iconColor": "rgba(0, 211, 255, 1)",
        "name": "Annotations & Alerts",
        "type": "dashboard"
      }
    ]
  },
  "editable": true,
  "gnetId": null,
  "graphTooltip": 0,
  "id": 2047,
  "links": [],
  "panels": [
    {
      "backgroundMeta": {
        "height": 100,
        "url": "",
        "width": 100
      },
      "backgroundSize": "contain",
      "basicAuth": false,
      "basicAuthPassword": "",
      "basicAuthUsername": "",
      "bgimage": "",
      "bgimageSuffix": ".png",
      "bustCache": true,
      "datasource": null,
      "displayImage": 0,
      "fixRatio": true,
      "gridPos": {
        "h": 9,
        "w": 5,
        "x": 0,
        "y": 0
      },
      "height": "400px",
      "id": 12,
      "links": [],
      "mode": "harvest_files",
      "series": [],
      "seriesList": [],
      "targets": [
        {
          "datatype": "table",
          "devicetype": "subscribers",
          "pro": true,
          "refId": "A",
          "target": "",
          "type": "timeseries"
        }
      ],
      "title": "Face Image",
      "type": "soracom-dynamic-image-panel",
      "urlValue": "A-image_path",
      "valueMaps": {},
      "variables": [],
      "width": "100px"
    },
    {
      "cacheTimeout": null,
      "colorBackground": false,
      "colorValue": false,
      "colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"],
      "datasource": "Harvest",
      "format": "none",
      "gauge": {
        "maxValue": 100,
        "minValue": 0,
        "show": false,
        "thresholdLabels": false,
        "thresholdMarkers": true
      },
      "gridPos": {
        "h": 9,
        "w": 4,
        "x": 5,
        "y": 0
      },
      "id": 8,
      "interval": null,
      "links": [],
      "mappingType": 1,
      "mappingTypes": [
        {
          "name": "singlestat.value_to_text",
          "value": 1
        },
        {
          "name": "singlestat.range_to_text",
          "value": 2
        }
      ],
      "maxDataPoints": 100,
      "nullPointMode": "connected",
      "nullText": null,
      "postfix": "",
      "postfixFontSize": "50%",
      "prefix": "",
      "prefixFontSize": "50%",
      "rangeMaps": [
        {
          "from": "null",
          "text": "N/A",
          "to": "null"
        }
      ],
      "sparkline": {
        "fillColor": "rgba(31, 118, 189, 0.18)",
        "full": false,
        "lineColor": "rgb(31, 120, 193)",
        "show": false
      },
      "tableColumn": "",
      "targets": [
        {
          "datatype": "standard",
          "devicetype": "subscribers",
          "pro": true,
          "properties": "mask",
          "refId": "A",
          "target": "",
          "type": "timeseries"
        }
      ],
      "thresholds": "",
      "title": "Mask",
      "type": "singlestat",
      "valueFontSize": "80%",
      "valueMaps": [
        {
          "op": "=",
          "text": "no mask",
          "value": "0"
        },
        {
          "op": "=",
          "text": "mask",
          "value": "1"
        }
      ],
      "valueName": "current"
    },
    {
      "cacheTimeout": null,
      "colorBackground": false,
      "colorValue": false,
      "colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"],
      "datasource": null,
      "format": "percentunit",
      "gauge": {
        "maxValue": 100,
        "minValue": 0,
        "show": true,
        "thresholdLabels": false,
        "thresholdMarkers": false
      },
      "gridPos": {
        "h": 9,
        "w": 6,
        "x": 9,
        "y": 0
      },
      "id": 4,
      "interval": null,
      "links": [],
      "mappingType": 1,
      "mappingTypes": [
        {
          "name": "singlestat.value_to_text",
          "value": 1
        },
        {
          "name": "singlestat.range_to_text",
          "value": 2
        }
      ],
      "maxDataPoints": 100,
      "nullPointMode": "connected",
      "nullText": null,
      "postfix": "",
      "postfixFontSize": "50%",
      "prefix": "",
      "prefixFontSize": "50%",
      "rangeMaps": [
        {
          "from": "null",
          "text": "N/A",
          "to": "null"
        }
      ],
      "sparkline": {
        "fillColor": "rgba(31, 118, 189, 0.18)",
        "full": false,
        "lineColor": "rgb(31, 120, 193)",
        "show": false
      },
      "tableColumn": "",
      "targets": [
        {
          "datatype": "standard",
          "devicetype": "subscribers",
          "pro": true,
          "properties": "distance",
          "refId": "A",
          "target": "",
          "type": "timeseries"
        }
      ],
      "thresholds": "",
      "title": "Confidence",
      "transparent": true,
      "type": "singlestat",
      "valueFontSize": "80%",
      "valueMaps": [
        {
          "op": "=",
          "text": "N/A",
          "value": "null"
        }
      ],
      "valueName": "current"
    },
    {
      "columns": [],
      "datasource": null,
      "fontSize": "100%",
      "gridPos": {
        "h": 11,
        "w": 18,
        "x": 0,
        "y": 9
      },
      "id": 10,
      "links": [],
      "pageSize": 10,
      "scroll": true,
      "showHeader": true,
      "sort": {
        "col": 0,
        "desc": true
      },
      "styles": [
        {
          "alias": "Time",
          "dateFormat": "YYYY-MM-DD HH:mm:ss",
          "pattern": "time",
          "type": "date"
        },
        {
          "alias": "",
          "colorMode": null,
          "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
          "decimals": 2,
          "pattern": "/.*/",
          "thresholds": [],
          "type": "number",
          "unit": "short"
        }
      ],
      "targets": [
        {
          "datatype": "table",
          "devicetype": "subscribers",
          "pro": true,
          "refId": "A",
          "target": "",
          "type": "timeseries"
        }
      ],
      "title": "History",
      "transform": "table",
      "type": "table"
    }
  ],
  "refresh": "10s",
  "schemaVersion": 16,
  "style": "dark",
  "tags": [],
  "templating": {
    "list": []
  },
  "time": {
    "from": "now-30m",
    "to": "now"
  },
  "timepicker": {
    "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
    "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
  },
  "timezone": "",
  "title": " Image Classification ",
  "uid": "X8z0KznGz2",
  "version": 12
}