LoginSignup
2
2

More than 3 years have passed since last update.

FaceAPIをRubyから使う

Last updated at Posted at 2021-01-01

この記事はMicrosoft Azure Cognitive Services Advent Calendar 2020の21日目の記事です(大遅刻)。
RubyをやっててAIによる画像分析を簡単な形で使ってみたいな、という初心者向けの記事になります。

FaceAPIとは

Microsoft Azureの提供する構築済みAIによる人間の特徴分析機能です。
AWS,GCP等各社がクラウドベースのAIを提供する中で私がこのサービスを選定したのはデフォルトで「年齢・性別」の機能を使えるからです。

Ledgeのまとめ記事が大変参考になりました。->顔認識・顔検出とは?6つの顔認識APIの機能・精度・価格を比較!|Ledge.ai

FaceAPIのデモページがこちらにあるのでどういったパラメータが取得できるのか気軽に試せます。
image.png

ちなみに以前は右側のレスポンス欄の"faceattributes"に年齢と性別が返ってきていたのですが最近(要出典)はnullが返ってくるようになってますね。

利用準備

こちらからAzureの登録をしてきましょう。
すでにOffice365などでメールアドレスを取得されてる方はフローが少し楽になるのかしら?(未確認)

登録してきたらFaceAPIを使うためのサブスクリプションキーを発行します。

Azureのポータルに移動して「新しいリソースを作成」します。

新規リソースの作成画面はこのようになっていて、
image.png
件の FaceAPI用のエンドポイント作成は矢印の先の「Face」から行います。

画面の指示にしたがって

  • リソースグループ (使いたいサービス:この場合FaceAPI)
  • リージョン (多くの場合東日本と西日本になると思いますが、リージョンごとにそれぞれエンドポイントが変わります。)
  • 名前 (一意でユニークなものにしましょう)
  • 価格レベル (Freeで多くの場合十分だと思います。価格設定は詳細から確認してください。)

を設定し、「確認と作成」を押したら流れで作成できます。

image.png

作成したら先ほどのポータルのホームに戻ると設定した名前でリソースが作成されています。

image.png

これをクリックすると、各種設定画面に移ります。
キーとエンドポイントタブをクリックするとAPIにリクエストを飛ばすためのキーが確認できます。
このページで表示されるエンドポイントは今回は使いません。

image.png

RubyでAPIをコールする

検索上位でヒットする日本語ドキュメントにはPython,C#,GoおよびREST (curl)でのサンプルしか載っていませんが、Cognitive Servicesのページを深掘りするともう少し多くの言語でのサンプルが載ってるドキュメントがあります。

ページ下部に以下のような部分があるのでこちらをコピペしてそのまま骨組みになります。
image.png

全文がこのようになってます。

Rubyのサンプル

require 'net/http'

uri = URI('https://japanwest.api.cognitive.microsoft.com/face/v1.0/detect')
uri.query = URI.encode_www_form({
    # Request parameters
    'returnFaceId' => 'true',
    'returnFaceLandmarks' => 'false',
    'returnFaceAttributes' => '{string}', #ここを変える①
    'recognitionModel' => 'recognition_03',
    'returnRecognitionModel' => 'false',
    'detectionModel' => 'detection_02', #ここを変える②
    'faceIdTimeToLive' => '86400'
})

request = Net::HTTP::Post.new(uri.request_uri)
# Request headers
request['Content-Type'] = 'application/json'
# Request headers
request['Ocp-Apim-Subscription-Key'] = '{subscription key}' #ここを変える③
# Request body
request.body = "{body}" #ここを変える④

response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
    http.request(request)
end

puts response.body

コード中の「ここを変える」の部分を変えると今回の目的である「年齢と性別」をレスポンスとして得られるようになります。

どんなリクエストを飛ばしたいか

それぞれの値を変える解説をする前に、「Curl」のサンプルを見てもらうとわかりますが、APIに投げるリクエストはuriの形をとります。
サンプルドキュメントにはこの記事の冒頭で触れたデモのようなコンソールが用意されていて、こちらでCurlで投げるuriの作成ができます。

先に載せたRubyのコードではuri.queryの中身にクエリパラメータとして各種文字列を入力しています。

それを踏まえて、実際に送られるuriは以下のようになります。

https://japanwest.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&recognitionModel=recognition_03&returnRecognitionModel=false&detectionModel=detection_01&faceIdTimeToLive=86400

なおこのパラメータもコンソールのページで実際にリクエストとして投げられて正しい値を入れると200 okが返ってきます。

