中国公安当局が採用しているという画像認識プラットフォーム「Face++」。こちらの記事をみて、顔検出だけでなく視線検出もできるというので、実際に試してみました。
#2019/6/1 誤記修正
環境
- OS: Ubuntu16.04LTS
- Python 3.7.0
Face+とは?
公式サイトを参照頂いたほうが良いかもしれませんが、Deep learningを使った画像認識プラットフォームです。
Face Recognition、Body Recognition、Image Recognitionと3つのカテゴリに分かれていますが、今回はFreeのアカウントを取得して、Face Recogniton のDetect APIを試してみます。
準備
こちらのサイトからアカウントを作成して、API KeyおよびAPI Secretを取得します。2018年10月現在、無料で作成できます。
Detect APIについて
概要
- 画像をインプットすると、その画像の中の人の顔を検出して特徴を分析してくれます。
- 検出する顔の数に制限はなく、検出できる顔は全て検出できるとのこと。(有料プランにすると、検出エリアを指定できるみたいです。)
- 検出された顔から、顔のlandmark(まゆげ、あご等のポイント)や、視線の方向、年齢、性別等の特徴を推論して出力します(Freeプランは5つ迄の制限有り)
実際に使ってみましょう。
APIのフォーマットは基本的に公式Referenceに書いてあるとおりですが、以下にざっと記載します。
- リスクエストURL
- リクエストメソッド
- パラメータ
https://api-us.faceplusplus.com/facepp/v3/detect
POST
今回は、以下のように設定しました。
#Set configuration
config = {'api_key':API_KEY, # API Key
'api_secret':API_SECRET, # API Secret
'image_base64':img_file, # 画像データ
'return_landmark':1, # landmark設定
'return_attributes':'gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus' # 特徴分析
}
それぞれをざっと説明すると、
パラメータ | 内容 |
---|---|
API KeyとAPI Secret | 自分で取得したものを設定 |
画像データ | URL指定/バイナリデータ/base64バイナリデータの3つから選ぶことができます。今回はbase64を選択 |
Landmark | まゆげや目、あごなどの顔のいろいろなポイントのこと。 ここでは、何箇所抽出するかを選択します。検出しない/106個/83個から選びます。今回は、83個にしました。具体的な出力例は後述 |
特徴分析 | 検出画像から、性別、年齢、民族、ご機嫌、視線方向等、いろいろあります。 Face++がどんな学習モデルをつかっているかわかりませんが、それをベースとした推論結果が得られます。今回は欲張って設定できるものは全て設定してみました。主なものを挙げると、
|
各パラメータの詳細は、公式Referenceを参照ください。
これでパラメータは設定できましたので、早速Web APIにアクセスします。Requestsモジュールを使えば簡単ですね。
Requestsモジュールはこちらの記事でもまとめています。ご参照ください。
→ [Python] Webサイトのデータ取得(Requestsモジュール)
import requests
import base64
# 画像ファイルをbase64バイナリ形式で読み出します
# file_pathは画像ファイル(jpgなど)
with open(file_path, 'rb') as f:
img_file = base64.encodebytes(f.read())
# リクエストURLの設定
url = 'https://api-us.faceplusplus.com/facepp/v3/detect'
# POSTリクエスト
res = requests.post(url, data=config)
上記を実行すると、Web APIからのレスポンスが得られます。フォーマットはjson形式です。以下に例を示します。得られます。長いので全部は載せられませんが、一部のみ注釈を入れておきます。
{
"image_id": "***************************",
"request_id": "******************************",
"time_used": 391,
"faces": [
{
★★ Landmarkの出力結果
"landmark": {
"mouth_upper_lip_left_contour2": {
"y": 322,
"x": 533
},
:
(略)
:
"mouth_upper_lip_bottom": {
"y": 327,
"x": 547
}
},
"attributes": {
"emotion": {
"sadness": 98.921,
"neutral": 0.168,
"disgust": 0.011,
"anger": 0.003,
"surprise": 0.006,
"fear": 0.011,
"happiness": 0.88
},
"beauty": {
"female_score": 51.487,
"male_score": 52.842
},
"gender": {
"value": "Female"
},
:
(略)
:
★★ 視線方向は以下の様にxyz座標上の単位ベクトルで表されているようです
"left_eye_gaze": {
"position_x_coordinate": 0.458,
"vector_z_component": 0.994,
"vector_x_component": -0.101,
"vector_y_component": 0.05,
"position_y_coordinate": 0.448
}
}
},
★★ 検出された顔の位置。この数値は顔の傾きは考慮されていないようです。
"face_rectangle": {
"width": 106,
"top": 257,
"left": 485,
"height": 106
},
"face_token": "********************************"
},
:
:
これをjsonモジュールを使って辞書形式に変換して、目的の情報を抽出していきます。
# Load json data
data = json.loads(res.text)
得られた結果を画像に表示するようにしましたので、以下に示します。
尚、コードはこちらにアップロードしておきました。
顔検出と分析結果
- 顔検出のbounding Boxは、顔の傾きに合わせて回転
- 特徴分析の結果を、bounding Boxの横(又は上)に表示
- 目から出ている線は、視線の方向
その1
5人の大人の画像(上)と3人の子供の画像(下)をAPIに通してみました。どちらも顔を全て検出できています。視線は画像上分かり難い為かあまり正確でなさそうなものもあります。メガネがやはり厳しそうです。年齢は正確でないかもしれません。(人間でも正確に当てるのは難しい)
その2
顔がたくさんあってもほぼ検出できています。
その3
横顔も検出できてますね。
その4
目がはっきり見えていると、視線の方向はそれなりに合っているように思います。
Landmarks結果
5人の顔のランドマークがきちんと検出されています。
まとめと所感
今回は、Face++の顔検出Web APIを試してみました。顔検出自体は、ランドマークがかなり正確に検出できているので、なかなかうまくできているように思います。
年齢や性別などは、大人の画像はそれなりに推論できているようでしたが、子供は難しそうですね。正確な年齢は人間でも当てることは難しいので、画像だけで判定させるのは無理があるかも。
視線検出については、画像認識を使った方法では更なる正確さを求めるのは難しいかもしれません。
今回はweb APIなのでワンショットしかできませんでしたが、デバイスに組み込んでリアルタイム動画で検出させると用途が広がると思いました。