Nextremer Advent Calendar 2016の19日目の記事です。
はじめに
顔画像から年齢や性別を判定するAPIは多くありますが、どのAPIが良いか気になり試してみました(2016年12月時点)。
今回比較したのは次の4つです。APIではないですが、参考のためフリーの年齢・性別モデルも比較しました。
結論から言うと、FaceAPIが良かったです。
- Microsoft社: Face API
- IBM社: Visual Recognition
- PUX社: 顔検出(評価版)
- その他:フリーの年齢・性別モデル
検証は下記サイトを参考に、有名人の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枚集めました。
ちなみに、今回一番大変だったのは画像集めでした
対象者の年齢分布は次の通りです。
実験結果(性別判定)
正解と不正解、非検出数
- 正解:男性を男性、女性を女性と判定した数
- 不正解:男性を女性、女性を男性と判定した数
- 非検出:顔の認識が出来なかった数(正解 + 不正解 + 非検出 = 816)
- 正解率:顔を認識した場合の正解の割合(正解 / (正解 + 不正解))
- 検出率:顔を認識した割合((正解 + 不正解)/(正解+不正解+ 非検出))
男性と女性の判定数
- 男性:男性だと判定した数
- 女性:女性だと判定した数
考察
- 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) 。