また、指定するエンドポイントとしてjapanwest.api.cognitive.microsoft.comとしていますが、東日本リージョンを指定した場合はjapaneast.api.cognitive.microsoft.comとなります。

ここを変える①

'returnFaceAttributes' => '{string}'

このFaceAttributesにはレスポンスとして返したい(=分析したい属性)を入力します。

例えば「年齢と性別」を返したい場合、

'returnFaceAttributes' => 'age,gender'

とすると良いでしょう。
なお他にはaccessoriesを指定すればマスクやメガネをつけているか否かが、makeupを指定すればお化粧をしているかすっぴんか否かが返ってきたりします。詳しくはドキュメントを読みましょう。

ここを変える②

'detectionModel' => 'detection_02'

上記のdetection_02detection_01に変えます。

感情分析や年齢等の識別機能を使うには、同じクエリパラメータのrecognitionModelrecognition_03を指定してつかいますが、現時点では新しい人の顔の検出モデルであるdetection_02recognition_03に対応していません。そのためdetection_01をつかいます。

ここを変える③

request['Ocp-Apim-Subscription-Key'] = '{subscription key}'

Ocp-Apim-Subscription-Keyとして指定するのは利用準備の項目で触れた「キー1」で、これをsubscription keyとして使います。
ローカルで動かすだけであればそのまま書いても差し支えないと思いますが、リモート上のリソースとするのであればyamlファイルに記述したり環境変数を管理できる仕組みを入れた上でファイルの外に参照できるようにしておくことをお勧めします。

以上で下準備は終わりです。

ここを変える④

request.body = "{body}"

bodyには画像のURL、またはバイナリとして展開したjpegなどが指定できます。
今回の例ではサンプルとしてPR Timesさんの記事より、Matzとロケッタ社のお二人(鳴瀬さんと清水さん)が写っている画像をお借りしてきます。

image.png

画像のアドレス:https://prtimes.jp/i/35716/3/resize/d35716-3-604425-6.jpg

ローカルにあるファイルを送信する場合は

Ruby
file_path = ARGV.shift
file_data = File.open(file_path, "r+b")
request.body = file_data.read
file_data.close

のように記述すると良いかと思います。

どんなレスポンスが返ってくるか。

以上の準備を整えた上で、ローカルでソースコードを実行すると、

リクエストがjson形式で返ってきて、hashとしてパースすると、

{"faceId"=>"a7d7d489-b657-4149-a2d8-e7b1b8af9aa5", "faceRectangle"=>{"top"=>69, "left"=>438, "width"=>62, "height"=>62}, "faceAttributes"=>{"gender"=>"male", "age"=>33.0}}
{"faceId"=>"b07990e7-d0b3-4030-bd2a-41bbcf86de7d", "faceRectangle"=>{"top"=>71, "left"=>126, "width"=>58, "height"=>58}, "faceAttributes"=>{"gender"=>"male", "age"=>23.0}}
{"faceId"=>"26876e61-d6fb-482c-b43b-3e7d4410df52", "faceRectangle"=>{"top"=>93, "left"=>286, "width"=>57, "height"=>57}, "faceAttributes"=>{"gender"=>"male", "age"=>44.0}}

のような形で得られます。

人間の顔がDetectされた位置情報もついでに取得できているのでこれらをもとに矩形を描画すると以下のようになります。

generated14.png

matzの年齢は44才と撮影当時で10才前後若く出ていました。
う〜〜ん、エンジニアはやはり見た目が若い人が多い...

その他のポイント

多かれ少なかれ、学習を行ったデータセットによってバイアス生じます。
画像認識、および機械学習が私の専門ではないのとドキュメントやテクニシャンからの評価を深掘りできていないのですが、あるいはrecognitionモデルにも人種的なモデルの偏りがあれば、東アジア系の顔立ちだと年齢が若く出る傾向があったりするかも?
また、性別は男女の二値ではありますが、髪が長く輪郭を隠した男性が女性として判別されやすかったりする例もあります。
これらは推程度を百分率で返したりもできるので、上手に使ってAIでの判別を行えるようになれば新たな知識を得るきっかけになると思います。

終わりに

この手のプラットフォームはUIをはじめ提供サービスの詳細が割と頻繁に変わりますのでできるだけ最新情報を探されることをお勧めします。(釈迦に説法)

Githubにサンプルとドキュメントが用意してありますのでこちらも参考にしてみてください。

記事内で使わせていただいた画像サンプルはこちらからお借りしてきました。
URL: https://prtimes.jp/main/html/rd/p/000000003.000035716.html
著作権や肖像権は全て元画像の権利者に帰属します。

Ruby3.0.0リリースおめでとうございます!!!(2020/12/25)

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2