Soracom

Users

ドキュメント

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

Image Classification (Face) は、S+ Camera シリーズ で取得した顔画像を元に学習した顔認識モデルを簡単に作成できるサンプルアルゴリズムです。作成したモデルを使用することで、S+ Camera シリーズ で顔認識ができます。

ここでは Image Classification (Face) で作成した顔認識モデルを S+ Camera シリーズ にインストールして、顔認識の結果を Lagoon の Dashboard に表示する手順を説明します。

操作を始める前に準備が必要です (クリックして確認してください)

(1) エッジコンピューターを準備して SORACOM ユーザーコンソールに登録する

あらかじめ、エッジコンピューターの初期設定を行ってください。詳しくは、「S+ Camera シリーズユーザーガイド」の S+ Camera シリーズの初期設定を行う を参照してください。

準備完了

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

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

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

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

[SORACOM_ENV_FREE_PARAM] には、JSON 形式で以下のパラメータを指定できます。環境変数の設定については、エッジコンピューターごとに任意のパラメータを渡す (環境変数) を参照してください。

パラメータ (型)説明
UInv (integer)データの送信間隔 (この間のデータは破棄)。デフォルトは、60 秒です。
SInt (integer)Harvest Data/Files への送信間隔 (秒)。デフォルトは、[SORACOM_ENV_WAIT] に指定した時間 (秒) です。
UInv (integer)Harvest Data/Files へのデータの送信間隔 (この間のデータは破棄)。デフォルトは、[SORACOM_ENV_WAIT] に指定した時間 (秒) です。
SInt (integer)この期間は同一の顔と判定されたデータを破棄 (秒)。デフォルトは、[SORACOM_ENV_WAIT] に指定した時間 (秒) です。
SData (boolean)true の場合、モデル作成用のデータを作成します。デフォルトは、true です。

学習用の顔画像を撮影する

サンプルアルゴリズム Image Classification (Face) (顔認識) をインストールした S+ Camera シリーズ に学習させる顔を映すと、顔画像が Harvest Files の /image_classification/{MOSAIC ID}/yyyy/mm/dd/ に WebP 形式でアップロードされます。

img img

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

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

顔画像は、環境変数 [SORACOM_ENV_WAIT] に指定した時間 (秒) ごとに撮影されます。

Harvest Files にアップロードされたデータを確認する操作について詳しくは、Harvest Files にアップロードされたデータを確認する を参照してください。

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

顔認識をするには、Harvest Files の /face_detection_v1/detections/ にモデル作成用のデータを保存する必要があります。

モデル作成用のデータは、以下の条件で作成されます。

  • Image Classification (Face) をインストールした S+ Camera Basic で撮影した顔が分類できない場合 (認識結果の labelnull の場合)

    顔認識ができない顔について、モデル作成用のデータが作成されます。

  • Image Classification (Face) をインストールした S+ Camera Basic の Image Classification (Face) の詳細設定 (SORACOM_ENV_FREE_PRAM) で、SDatatrue に設定している場合

    この場合は、顔認識の結果に関わらずすべての顔について、モデル作成用のデータが作成されます。

学習用の新しいモデルを作成する

  1. Mosaic コンソール の右上のユーザー名をクリックして、[Mosaic Classifier (BETA)] をクリックします。

    Image Classification (Face) コンソールが表示されます。

    img img

  2. [+New model] をクリックします。

    img img

  3. [NAME] にモデル名 (例: my_model) を入力し、[TYPE] で「Face Detection v1」を選択して、[Create model] をクリックします。

    img img

  4. [OK] をクリックします。

    モデルの作成は数秒で完了し、ステップ 1: S+ Camera Basic を使って学習用の顔画像を収集する で収集した顔画像が古いものから順に 100 枚読み込まれます。読み込まれた顔画像はモデルにより人物ごとに分類されます。

    ただし、学習前のモデルのためこの段階では判定精度が悪く顔画像をうまく分類できません。以下の画面に表示されている青枠の分類結果を見ると、異なる人物の顔写真が混ざっていることが分かります。

    img img

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

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

分類結果を手動で変更する

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

(1) 異なる人物にも関わらず同一人物として分類された顔画像を分離する (偽陽性への対応)

(2) 同一人物にも関わらず異なる人物として分類された顔画像を統合する (偽陰性への対応)

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

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

  1. 誤って同一人物として分類された顔画像 (青枠で囲った顔画像) をクリックして、[Create new person] をクリックします。

    すでにグループが作成されている場合は、[Move to {統合するグループのラベル}] をクリックします。

    ここでは、Person 1 の中から、新しい人物を分離します。

    img img

    クリックした顔画像が、元のグループ (Person 1) から消えて、新しく作成されたグループ (Person 20) に移動されます。このとき、クリックした顔画像と同一人物と判定された他の顔画像も、同様に移動されます。

    img img

    img img

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

