Google Cloud Platformのニューラルネットワークで写真の人物の顔の表情から感情分析 | そう備忘録

Google Cloud Platformのニューラルネットワークで写真の人物の顔の表情から感情分析

顔の感情分析

以前にGCP(Google Cloud Platform)のニューラルネットワークモデルのSpeech-to-Text APIを使って音声をテキスト化した時の事を記事とそのテキスト文章をanalyzeSentiment APIを使って感情分析をした時の記事を書いた。

今回はテキストからでは無く、人物の顔写真からの感情分析を行うCloud Vision APIについて試してみた事を備忘録として記事にしておく。

概要図

複数の人物の写っている写真より顔のパーツを検出して、

  1. 喜び
  2. 悲しみ
  3. 怒り
  4. 驚き

の4種類の感情を分析すると同時に顔のパーツの写真上の座標を検出する。

感情分析概要図

事前準備

GCP上でAPIを使用できる環境を整える必要があるのだが大まかな手順は以下の通り。

  1. GCP(Google Clond Platform)でプロジェクトを作成する
  2. API認証情報を作成する(控えておく)
  3. VMインスタンスを作成する

上記については以前の記事の「GCP(Google Clond Platform)でプロジェクトを作成する」から「VMインスタンスを作成する」までを参照して欲しい。

顔の感情分析を行う

前述の手順でAPI実行用のVMインスタンスが出来ている前提として以下の手順で感情分析を行う。

Cloud Vision APIを有効にする

顔感情分析で必要なAPIを有効にする。

Google Cloud Platformにログインしてメニューから”APIとサービス”ー>”ライブラリ”をクリックする。

APIとサービス、ライブラリ

“APIとサービスを検索”欄でCloud Vision APIを検索する。

Cloud Natural Language APIを検索する

「有効にする」ボタンをクリックする。

Cloud Vision APIを有効にする

有効になった。

Cloud Vision APIが有効になった

sshの起動

Compute EngineのVMインスタンスの画面にて該当インスタンスのSSH横の三角をクリックして”ブラウザウィンドウで開く”をクリックする。

sshをブラウザウィンドウで開く

APIキーの設定

しばらく待つと新しいsshウィンドウが開く。

API認証情報を作成する”で控えておいたAPIキーを使うのだがAPIを呼び出すたびに何回も入力するのは面倒なので下記のコマンドで環境変数に保存しておく。

export API_KEY=控えておいたAPI KEY

APIキーをexport

ストレージにファイルをアップロード

人物の顔が写った写真をGoogleのストレージにアップロードする。

写真は著作権フリーの人物写真を探して利用させて貰うことにした。

今回使用するフリーの写真

今回使用させて貰ったのは以下の2つの写真。

1枚目は日本人家族の集合写真。

外国人からは日本人の表情が分かりづらいと聞いたことがあるので主に外国人の顔写真で学習したと思われるGoogleのAPIでそれぞれの感情が読み取れるのかを試してみようと思う。

家族の集合写真

2枚目は外国人の両親と赤ちゃんの写真。

両親はともかく赤ちゃんの表情から感情をどの様にGoogleのニューラルネットワークが分析するのか興味深い。

外国人家族

Cloud Storageにアップロード

メニューから”storage”ー>”ブラウザ”、バケットの作成で”cloudvision20200628”を作成してその中に感情分析したい画像をアップロードした。(バケットの作成からファイルのアップロードまで詳しいやり方は以前の記事を参照して欲しい)

尚、外部から参照できるようにallUsersの権限を追加している。

保存したファイル

request_facedetect.jsonの作成

リクエスト用のJSONファイルを準備する。

{
  "requests": [
      {
        "image": {
          "source": {
              "gcsImageUri": "gs://cloudvision20200628/face-detect-01.jpg"
          }
        },
        "features": [
          {
            "type": "FACE_DETECTION"
          }
        ]
      }
  ]
}

gcsImageUri

Google Storage上の写真のパス名を指定する

type

分析のタイプを指定する

  • FACE_DETECTION:顔分析
  • LANDMARK_DETECTION:ランドマーク(写っている場所が何処かを判別)
  • TEXT_DETECTION:テキスト(画像上の文字をテキストに変換)

等が指定可能で複数のtypeを同時に指定する事も出来る

