Microsoft Cognitive ServicesのFace APIをPerlから使ってみる
どーも、わいとんです。
近頃、業務の延長線上の分野として、顔のパーソナライズ認識、及びそれらのリレーショナルな利用について興味が湧いております。
「顔画像のパーソナライズ認識とリレーショナルな利用」の例
例えばFacebookやvk.comなどのような実名SNSでは、概ね以下のような情報を登録するように促されることでしょう。
- 姓名
- 性別
- 生年月日
- 居住地
- 興味のあること
- 顔画像
さて、これらの情報を一般的なリレーショナルデータベースのテーブル構造として捉えた場合、「姓名」「性別」「年齢」「居住地」「興味のあること」でのレコード検索が可能かと思います。
ところがもし、「顔画像」の近似値でレコード検索できるとしたら・・・
端的な例えですが、こんなことができるようになるわけですね。
2011年の写真くらいしかさっくり入手できなかったのですが、頭の上に何か表示が出てますよね。その気になれば、年齢とか居住地とか出せそうではあるのですが、プライバシー保護の観点から、表示されて良い情報は非常に限定的かと思います。
こんな感じのことをMicrosoft Cognitive Servicesを使えば実現できそうだなぁ、と直感しておりまして、ひとまず一番慣れているperl5で利用できるようモジュールを書いてみました。
ytnobody/p5-Net-Microsoft-CognitiveServices-Face
ちなみにCognitive ServicesのFace APIは、試すだけなら3万トランザクション/月まで無料ですので、割といい感じだと思います。
※Microsoft Cognitive Servicesを利用するためには、あらかじめMicrosoft Azureを利用している必要があります。ここではAzureやCognitive Servicesの設定については細かく説明しませんが、Azure上でCognitive Services - Face APIをデプロイするとAccess Keyが払い出されるので、そのことだけは覚えておいてください。
Net::Microsoft::CognitiveServices::Faceを使ってみる
まぁeg/identify.plあたりを見てもらえると何となく使い方などがわかるとは思うんですが、一応解説。
まずFace APIのドキュメンテーションを把握しておく
Net::Microsoft::CognitiveServices::Face(以下CS::Face)のインターフェースは、ほぼFace APIのドキュメンテーションに合わせて作ってあります。したがって、Face APIのドキュメンテーションを読んでおかないと使い方がピンとこないです。
名前が長いので変数に食わしておく
ハイ、名前が長いのです・・・
my $api = 'Net::Microsoft::CofnitiveServices::Face';
Access Keyを食わせる
まずは何をするにもAccess Keyを食わせないことにはアクセスさせてくれませんので、これを食わせます。
$api->access_key('YOUR_ACCESS_KEY');
YOUR_ACCESS_KEY
は適宜ご自身のAccess Keyに置き換えてください。
Person Groupを作る
人物情報を格納するために、Face APIにてPerson Groupを作っておく必要がありますので、これを作ります。 $person_group_id
は半角英数及びハイフン・アンダーバーが利用可能です。 name
は文字列で好きな値を設定できます。
my $person_group_id = 'my_person_group';
$api->PersonGroup->create($person_group_id, name => 'My Person Group');
Person GroupにPersonを登録していく(人数分やる)
顔画像の登録をする前に、人物情報となるPersonをPerson Groupに登録していきます。name
及びuserData
に任意の文字列を設定できます。
my $person = $api->Person->create($person_group_id,
name => 'ytnobody',
userData => 'Favorite:Programming,Motorcycle,Cooking,Anime',
);
人物情報に顔画像を紐付ける(人数分やる)
先ほど登録した人物情報に顔画像を紐付けます。$image
には、外部から参照可能なurlを食わせる必要があります。
my $person_id = $person->{personId};
my $image = 'https://lh5.googleusercontent.com/-8qD5BkKOV3g/TtpRC-8J_wI/AAAAAAAAAlY/yYk2AFtM51U/s1024/20111203-P1000424.jpg';
$api->Person->add_face($person_group_id, $person_id, $image);
Person Groupに顔画像を学習させる
顔画像の登録が済んだら、Person Groupに顔画像の学習をさせます。学習には顔画像の数によってかかる時間が異なりますが、学習の済んでいないPerson Groupでは人物特定ができませんので、顔画像の登録後には必ず実施する必要があります。
$api->PersonGroup->train($person_group_id);
なお、以下のようにすることで学習状態の確認が可能です。
my $result = $api->PersonGroup->training_status($person_group_id);
say $result->{status}; ## "succeeded" となっていれば学習完了。
異なる顔画像からの人物特定
全く別の画像から顔画像を検出します。
my $detected = $api->Face->detect('https://mynavi-agent.jp/it/geekroid/ent51_img14.jpg');
my $face_id = $detected->[0]{faceId};
検出できた顔画像から、該当する人物のpersonIdを取得します。faceIds
には本来複数のface_idを食わせることが可能ですが、今回は1件のみ食わせました。
なお、maxNumOfCandidatesReturned
にはマッチした人物の件数を指定できますが、1を指定することで一人に絞り込むことができます。
confidenceThreshold
には一致率を0〜1の範囲で指定ができますが、この値に及ばない一致率の結果を足切りすることができます。
my $ident = $api->Face->identify(
faceIds => [ $face_id ],
personGroupId => $person_group_id,
maxNumOfCandidatesReturned => 1,
confidenceThreshold => 0.6,
);
my $candidated_person_id = $ident->[0]{candidates}[0]{personId};
特定できた人物の情報を取得
ここまでである程度「この人間ですよね?」というレベルのマッチングがかかっているので、後はpersonIdを元にPersonを取得できればOKという感じになります。
$person = $api->Person->get($person_group_id, $candidated_person_id);
printf "name => %s \n%s\n", $person->{name}, $person->{userData};
まとめ
PerlからMicrosoft Cognitive ServicesのFace APIを利用するためのモジュールNet::Microsoft::CognitiveServices::Face
を作ってみたので紹介しました。
Cognitive Servicesには他にも画像・動画などの認識にまつわるAPIがあるので、今までにない仕組みを作るのに一役買ってくれるんじゃないでしょうか。