Soracom

Users

ドキュメント

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

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

事前準備 

SORACOM Harvest Files および SORACOM Harvest Data を有効にする 

サンプルアルゴリズムが SORACOM Harvest Files (以下、Harvest Files) や SORACOM Harvest Data (以下、Harvest Data) を使用する場合は、あらかじめ各機能を有効にしてください。詳しくは、「S+ Camera シリーズユーザーガイド」の SIM グループの初期設定 を参照してください。

別途料金が発生します
Harvest Files、および Harvest Data を使用すると、別途料金が発生します。

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

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

サンプルアルゴリズム Image Classification (Face) (顔認識) をインストールしてください。アルゴリズムのインストールについて詳しくは、アルゴリズムをインストールする を参照してください。

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

S+ Camera シリーズ を学習させたい顔に向けると、顔画像が Harvest Files の /image_classification/{MOSAIC ID}/yyyy/mm/dd/ に WebP 形式でアップロードされます。Harvest Files にアップロードされたデータを確認する操作について詳しくは、Harvest Files にアップロードされたデータを確認する を参照してください。

img

利用前に必ず契約約款をご確認ください。S+ Camera シリーズ での撮影時には個人情報およびプライバシーに配慮し、被撮影者の同意を得る等必要な措置をとってください。
顔画像が SORACOM Harvest Files に送信されない場合
  • 当アルゴリズムでは顔を斜めから撮影している場合には顔が認識されません。当社での検証では、正面を向いた状態から上下左右に 30 〜 45 度以上の角度をつけると顔を認識しませんでした。なるべく正面で顔を捉えるよう画角を調整してください。
  • 日光などが強く当たった場合に認識精度が下がる事例が報告されております。適宜設置場所を調整してください。
顔画像は、SORACOM_ENV_WAIT 秒ごとに撮影されます

Image Classification (Face) の詳細設定 (SORACOM_ENV_FREE_PRAM) 

SORACOM_ENV_FREE_PARAM には、JSON 形式で以下のパラメータを指定できます。

パラメータ (型)説明
UInv (integer)データの送信間隔 (この間のデータは破棄)。Default 60 秒
SInt (integer)Harvest Data/Files への送信間隔 (秒)。Default SORACOM_ENV_WAIT (60) 秒
UInv (integer)Harvest Data/Files へのデータの送信間隔 (この間のデータは破棄)。Default SORACOM_ENV_WAIT (秒)
SInt (integer)この期間は同一の顔と判定されたデータを破棄 (秒)。Default SORACOM_ENV_WAIT (秒)
SData (boolean)true の場合、モデル作成用のデータを作成する。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 シリーズ の設置環境、求めている精度などにより異なりますので、ユースケースに応じてご調整ください。

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

img

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

img

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

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

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

SORACOM Lagoon の利用を開始する 

詳しくは、SORACOM Lagoon の利用を開始する を参照してください。

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

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

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

img

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

  • Face Image: S+ Camera シリーズ で撮影された顔画像
  • 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 シリーズ に取り付けた IoT 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
}