今回はFACE_DETECTIONのみを指定した

実行コマンド

以下のコマンドでCloud Vision APIを呼び出して実行する。

curl -s -X POST -H "Content-Type: application/json" --data-binary @request_facedetect.json  https://vision.googleapis.com/v1/images:annotate?key=${API_KEY}

実行結果(日本人家族)

最初に日本人家族の実行結果

検出結果のJSONは非常に長いので加工、省略してコメントを追記している。

{
  "responses": [
    {
      "faceAnnotations": [
        {
          "boundingPoly": {
            "vertices": [
              {
                "x": 1836,
                "y": 818
              },
              {
                "x": 2164,
                "y": 818
              },
              {
                "x": 2164,
                "y": 1198
              },
              {
                "x": 1836,
                "y": 1198
              }
            ]
          },
          "fdBoundingPoly": {
            "vertices": [
              {
                "x": 1873,
                "y": 880
              },
              {
                "x": 2144,
                "y": 880
              },
              {
                "x": 2144,
                "y": 1168
              },
              {
                "x": 1873,
                "y": 1168
              }
            ]
          },
          "landmarks": [
            {
              "type": "LEFT_EYE", ←顔のパーツ位置(左目の座標)
              "position": {
                "x": 1958.7432,
                "y": 1008.46277,
                "z": -7.6293945e-06
              }
            },
            {
              "type": "RIGHT_EYE", ←右目の座標
              "position": {
                "x": 2055.521,
                "y": 1000.0075,
                "z": 4.8429937
              }
            },
            {
以下省略
              "type": "LEFT_OF_LEFT_EYEBROW", ←左眉(以下座標は省略)
              "type": "RIGHT_OF_LEFT_EYEBROW", ←以下、顔のパーツ位置が続く
              "type": "LEFT_OF_RIGHT_EYEBROW",
              "type": "RIGHT_OF_RIGHT_EYEBROW",
              "type": "MIDPOINT_BETWEEN_EYES",
              "type": "NOSE_TIP",
              "type": "UPPER_LIP",
              "type": "LOWER_LIP",
              "type": "MOUTH_LEFT",
              "type": "MOUTH_RIGHT",
              "type": "MOUTH_CENTER",
              "type": "NOSE_BOTTOM_RIGHT",
              "type": "NOSE_BOTTOM_LEFT",
              "type": "NOSE_BOTTOM_CENTER",
              "type": "LEFT_EYE_TOP_BOUNDARY",
              "type": "LEFT_EYE_RIGHT_CORNER",
              "type": "LEFT_EYE_BOTTOM_BOUNDARY",
              "type": "LEFT_EYE_LEFT_CORNER",
              "type": "RIGHT_EYE_TOP_BOUNDARY",
              "type": "RIGHT_EYE_RIGHT_CORNER",
              "type": "RIGHT_EYE_BOTTOM_BOUNDARY",
              "type": "RIGHT_EYE_LEFT_CORNER",
              "type": "LEFT_EYEBROW_UPPER_MIDPOINT",
              "type": "RIGHT_EYEBROW_UPPER_MIDPOINT",
              "type": "LEFT_EAR_TRAGION",
              "type": "RIGHT_EAR_TRAGION",
              "type": "FOREHEAD_GLABELLA",
              "type": "CHIN_GNATHION",
              "type": "CHIN_LEFT_GONION",
              "type": "CHIN_RIGHT_GONION",
省略
          "rollAngle": -3.5831172, ←息子(手前の子供)
          "panAngle": 2.8962502,
          "tiltAngle": -0.7956371,
          "detectionConfidence": 0.7510176,
          "landmarkingConfidence": 0.8474098,
          "joyLikelihood": "VERY_LIKELY",
          "sorrowLikelihood": "VERY_UNLIKELY",
          "angerLikelihood": "VERY_UNLIKELY",
          "surpriseLikelihood": "VERY_UNLIKELY",
          "underExposedLikelihood": "VERY_UNLIKELY",
          "blurredLikelihood": "VERY_UNLIKELY",
          "headwearLikelihood": "VERY_UNLIKELY"

以下省略(顔感情分析のみ)
          "rollAngle": -2.6513717, ←娘(手前の子供)
          "panAngle": 3.2708335,
          "tiltAngle": 1.9415131,
          "detectionConfidence": 0.95929766,
          "landmarkingConfidence": 0.80905235,
          "joyLikelihood": "VERY_LIKELY",
          "sorrowLikelihood": "VERY_UNLIKELY",
          "angerLikelihood": "VERY_UNLIKELY",
          "surpriseLikelihood": "VERY_UNLIKELY",
          "underExposedLikelihood": "VERY_UNLIKELY",
          "blurredLikelihood": "VERY_UNLIKELY",
          "headwearLikelihood": "VERY_UNLIKELY"

省略
          "rollAngle": -5.808591, ←祖母(右端)
          "panAngle": -12.45207,
          "tiltAngle": 7.7147107,
          "detectionConfidence": 0.9816313,
          "landmarkingConfidence": 0.71497536,
          "joyLikelihood": "UNLIKELY",
          "sorrowLikelihood": "VERY_UNLIKELY",
          "angerLikelihood": "VERY_UNLIKELY",
          "surpriseLikelihood": "VERY_UNLIKELY",
          "underExposedLikelihood": "VERY_UNLIKELY",
          "blurredLikelihood": "VERY_UNLIKELY",
          "headwearLikelihood": "VERY_UNLIKELY"

省略
          "rollAngle": -4.591464, ←母(後列)
          "panAngle": -2.5934389,
          "tiltAngle": -3.351017,
          "detectionConfidence": 0.9577053,
          "landmarkingConfidence": 0.64401776,
          "joyLikelihood": "VERY_LIKELY",
          "sorrowLikelihood": "VERY_UNLIKELY",
          "angerLikelihood": "VERY_UNLIKELY",
          "surpriseLikelihood": "VERY_UNLIKELY",
          "underExposedLikelihood": "VERY_UNLIKELY",
          "blurredLikelihood": "VERY_UNLIKELY",
          "headwearLikelihood": "VERY_UNLIKELY"

省略
          "rollAngle": 1.7782475, ←祖父(左端)
          "panAngle": 9.86058,
          "tiltAngle": -1.5865794,
          "detectionConfidence": 0.61254394,
          "landmarkingConfidence": 0.6965967,
          "joyLikelihood": "LIKELY", 
          "sorrowLikelihood": "VERY_UNLIKELY",
          "angerLikelihood": "VERY_UNLIKELY",
          "surpriseLikelihood": "VERY_UNLIKELY",
          "underExposedLikelihood": "VERY_UNLIKELY",
          "blurredLikelihood": "VERY_UNLIKELY",
          "headwearLikelihood": "VERY_UNLIKELY"

省略
          "rollAngle": -1.6559919, ←父(後列)
          "panAngle": -0.8663944,
          "tiltAngle": 9.723327,
          "detectionConfidence": 0.965396,
          "landmarkingConfidence": 0.6743713,
          "joyLikelihood": "VERY_UNLIKELY",
          "sorrowLikelihood": "VERY_UNLIKELY",
          "angerLikelihood": "VERY_UNLIKELY",
          "surpriseLikelihood": "VERY_UNLIKELY",
          "underExposedLikelihood": "VERY_UNLIKELY",
          "blurredLikelihood": "VERY_UNLIKELY",
          "headwearLikelihood": "VERY_UNLIKELY"

出力結果のJSONには各自の顔のパーツ位置の座標(X、Y、Z)の検出結果と感情分析の結果が出力された。

主な項目は以下の通り。

  • detectionConfidence:検出信頼度
  • joyLikelihood:喜び
  • sorrowLikelihood:悲しみ
  • angerLikelihood:怒り
  • surpriseLikelihood:驚き
  • underExposedLikelihood:露出
  • blurredLikelihood:ピンぼけ
  • headwearLikelihood:被りもの?

それぞれ6人の感情の検出結果は以下の通り。

祖父(左端)

祖父

「喜んでいる」判定

元の写真では若干固目の表情だからなのかVERYの付かない”LIKELY”の判定

 しかし日本人の表情であってもある程度正確に読み取れる事が分かった

祖母(右端)

祖母

「喜んでいない」判定

やや微笑んでいるように見えるのだがニューラルネットワーク的には”UNLIKELY”との判断

祖父もそうだが高齢者の表情の検知は全体的に厳し目に出ているように感じた

父(後列)

父

「どれでも無い」判定

全ての項目で”VERY_UNLIKELY”判定

かしこまった表情からは感情が読み取れないとの判定と思われる

母(後列)

母

「とても喜んでいる」判定

母親の表情から感情を正しく読み取っていると思う

息子(前列子供)

息子(子供)

「とても喜んでいる」判定

子供達の表情はどちらも”VERY_LIKELY”判定

元の写真では若干微妙な表情だとは思ったのだが子供の方が感情が強目に判定されているのかも知れない

祖母の写真と比べてもそれほど大きな差は無いように思うのだが。。。

娘(前列子供)

娘(子供)

「とても喜んでいる」判定

実行結果(外国人家族)

続いて赤ちゃんを含む外国人家族の写真の検出結果。

前半部分省略

          "rollAngle": 0.034466736, ← 父親
          "panAngle": -11.247587,
          "tiltAngle": -7.610189,
          "detectionConfidence": 0.8356669,
          "landmarkingConfidence": 0.74332947,
          "joyLikelihood": "LIKELY",
          "sorrowLikelihood": "VERY_UNLIKELY",
          "angerLikelihood": "VERY_UNLIKELY",
          "surpriseLikelihood": "VERY_UNLIKELY",
          "underExposedLikelihood": "VERY_UNLIKELY",
          "blurredLikelihood": "VERY_UNLIKELY",
          "headwearLikelihood": "VERY_UNLIKELY"


          "rollAngle": -5.8361053, ←赤ちゃん
          "panAngle": 10.476092,
          "tiltAngle": -0.96431774,
          "detectionConfidence": 0.7338021,
          "landmarkingConfidence": 0.6968528,
          "joyLikelihood": "VERY_UNLIKELY",
          "sorrowLikelihood": "VERY_UNLIKELY",
          "angerLikelihood": "VERY_UNLIKELY",
          "surpriseLikelihood": "UNLIKELY",
          "underExposedLikelihood": "VERY_UNLIKELY",
          "blurredLikelihood": "VERY_UNLIKELY",
          "headwearLikelihood": "VERY_UNLIKELY"


          "rollAngle": -6.7787957, ←母親
          "panAngle": -11.010976,
          "tiltAngle": -5.9172897,
          "detectionConfidence": 0.7529465,
          "landmarkingConfidence": 0.5972206,
          "joyLikelihood": "VERY_LIKELY",
          "sorrowLikelihood": "VERY_UNLIKELY",
          "angerLikelihood": "VERY_UNLIKELY",
          "surpriseLikelihood": "VERY_UNLIKELY",
          "underExposedLikelihood": "VERY_UNLIKELY",
          "blurredLikelihood": "VERY_UNLIKELY",
          "headwearLikelihood": "VERY_UNLIKELY"

父親

父親

「喜んでいる」判定

確かに妥当な判定かと思う

母親

母親

「とても喜んでいる」判定

こちらの判定も納得の結果

赤ちゃん

赤ん坊

「驚いていない」判定

surpriseLikelihoodがUNLIKELYでそれ以外はVERY_UNLIKELYの判定

合っているとも間違っているとも判定できない結果

この赤ん坊の表情からの感情を判定するのは難しいのかも知れない

終わりに

以上で人物の顔写真から感情を検出するCloud Vision APIの記事は終了とする。

最後に

この記事が何処かで誰かの役に立つことを願っている。

尚、当記事中の商品へのリンクはAmazonアソシエイトへのリンクが含まれています。Amazonのアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。

souichirou

やった事を忘れない為の備忘録 同じような事をやりたい人の参考になればと思ってブログにしてます。 主にレゴ、AWS(Amazon Web Services)、WordPress、Deep Learning、RaspberryPiに関するブログを書いています。 仕事では工場に協働ロボットの導入や中小企業へのAI/IoT導入のアドバイザーをやっています。 2019年7月にJDLA(一般社団法人 日本デイープラーニング協会)Deep Learning for GENERALに合格しました。 質問は記事一番下にあるコメントかメニュー上部の問い合わせからお願いします。

おすすめ

質問やコメントや励ましの言葉などを残す

名前、メール、サイト欄は任意です。
またメールアドレスは公開されません。