Microsoft Azure Advent Calendar 2015 の20日目の記事です。
今回はProject Oxfordを使って三倉姉妹(マナカナ)の判別を行いたいと思います。
三倉姉妹とは?
三倉姉妹とは、三倉茉奈と三倉佳奈の双子の女優・タレント・歌手です。
通称マナカナと呼ばれている人たちです。
「左がマナで、右がカナ。」という言葉が出来るほどに判別は難しく、人類がこれまで幾度と無く挑戦し失敗し諦めてきた大きな課題です。
準備としては、
まずBing Search APIを利用してマナカナの画像を集め、
blog.tottokug.com
Project OxfordのFace APIを使ってかおの画像を切り出しました。
blog.tottokug.com
今日はついにマナカナを判別する所を実装していきます。
実装するは言い過ぎました。実装は特にしません。
Project Oxfordの機能を使って、
といった感じに、Face APIに全てを任せます。
マナカナ判別用教師データの作成。
今回使うのもProject OxfordのFace APIです。
Face APIを使いはじめるところまでは、前回のマナカナの画像からProejctOxfordとimagemagickで顔を切り出す。 - かれ4で書いた通りで、
今回はここからさらにマナカナをマナとカナに分類することをしていきます。
今回は顔を切り出す必要はないので、ImageMagickは使わずにただBounding Boxを一覧化するところまでをおこえば良いのかなと。
気をつけないと行けないのはfaceAPIは秒間1回くらいの利用しか認めておらず、それを超えるとエラーが帰ってくるので要注意です。
なので、sleep 1などを入れて1秒待機させる事にすると回避出来るので、スリープはぜひ入れましょう。
IFS='
'
APIKey=***************************************
[ -d images/detected ] || mkdir -p images/detected
for f in $(find ./images/manakana -type f);
do
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @${f} \
"https://api.projectoxford.ai/face/v0/detections?subscription-key=${APIKey}" \
|jq -r ".[] | [\"$f\",.faceId,.faceRectangle.width,.faceRectangle.height,.faceRectangle.left,.faceRectangle.top] | @csv" >> faceindex.csv
mv "${f}" images/detected/
sleep 1
done
これで faceindex.csvに下記のような
画像ファイル名,faceId,幅,高,x,y
という形式でのCSVファイルが吐き出せました。
"./images/manakana/00011738_02A.jpg","a6415064-2720-4c84-8dff-7701f006f36d",81,81,123,93
"./images/manakana/00011738_02A.jpg","3d957436-a206-4d78-839a-bc0174345f77",77,77,546,144
"./images/manakana/00011738_02A.jpg","2bf5f7dd-c9c5-45e5-acab-6a58b13da0ad",75,75,415,136
"./images/manakana/000504.jpg","0913d773-c52f-45f4-8dce-16ba86b26d42",115,115,28,75
"./images/manakana/001-199x300.jpg","94f18b64-1faf-425f-a064-1a203b8c4140",42,42,87,26
"./images/manakana/001-199x300.jpg","fc8407f4-4722-4e58-ad10-f5e1d1efb733",39,39,34,54
"./images/manakana/001.jpg","87de0b21-ee19-4072-bf7d-b6d14895578c",76,76,96,104
"./images/manakana/0014d0d9.jpg","ca4d66a1-2243-44ac-b084-c1703d419ff6",133,133,145,368
"./images/manakana/0014d0d9.jpg","7a71404c-81b3-4562-8f24-3d78e455b480",122,122,419,370
"./images/manakana/001l.jpg","a967b8e8-a50d-43be-beb7-5d718e0577bd",90,90,199,89
この処理はスリープが入っているので、時間がかかります。
待っている間に、先にPersonGroupの作成とPersonの作成をしてしまいます。
どちらも、繰り返し行う動作ではないのでブラウザでさくっとやってしまいます。
API Referenceから実行出来るようになっているので、そこから実行します。
最近API Referenceから実行出来るようなのが増えていますね。
Person Groupの作成
Personができていることの確認
学習させる
ここまでで準備は整ったので、ついに学習させていくことになります。
学習させるためには、Face APIのPersonにあるAdd Faceを利用してまずは顔を登録していきます。
今回は顔を検出した結果、2人で写っているものだけを学習用に使い、1人もしくは3人以上で写っている画像を検証用に使います。
2人で写っているものを使う理由として、マナカナには「左:マナ、右:カナ」というルールがあるためです。
ここが今回一番大切な所です。
他にもカナの左目の下にほくろがあるとか、鼻の穴の角度が違うとかそんな見分け方も有りますが、それは今回は使いません。
大切な事なので、もう一度。
「左がマナで、右がカナです。」
言い換えると、Bounding BoxのLeftの値が小さい方がマナ、大きい方がカナです。
というわけで、2人で写っている画像を探し出してきてその画像と一緒に、顔の位置の情報を送ります。
IFS='
'
APIKey=**************************************
personGroupId="manakana"
mana="4314b829-559c-4350-81d5-7bb24b4041e7"
kana="6eb1744b-a7e6-4782-acb4-6a35ec74a8a1"
for file in $(cat faceindex.csv|cut -d',' -f1 |sort |uniq -c |grep "^\s*2"|perl -pe "s|.*images/manakana(.*?)\"|images/detected\1|g ");
do
personId=$mana
for bb in $(cat faceindex.csv |grep "${file##*/}" |perl -pe "s|.*,(\d+),(\d+),(\d+),(\d+)|\3,\4,\2,\1|g")
do
echo "========="
target=$bb
eretry=1
while :
do
URL="https://api.projectoxford.ai/face/v1.0/persongroups/${personGroupId}/persons/${personId}/persistedFaces?targetFace=${target}"
faceId=$(curl -X POST "$URL" \
-H "Content-Type: application/octet-stream" \
-H "Ocp-Apim-Subscription-Key: ${APIKey}" \
--data-binary @./${file} \
)
if [ ! -z "$(echo $faceId |grep RateLimitExceeded)" ]
then
eretry=$(expr "$eretry" + "$eretry" )
echo "retry ${eretry} sec ago"
sleep ${eretry}
continue
fi
echo "$file,$faceId,$bb" >> registIndex.csv
break;
done
personId=$kana
sleep ${eretry}
done
done
ここで指定している
mana="4314b829-559c-4350-81d5-7bb24b4041e7"
kana="6eb1744b-a7e6-4782-acb4-6a35ec74a8a1"
はpersonを作った時に付与されたPersonIdになっています。
また、このAPIは1秒のSleepを入れても、RateLimitExceededが出てしまうので、出てしまった場合は1秒、2秒、4秒と増やしながらリトライする処理が入っています。
ひとまずこれで顔の登録が完了しました。
学習の結果確認
こちらも繰り返し行うものではないので、ブラウザ上で確認します。
無事に成功しているようです。
今回顔画像をそれぞれ250枚ほど登録していますが、
約1分程度でステータスはSucceededになっていました。
検証
それではドキドキのマナカナが見分けられるかどうかのテストになります。
テストにはファイルを指定して、そのままどっちなのか判定出来るように以下のスクリプトを使います。
IFS='
'
APIKey=****************************************
faceId=$(curl -s -X POST "https://api.projectoxford.ai/face/v1.0/detect?returnFaceId=true" \
-H "Content-Type: application/octet-stream" \
-H "Ocp-Apim-Subscription-Key: ${APIKey}" \
--data-binary @${1} \
| jq -r .[].faceId)
echo "FACE ID = $faceId"
curl -s -X POST "https://api.projectoxford.ai/face/v1.0/identify" \
-H "Content-Type: application/json" \
-H "Ocp-Apim-Subscription-Key: ${APIKey}" \
--data-ascii "{\"personGroupId\":\"manakana\",\"faceIds\":[\"${faceId}\"],\"maxNumOfCandidatesReturned\":1 }" \
| jq -r '.[].candidates[] |[.personId,.confidence] | @csv' \
|perl -pe "s/4314b829-559c-4350-81d5-7bb24b4041e7/mana/g; s/6eb1744b-a7e6-4782-acb4-6a35ec74a8a1/kana/g"
マナの判定
ではまずは、こちらの画像から
$ ./identify.sh images/detected/mikuramana.jpg
FACE ID = efd9608a-b6ff-47a9-84cc-4107f9789d2d
"mana",0.6302
無事にmanaと判定されました。
カナの判定
次に,この画像から、kanaと判別されれば成功です。
$ ./identify.sh images/detected/kana.jpg
FACE ID = 6ff3601d-a2f6-4ba5-81e0-0e6a39df2a16
"kana",0.73804
無事に認識されました。
これで、マナカナを見分ける事が出来るようになりました。