以下の Person 30 と Person 35 のように、同一人物が異なる人物として分類される場合があります。

img img

img img

  1. 誤って異なる人物として分類された顔画像 (青枠で囲った顔画像) をクリックして、[Move to {統合するグループのラベル}] をクリックします。

    img img

    クリックした顔画像が、同一人物として分類されます。

    Person 30:

    img img

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

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

img img

  1. モデルの学習対象から外す顔画像をクリックして、[Ignore this face] をクリックします。

    img img

    クリックした画像は Image Classification (Face) コンソールから削除されます。

    Image Classification (Face) コンソールから削除された画像は、Harvest Files 上からは削除されません。

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

読み込んだ 100 枚の顔画像に対して、分類結果を手動で変更 したら、顔画像の横にある入力ボックスに人物のラベルを入力します。

img img

分類結果をモデルに反映して次の顔画像を読み込む

  1. [Confirm 100 faces and load more] をクリックします。

    分類結果がモデルに反映され、次の顔画像が 100 枚読み込まれます。新しく読み込んだ顔画像に対して、分類結果を手動で変更 し、顔画像の分類結果を表すラベルを付け ます。

    img img

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

    img img

  • Harvest Files にアップロードされたデータを確認する操作について詳しくは、Harvest Files にアップロードされたデータを確認する を参照してください。
  • 収集したすべての顔画像の分類結果を学習していない状況でもモデルは使用できます。ただし、判定精度を向上させるためには、より多くの顔画像で学習する必要があります。
  • 学習に必要な顔画像の枚数は、画像の画質、判定する人物の数、S+ Camera シリーズ の設置環境、求める精度などによって異なります。ユースケースに応じて調整してください。

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

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

  1. Mosaic コンソール にアクセスし、顔認識モデルを反映するエッジコンピューターのデバイス ID をクリックします。

  2. [アルゴリズム] タブをクリックし、作成したモデルの URI (例: http://harvest-files.soracom.io/face_detection_v1/models/cjxen9kaiid-my_model.json) を [SORACOM_ENV_URI] に入力して、[適用] をクリックします。

    img img

  3. [OK] をクリックします。

    img img

顔認識を行う

[SORACOM_ENV_URI] に顔認識モデルの URI を指定した S+ Camera シリーズ に顔を映すと、顔認識の判定結果が Harvest Data に送信されます。

Harvest Data を確認すると、以下の青枠で示したように、判定した人物のラベルが label に出力されます。以下の画面では、jed であると判定されています。

img img

顔認識されない場合には、エッジコンピューターを再起動 してください。

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

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

Lagoon の利用を開始する

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

SORACOM Lagoon の Dashboard を作成する

ここでは、サンプル Dashboard の定義 をインポートすることで、以下のような Dashboard を作成します。

img img

各パネルに表示されるデータは以下のとおりです。

  • Face Image: S+ Camera シリーズ で撮影された顔画像
  • Mask: マスクの有無
  • Confidence: 学習済みの顔画像との類似度
  • History: Harvest Data に保存されたデータ
  1. SORACOM Lagoon コンソール にアクセスして、[+][Import] の順にクリックします。

    img img

  2. [Import via panel json]サンプル Dashboard の定義 の JSON を貼り付けて、[Load] をクリックします。

    img img

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

    img img

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

    img img

  4. Face Image のパネル名をクリックして、[Edit] をクリックします。

    img img

  5. [Query] タブ の [Metric][Air] を選択し、S+ Camera シリーズ で利用する IoT SIM を選択します。

    顔画像が表示されます。顔画像が表示されない場合は、パネル右上の表示期間に顔画像が存在することを確認してください。

    img img

  6. [Save][Save] の順にクリックします。

    Panel が保存されます。

    img img

  7. [Apply] をクリックします。

    Dashboard に戻ります。

    img img

  8. 同様に Mask パネルを設定します。

    S+ Camera シリーズ で利用する IoT SIM を選択し、mask を選択してください。

    img img

  9. 続けて、Confidence パネルを設定します。

    S+ Camera シリーズ で利用する IoT SIM を選択し、distance を選択してください。

    img img

  10. 最後に、History パネルを設定します。

    S+ Camera シリーズ で利用する IoT SIM を選択してください。

    img img

    以上の操作で、すべてのパネルに顔画像や値が表示されます。

    img img

サンプル Dashboard の定義

{
  "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
}