[アイマス駆動開発]アイマスガールズの顔写真分析機能をサーバーレス開発

元記事はこちら→[[アイマス駆動開発]アイマスガールズの顔写真分析機能をサーバーレス開発](https://k1-style.net/2017/12/imasgirls_photo_rekognition_serverless/)


この記事は<a href="https://adventar.org/calendars/2130" target="_blank">アイドルマスター Advent Calendar 2017</a>と
<a href="https://qiita.com/advent-calendar/2017/aws-lambda" target="_blank">AWS Lambda Advent Calendar 2017 - Qiita</a>の13日目の記事です。

## アイマス駆動開発とは

下記のスライドで提起されております。要はアイマスが好きな気持ちをトリガーにして何か作ろうぜ！って感じです。

<iframe src="//www.slideshare.net/slideshow/embed_code/key/iQWkYuX9Pjpncv" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/treby/imas-driven-developemnt" title="アイマス駆動開発 #shinjukurb" target="_blank">アイマス駆動開発 #shinjukurb</a> </strong> from <strong><a href="https://www.slideshare.net/treby" target="_blank">treby</a></strong> </div>

ちょうど今勤めている会社の関係でAWSの勉強をしており、ただ勉強するのもつまらないので自分が愛してやまないアイマスのネタを使って何か作ろうと思い立ちました。

## 今作っているもの

ということで、タイトルにある通り **「<a href="http://dic.nicovideo.jp/a/%E3%82%A2%E3%82%A4%E3%83%9E%E3%82%B9%E3%82%AC%E3%83%BC%E3%83%AB%E3%82%BA" target="_blank">アイマスガールズ</a>の顔写真分析機能」** というものを作っております。

"作っております"と現在進行形で敢えて言ってますが、まだ一般公開はしておりません。今の状態で色んな人に乱用されると色々困るので。。

ソースコードは公開します。AWSアカウント持ってる人で興味を持たれた方はご自分の環境で設置して使ってみてください！リファクタとか要望とかPR大歓迎です。

<a href="https://github.com/K1-Style/imasgirls-photo-rekognition" target="_blank">GitHub:K1-Style/imasgirls-photo-rekognition</a>

### どんな機能？

1. アイマスガールズがTwitterに上げた写真を収集
2. 収集した写真から顔写真情報を分析・抽出
3. 顔写真の照合

![システム全体像](https://qiita-image-store.s3.amazonaws.com/0/100077/2a8b2784-ae3b-92e2-660a-2cb05d9ea5d9.png)

Webサービスとして皆さんに使っていただくとしたら**顔写真照合**がその機能にあたります。イメージとしては以下の通り。

この画像を送ったら↓

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">【アイドルマスター シンデレラガールズ 6th Anniversary Memorial Party】ご来場誠にありがとうございました！本日の発 ...→→ <a href="https://t.co/LKfpnSENYk">https://t.co/LKfpnSENYk</a> <a href="https://twitter.com/hashtag/idolmaster?src=hash&amp;ref_src=twsrc%5Etfw">#idolmaster</a> <a href="https://t.co/c8AUlnHqMc">pic.twitter.com/c8AUlnHqMc</a></p>&mdash; アイドルマスター公式ツイッター (@imas_official) <a href="https://twitter.com/imas_official/status/932202401305522176?ref_src=twsrc%5Etfw">2017年11月19日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

事前に顔情報登録しておいた中から近い画像を返してくれるようなサービスを想定してます。

例えば、上記の集合写真だと乙倉悠貴役の中島由貴さんがいらっしゃるので、事前にtwitterで収集した中から「この人いますね！」って感じで以下の情報が返ってきたり↓
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">午後も頑張るぞーーー(*´◒`*) <a href="https://t.co/UaLNtp5161">pic.twitter.com/UaLNtp5161</a></p>&mdash; 中島由貴❄ (@Yuki_Nakashim) <a href="https://twitter.com/Yuki_Nakashim/status/940065025556824064?ref_src=twsrc%5Etfw">2017年12月11日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

高森藍子役の金子有希さんもいらっしゃるので、こんなのとかも返ってくることを想定してます↓

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">例のイタリア写真あげるよー！<br><br>謎に高確率で赤いおじさんが写りこむ(笑)素敵な町だったー！！<a href="https://twitter.com/hashtag/Italy?src=hash&amp;ref_src=twsrc%5Etfw">#Italy</a> <a href="https://twitter.com/hashtag/%E3%82%A4%E3%82%BF%E3%83%AA%E3%82%A2?src=hash&amp;ref_src=twsrc%5Etfw">#イタリア</a> <a href="https://t.co/RPOxmU4nKm">pic.twitter.com/RPOxmU4nKm</a></p>&mdash; 金子 有希 シーズン2 (@kanekosanndesu) <a href="https://twitter.com/kanekosanndesu/status/938378990758240258?ref_src=twsrc%5Etfw">2017年12月6日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

特に、アイマスは好きだけど声優にそんなに詳しくなくて、こういった集合写真って誰がどの人か分からない！なんて方もいると思います。そんなあなたにうってつけ！なサービスに出来るといいなぁと思って日々開発を続けております。

<a href="https://aws.amazon.com/jp/about-aws/whats-new/2017/11/amazon-rekognition-announces-real-time-face-recognition-text-in-image-recognition-and-improved-face-detection/" target="_blank">Amazon Rekognitionが先日のアップデート</a>で、最大１００人の集合写真でも全員の顔検出ができるようになったらしいです。で、今回の開発に思い立ったわけです。

## 技術解説

### 0. インフラ、開発環境

上記の図にもある通り、AWSの各種サービスを使っています。Rekognition以外は<a href="https://serverless.com/" target="_blank">Serverless Framework</a>を使って構築しています。

詳細や導入方法については<a href="https://github.com/K1-Style/imasgirls-photo-rekognition/blob/master/README.md" target="_blank">GithubのREADME</a>にて。

* <a href="http://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/WhatIsCloudWatchEvents.html" target="_blank">Amazon CloudWatch Events</a>  
１時間に１回twitterから画像収集するためのトリガーとして利用。
* <a href="https://aws.amazon.com/jp/lambda/" target="_blank">AWS Lambda</a>  
サーバーサイドのプログラム実行環境。顔写真収集・顔情報登録／照合のメインプログラムをここで動かす。
* <a href="https://aws.amazon.com/jp/s3/" target="_blank">Amazon S3</a>  
ストレージサービス。twitterから収集した画像の置き場所。
* <a href="https://aws.amazon.com/jp/api-gateway/" target="_blank">Amazon API Gateway</a>  
WebAPI管理ができるサービス。顔認証照合APIの受け口として利用。
* <a href="https://aws.amazon.com/jp/rekognition/" target="_blank">Amazon Rekognition</a>  
画像内の背景や人物などの情報を検出、識別できるサービス。

あと、上記の図には載せてませんがLambdaの各プログラムの実行ログを<a href="http://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html" target="_blank">Amazon CloudWatch Logs</a>に保存し、もしエラーとか出た場合に解析出来るようにしております。

この辺りのサービスを、プログラムも含めてコマンド一発で構築できるServerless Framework便利です。

### 1. アイマスガールズがTwitterに上げた写真を収集

アイマスガールズのtwitterアカウントを予めリスト化して、そのリストのタイムラインから毎時拾ってきます。

リストはこちら↓  
<a href="https://twitter.com/k1_style/lists/imasgirls" target="_blank">@k1_style/imasgirls</a>

この人いないじゃんか！っていうお声もあるかと思います。気づき次第随時追加中です。

処理内容としてはざっと以下の通り。

* CloudWatch Eventで1時間おきにLambdaを実行
* Lambdaでは、TwitterAPIを利用して上記リストのタイムラインを取得(<a href="https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-statuses" target="_blank">GET lists/statuses</a>を使用)
* タイムラインで画像投稿が存在する場合は、その画像をダウンロードしてS3バケットへ保存
* タイムラインで取得した最新のツイートIDをあわせてS3へファイル保存。次の実行ではこのIDより後のツイートを取得

### 2. 収集した写真から顔写真情報を抽出

1で画像が保存されたら、それをトリガーに写真に写っている顔情報をRekognitionで分析し、情報抽出出来たらそれをRekognitionのコレクションへ登録します。

* S3へファイルが保存されたタイミングで、Lambdaを実行
* 保存された画像から顔情報抽出するRekognitionのAPI(<a href="http://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/howitworks-index-faces.html" target="_blank">IndexFaces</a>)を実行  
→顔情報抽出できればそのままコレクションへ登録  
→顔情報抽出できない場合は何もしない
* （おまけ）S3のファイルが削除された場合、そのファイルに紐づく顔情報がある場合はコレクションからも削除

### 3. 顔写真の照合

手持ちの写真を送り、2で抽出した顔写真情報に近い人物が写っているかどうかを判定、その情報をjson形式で返します。

* API Gatewayで作成したURI宛にアイマスガールズが写っている（かもしれない）画像をPOSTする
* POST内容をLambdaに送り、Rekognitionで顔写真照合(<a href="http://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/how-it-works-storage-based.html" target="_blank">SearchFacesByImage</a>)をかける
* 結果が出た場合は、その内容をそのままjsonとして返す

画像POST方法はこんな感じで↓

```
$ curl -H "Content-Type: image/jpeg" --data-binary "@<画像ファイルパス>" -X POST <API Gatewayで作成したエンドポイントURIドメイン>/dev/match_faces
```

レスポンスjsonはこんな感じ↓

```json

{
  "result": "OK",
  "matchedFaces": [
    {
      "Similarity": 78.88072967529297,
      "Face": {
        "FaceId": "48d9d926-9163-47f6-a2f6-5c3f6bfef00b",
        "BoundingBox": {
          "Width": 0.046875,
          "Height": 0.03515620157122612,
          "Left": 0.29166701436042786,
          "Top": 0.40625
        },
        "ImageId": "1aa12926-0f98-5413-b5af-266ad564c10d",
        "ExternalImageId": "939154187413159936_kanekosanndesu_0.jpg",
        "Confidence": 99.99849700927734
      }
    },
    {...}
   ],
  "stackTrace": null
}
```
`ExternalImageId`がS3で保存された元の写真ファイル名となります。

その他のレスポンス情報については公式のドキュメントを参考にしてみてください。
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#searchFacesByImage-property

## 今後実現したいこと

まずは、この顔写真照合機能を一般公開できるようにしたいのですが、
そのためには以下のことが最低限必要かなぁと考えてます。

### 分かりやすいUI

今はただjsonとして返してるだけで、パッと見なんのこっちゃ分からん情報が並んでるだけです。自分が送った画像と、Twitterから拾ってきた画像の比較を分かりやすく表示してくれるような画面があると良いかなぁと。

### テスト整備

現状はソースコードをご覧いただくとわかりますが、twitterのAPIで返ってきたものから画像取得できるかどうかをするテストがあるのみです。その後はAWSにデプロイ→確認→修正→デプロイ→確認…、とひとまず繰り返してきただけでした。

Webサービスを公開しちゃうと修正したけど動作保証が無いものをおいそれと公開できなくなるため、リファクタとか機能改善とか定期的に行うには、繰り返し開発環境で確認できるテストを用意しておかないといかんですね。

### API実行はセキュアに

冒頭でも申しましたが、あまり乱用はされたくないので、公開する際もこちらが想定する適切な利用方法以外はAPI実行受け付けないようにしたいなあと思ってます。AWSのAPI GatewayやIAM、Cognitoをうまいこと使えばその辺り実現できるかも？引き続き調査勉強中でございます。

### エラー検知

CloudWatchでログ保存してますが、エラーが出てるかどうかは今のところAWSのコンソール画面を見ないと分かりません。いちいちコンソール画面開くのも手間なので、Slackやメールなどで知らせてくれる機能もあると良いですね。

## 参考情報

* <a href="https://serverless.com/framework/docs/providers/aws/" target="_blank">Serverless - AWS Documentation</a>
* <a href="http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html" target="_blank">Class: AWS.S3 — AWS SDK for JavaScript</a>
* <a href="http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html" target="_blank">Class: AWS.Rekognition — AWS SDK for JavaScript</a>
* <a href="http://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/how-it-works-storage-based.html" target="_blank">ストレージベースの API オペレーション: 顔の保存および一致する顔の検索 - Amazon Rekognition</a>
* <a href="https://qiita.com/OMOIKANESAN/items/c5d1dfe5c00105739dcf" target="_blank">Amazon Rekognitionで顔認証してみた - Qiita</a>

以上です。皆さん引き続き良きアイマスライフとAWSライフをお楽しみください。