Edited at
NextremerDay 19

年齢・性別判定APIを比較しました(その1)

More than 1 year has passed since last update.

Nextremer Advent Calendar 2016の19日目の記事です。


はじめに

顔画像から年齢や性別を判定するAPIは多くありますが、どのAPIが良いか気になり試してみました(2016年12月時点)。

今回比較したのは次の4つです。APIではないですが、参考のためフリーの年齢・性別モデルも比較しました。

結論から言うと、FaceAPIが良かったです。

検証は下記サイトを参考に、有名人のInstagram画像と生年月日を用いました。

なお、今回は性別判定についての記事になります。


準備

各種APIのユーザ登録を行い、Pythonで実装しました。

ユーザ登録の方法は割愛します。


APIキーの準備

登録時に取得したAPIキーはconfigファイルにまとめました。

各APIキー取得のためにget_api_key()を定義しています。

cfg = ConfigParser.SafeConfigParser()

cfg.read('config/api.cfg')

def get_api_key(section):
return cfg.get(section,'key') if cfg.has_section(section) and cfg.has_option(section, 'key') else {}

configファイルは以下の通りです。

[MSApi]

key = (Face APIのキー)

[IBMApi]
key =(Visual Recognitionのキー)

[PUXApi]
key =(PUX 評価版APIのキー)
domain = (PUX 評価版APIのドメイン)


Microsoft社: Face APIの使用

pathの画像について判定します。

判定結果をgender(性別), age(類推年齢)の2つに保存しています。

ageは小数点まで求まります。

def ms_predict(path):

print("//// MS ////")
# 該当のAPIキーを取得する
ms_key = get_api_key('MSApi')
if ms_key:
CF.Key.set(ms_key)
with open(path, 'rb') as image_file:
result = CF.face.detect(image_file, landmarks=True, attributes='age,gender')
# 顔画像を検出した場合に、gender,ageに値を入れる
if len(result) > 0:
target = result[0]["faceAttributes"]
res["gender"] = target["gender"]
res["age"] = target["age"]
print(res)
else:
print("No Face")
return res


IBM社: Visual Recognitionの使用

pathの画像について判定します。

判定結果をgender(性別), lo(類推年齢の下限), hi(類推年齢の上限)の3つに保存しています。

loやhiは必ずしも存在しない場合があり注意が必要です。

def ibm_predict(path):

print("//// IBM ////")
# 該当のAPIキーを取得する
ibm_key = get_api_key('IBMApi')
if ibm_key:
# Visual Recognition 無料プランでは、イメージのタグ付けおよび顔検出に対して、Bluemix アカウント 1 つにつき 1 日あたり 250 個のイベント (イメージ) を利用できます。
IBM_recognition = VisualRecognitionV3('2016-05-20', api_key=ibm_key)
with open(path, 'rb') as image_file:
result = IBM_recognition.detect_faces(images_file=image_file)
# 顔画像を検出した場合に、gender,lo,hiに値を入れる
if len(result["images"][0]["faces"]) > 0:
target = result["images"][0]["faces"][0]
res["gender"] = target["gender"]["gender"]
if target["age"].has_key("min"):
res["lo"] = target["age"]["min"]
if target["age"].has_key("max"):
res["hi"] = target["age"]["max"]
print(res)
else:
print("No Face")
return res


PUX社: 顔検出(評価版)の使用

pathの画像について判定します。

判定結果をgender(性別), age(類推年齢)の2つに保存しています。

#PUXのdetectFaceAPIを使用

def pux_predict(path):
print("//// PUX ////")
# 該当のAPIキーを取得する
pux_key = get_api_key('PUXApi')
if pux_key:
url = 'http://eval.api.polestars.jp:8080/webapi/face.do'
# APIの規約に合わせるために一時的にjpegに変換
im = Image.open(path)
im.save("/tmp/tmp.jpg", "JPEG")
with open("/tmp/tmp.jpg", 'rb') as image_file:
data = {
'apiKey': pux_key,
'inputBase64': base64.b64encode(image_file.read()).decode(),
'response': 'json'
}
result = json.loads(requests.post(url, data, headers={'Content-Type': 'application/x-www-form-urlencoded'}).text)
# 顔画像を検出した場合に、gender,ageに値を入れる
if result["results"]["faceRecognition"].has_key("detectionFaceInfo"):
target = result["results"]["faceRecognition"]["detectionFaceInfo"][0]
res["gender"] = "Male" if str(target["genderJudge"]["genderResult"]) == "0" else "Female"
res["age"] = target["ageJudge"]["ageResult"]
print(res)
else:
print("No Face")
return res


その他:フリーの年齢・性別モデルの使用

pathの画像について判定します。

判定結果をgender(性別), lo(類推年齢の下限), hi(類推年齢の上限)の3つに保存しています。

こちらを参考に、入出力を下記の形で実装しました。

def org_predict(path):

print("//// Original ////")
input_image = caffe.io.load_image(path)

# 顔画像を検出した場合に、gender,lo,hiに値を入れる
res["gender"] = _predict_gender(input_image)
res["lo"], res["hi"] = _predict_age(input_image)
print(res)
return res


データの準備

Instagramより、本人のみ写った写真を1~10枚集めました。対象年齢は20歳〜83歳です。

175名分(男性:73名、女性:102名)で、計816枚集めました。

ちなみに、今回一番大変だったのは画像集めでした:frowning2:

対象者の年齢分布は次の通りです。

スクリーンショット 2016-12-20 13.26.34.png


実験結果(性別判定)


正解と不正解、非検出数

スクリーンショット 2016-12-20 9.38.27.png


  • 正解:男性を男性、女性を女性と判定した数

  • 不正解:男性を女性、女性を男性と判定した数

  • 非検出:顔の認識が出来なかった数(正解 + 不正解 + 非検出 = 816)

  • 正解率:顔を認識した場合の正解の割合(正解 / (正解 + 不正解))

  • 検出率:顔を認識した割合((正解 + 不正解)/(正解+不正解+ 非検出))


男性と女性の判定数

スクリーンショット 2016-12-20 10.37.56.png


  • 男性:男性だと判定した数

  • 女性:女性だと判定した数


考察



  • FaceAPI正解率が0.96と最も高く、検出率は0.86と最も低い。顔検出が厳密に行われ、高い正解率になったのかも。


  • Visual Recognition正解率が0.8と低く、検出率は0.99と非常に高い。顔認識が不正確な場合でもなんらかの値を返しているみたい。


  • PUXの顔検出(評価版)正解率が0.82で、検出率は0.87だった。日本製APIのため有利かと思ってましたが、意外な結果でした。


  • その他のフリーの年齢・性別モデル正解率が0.57と最も低く、検出率は1で最も高い。顔認識が不正確だと男性として判定してそうです(実装によりますが)

正解率と検出率はトレードオフかもしれません。


まとめ


  • 正解率で考えると、FaceAPIが最も性別判定に使える

  • 検出率で考えると、Visual Recognitionがバランスが良い

今回は、性別判定のみで記事にしました。個人的には、APIのコール数が月30,000回まで無料で、性能も良いFaceAPIが使いやすいと思います。

それと、は◯な愛さんの性別の真値に迷いました

(ちなみに、性別判定だけなら、Amazon Rekognitionもできるので、そのうち比較してみたいと思います)


今後

次回は年齢判定について記事にします。日本製のモデルであるPUXの性能が気になるところです。

※追記:その2を書きました(2017/12/19) 。