Hatena::ブログ(Diary)

盆栽日記

2017-04-02

集合写真のメガネの数をカウントする

こんな話がある。

実際、昨晩開催されたGlobal TokyoRの集合写真においてもメガネが目立つ(ゲストスピーカーのHenningさんの記事参照)。

https://henningsway.github.io/post/2017-04-01-tokyo-r/

ということで集合写真からメガネ着用率を算出したい。

今回はMicrosoft Face APIを用いて集合写真から顔検出&メガネ着用の有無を判定したいと思う。

以下のステップで進める。

  • ローカルの画像を画像サーバ(imgur)にアップロードする
  • 画像をMicrosoft FACE APIにPOSTして結果を取得する
  • 結果を集計する

ローカルの画像を画像サーバ(imgur)にアップロードする

上記サイトの集合写真をFace APIにそのまま送ると、一つ一つの顔が小さすぎて顔検出に失敗する。

したがってローカルにいったんダウンロードし、引き延ばした画像を用いることにする。

ただし、Face APIはウェブ上の画像を対象としているため、ローカルの画像についてはいったんどこかの画像サーバにアップロードする必要がある(追記)指定を変えることで画像サーバにアップロードする必要はないとのこと。詳しくはuriboさんの記事を参照ください。

今回は一時的にimgurにアップロードしてメガネ着用率を算出後に消去することにする。

imgurにはimguRパッケージを用いてアップロードする。

結果のlinkにアップロード先のURLが格納されている。

# ローカルの画像を画像サーバ(imgur)にアップロードする
library("imguR")
tmp <- "oretachinoglobalr.png" # 引き延ばした画像
res_upload <- upload_image(tmp) 
url_image <- res_upload$link

画像をMicrosoft FACE APIにPOSTして結果を取得する

先の画像URLをMicrosoft FACE APIにPOSTして、結果を取得する。

この際、Subscribe Keyが必要なので取得しておいてほしい。

このあたりの記事を参照のこと。

POSTにはhttrパッケージを用いる。

# 画像をMicrosoft FACE APIにPOSTして結果を取得する
library("httr")
MS_FACE_KEY <- "取得したSubscribe Key"
url_request <- "https://westus.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses,emotion"
body <- list(url=url_image)
res <- POST(url=url_request,
            encode="json",
            body=body,
            add_headers(`Ocp-Apim-Subscription-Key`=MS_FACE_KEY),
            content_type_json()
)
res <- content(res)

結果を集計する

結果はcontent()でJSONからRのリストに変換されている。

この結果を集計する。

集計後はアップロードした画像を消去する。

この際、imguRパッケージのdelete_image()にdeletehashを指定する。

# リストで返ってくる結果を集計する
count_megane <- table(unlist(lapply(res,function(x)x$faceAttributes$glasses)))
# アップロードした画像を消去する
delete_image(res_upload$deletehash)

結果は以下の通り。

Face APIではメガネとして noGlasses、readingGlasses、sunglasses、swimmingGoggles の4つを判定可能である。

メガネ着用率は43.8%という結果になった。

この数字が高いか低いかわからないので、外国の集合写真などと比較してみる必要があるだろう。がんばってほしい。

> count_megane

     NoGlasses ReadingGlasses 
            18             14 
> round(prop.table(count_megane) * 100, 1)

     NoGlasses ReadingGlasses 
          56.2           43.8

まとめると、以下のようなコードになる。

# ローカルの画像を画像サーバ(imgur)にアップロードする
library("imguR")
tmp <- "oretachinoglobalr.png" # 引き延ばした画像
res_upload <- upload_image(tmp) 
url_image <- res_upload$link

# 画像をMicrosoft FACE APIにPOSTして結果を取得する
MS_FACE_KEY <- "取得したSubscribe Key"
url_request <- "https://westus.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses,emotion"
body <- list(url=url_image)
res <- POST(url=url_request,
            encode="json",
            body=body,
            add_headers(`Ocp-Apim-Subscription-Key`=MS_FACE_KEY),
            content_type_json()
)
res <- content(res)
count_megane <- table(unlist(lapply(res,function(x)x$faceAttributes$glasses)))

# アップロードした画像を消去する
delete_image(res_upload$deletehash)

count_megane
round(prop.table(count_megane) * 100, 1)

余談だが、当初はGoogle Cloud Vision APIでやろうかと思っていた。

しかしメガネの着用有無が判定できないのでやむなくMicrosoft FACE APIを用いた。

Enjoy!

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。

トラックバック - http://d.hatena.ne.jp/dichika/20170402/p1