JavaScript
Node.js
TypeScript
ReKognition
serverless

Amazonの画像認識がトイプードルと唐揚げの違いを認識できるか検証した

過去、話題になった画像

sample.jpg

こちらはトイプードルでしょうか。それとも唐揚げでしょうか。
人間には難しい判断を迫られますね!Amazonの画像認識APIに判断してもらいましょう。

使用技術

  • AWS
    • S3
    • Lambda
    • Rekognition
  • Serverless Framework
  • Typescript

検証環境

スクリーンショット 2018-07-07 23.12.47.png

画像の解析にAmazon Recognitionを使用します。

以下の流れとなります。

S3に画像をアップロード

Lambda関数の実行

Amazon Rekognition(画像解析)

環境構築

ソースコードはServerless Frameworkに記述します。
aws-cliおよびyarnをインストールしている前提で解説します。もちろんnpmでもOKです。

あらかじめawsの認証情報を記録しておきます。
Access Keyなどの詳しい解説は省略します。

$ aws configure
AWS Access Key ID [None]: xxx
AWS Secret Access Key [None]: xxx
Default region name [None]: ap-northeast-1
Default output format [None]: text

serverlessをインストールします。

$ yarn global add serverless

serverlessをインストールしたらテンプレートを作成します。
今回はTypescriptを使用するためaws-nodejs-typescriptを選択します。

$ sls create -t aws-nodejs-typescript -p rekognition-typescript

Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/xxx/yyy/zzz/rekognition-typescript"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.27.3
 -------'

Serverless: Successfully generated boilerplate for template: "aws-nodejs-typescript"

まずはパッケージのインストールです。

$ yarn install

yarn install v1.6.0
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
warning Your current version of Yarn is out of date. The latest version is "1.7.0", while you're on "1.6.0".
info To upgrade, run the following command:
$ curl --compressed -o- -L https://yarnpkg.com/install.sh | bash
✨  Done in 13.01s.

aws-sdkも必要になるためインストールします。

$ yarn add -D aws-sdk @types/aws-sdk

yarn add v1.6.0
[1/4] 🔍  Resolving packages...
warning @types/aws-sdk@2.7.0: This is a stub types definition for aws-sdk (https://github.com/aws/aws-sdk-js). aws-sdk provides its own type definitions, so you don't need @types/aws-sdk installed!
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 9 new dependencies.
info Direct dependencies
├─ @types/aws-sdk@2.7.0
└─ aws-sdk@2.270.1
info All dependencies
├─ @types/aws-sdk@2.7.0
├─ aws-sdk@2.270.1
├─ ieee754@1.1.8
├─ jmespath@0.15.0
├─ sax@1.2.1
├─ url@0.10.3
├─ uuid@3.1.0
├─ xml2js@0.4.17
└─ xmlbuilder@4.2.1
✨  Done in 5.00s.

serverless.ymlはRekognitionの権限を追加し、S3からイベントを受け取るように修正します。

Serverless.yml
service:
  name: rekognition-typescript

# Add the serverless-webpack plugin
plugins:
  - serverless-webpack

provider:
  name: aws
  runtime: nodejs6.10

  region: ap-northeast-1

  iamRoleStatements:
      - Effect: "Allow"
        Action:
          - "rekognition:DetectLabels"
        Resource: "*"

functions:
  sample:
    handler: handler.sample
    events:
#      - http:
#          method: get
#          path: hello
      - s3: {バケット名}

そしてメインになるコードはhandler.tsに実装します。

handler.ts
import { S3CreateEvent, Callback, Context, Handler } from 'aws-lambda'
import { Rekognition } from 'aws-sdk'

export const sample: Handler = (event: S3CreateEvent, context: Context, cb: Callback) => {
  // S3にアップロードされたファイルを取得する
  const s3Record = event.Records[0].s3
  const params = {
    Image: {
      S3Object: {
        Bucket: s3Record.bucket.name,
        Name: decodeURIComponent(s3Record.object.key.replace(/\+/g, ' '))
      }
    }
  }

  // Rekognitionで解析する
  const rekognition = new Rekognition
  rekognition.detectLabels(params, (err, data) => {
    if (err) cb(err)
    else {
      const result = data.Labels.map(detail =>
        detail.Name + ":" + detail.Confidence
      ).join("\n")
      console.log(result)
      cb(null, result)
    }
  })
}

デプロイ

AWSにデプロイします。

$ sls deploy -v

()

Service Information
service: rekognition-typescript
stage: dev
region: ap-northeast-1
stack: rekognition-typescript-dev
api keys:
  None
endpoints:
  None
functions:
  sample: rekognition-typescript-dev-sample

実行

S3へのファイルアップロードがトリガーになりますので、serverless.ymlに記載したバケットから画像をアップロードします。
スクリーンショット 2018-07-08 0.04.15.png

今回はconsole.logで結果を出力していますので、CloudWatchからみてみます。
スクリーンショット 2018-07-08 0.06.36.png

結果

さて、結果ですが以下のようになりました。

Teddy Bear:98.77598571777344
Toy:98.77598571777344
Food:78.60242462158203
Fried Chicken:78.60242462158203
Airedale:60.78370666503906
Animal:60.78370666503906
Canine:60.78370666503906
Dog:60.78370666503906
Mammal:60.78370666503906
Pet:60.78370666503906
Terrier:60.78370666503906
Asleep:54.675662994384766

Teddy Bearと認識されているようですが、
FoodFried Chickenも数値が高いですね。
一方でAnimalDogの数値が60前後になっています。

こちらの画像はどうやら唐揚げなのかもしれません。

皆さんも様々な画像で検証してみてください。

サンプルコード

サンプルコードをアップしていますのでご自由に閲覧ください。
https://github.com/flatgela/rekognition-typescript