RaspberryPIを使って、Amazon Rekognitionの画像認識を試してみた

# 概要

偶然、RaspberryPI Model 3が手に入ったので、転がっていたUSBカメラを利用して、
外出中のハムスター達の画像をSlackに投稿するシステムを作ってみました。

https://github.com/n-someya/rekog-hamster

# 構成

![aws-rok-rasp.png](https://qiita-image-store.s3.amazonaws.com/0/26693/93cce5a1-a3cb-ef0d-2ebf-2f3949b5060d.png)

# USBカメラから画像取得

raspberry piなのでカメラモジュールかと思いきや、普通のUSBカメラを使います。

## デバイス認識

特に何も考えず、USBを接続するだけで認識されるはずです。
認識されたかを確認するには、`lsusb`コマンドを実行します。
下は、私の環境の例です。
1行めでカメラデバイスが認識されてます。（Logitechのカメラを使っているので`Logitech`と出力されています）

```
$ sudo lsusb
Bus 001 Device 004: ID 046d:0826 Logitech, Inc.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

## Pythonプログラムからの画像(動画)取得

色々方法はあると思いますが、私はOpenCVを使いました。
（画像処理も簡単にできるし）

特にバージョンにこだわりがないなら、以下のコマンドでOpenCVがインストールされPythonから利用できます。
入るバージョンは、2.4です。

```bash
sudo apt-get install libopencv-dev python-opencv
```
これで、以下のようにPythonからUSBカメラの画像を取得できるようになります。

```py
# -*- coding: utf-8 -*-
import cv2
# OpenCVを利用してWebカメラからのキャプチャ準備
cap = cv2.VideoCapture(0)
# Webカメラから画像読み込み
ret, frame = cap.read()
```

# Amazon Rekognitionを使った画像認識

:warning: Amazon Rekognitionの利用には無料枠がありますが、利用の仕方によっては、利用料が発生するケースがあります。
[AWSのページ](https://aws.amazon.com/jp/rekognition/pricing/)などから利用料金をしっかり確認しましょう。


## AWS PythonSDKのインストールと利用準備

AWSのPythonSDKをインストールします。

```bash
sudo pip install boto3
```

`~/.aws/credentials`というファイルを用意し、
AWSのクレデンシャルを記載します。

```
[default]
aws_access_key_id = ****
aws_secret_access_key = ****
region = us-west-2
````
これで、PythonSDKからAWSにアクセス可能となります。

## AWS Rekognitionの利用

boto3からAWS RekognitionのDetect Labels APIを呼び出します。

Detect Labels APIは画像が入力されると、
画像に含まれるオブジェクトの名前(=Label)一覧と、
そのオブジェクトが本当に画像に含まれているかの確度が返却されます。

注意点としては、AWS側は画像データをbytearray型で受け取るので、
OpenCV側でndarray型となっているデータを変換する必要がある点でしょうか。

```py
import boto3

client = boto3.client('rekognition')

# awsに送信するためndarrayとなっている画像をpngのbytearrayに変換
ret, data = cv2.imencode('.png', frame)
byte_data = bytearray(data)

# Amazon rekognitionを呼び出し
response = client.detect_labels(
    Image={
        'Bytes': byte_data
    },
    MaxLabels=50
)
print(response)
```

レスポンス例:

```
{u'Labels': [
{u'Confidence': 66.29442596435547, u'Name': u'Animal'}, 
{u'Confidence': 66.29442596435547, u'Name': u'Hamster'},
{u'Confidence': 66.29442596435547, u'Name': u'Mammal'},
{u'Confidence': 66.29442596435547, u'Name': u'Rodent'}],
'ResponseMetadata': {'RetryAttempts': 0, 'HTTPStatusCode': 200, 'RequestId': '***', 
'HTTPHeaders': {'date': 'Fri, 12 May 2017 06:20:06 GMT', 'x-amzn-requestid': '***', 'content-length': '244', 'content-type': 'application/x-amz-json-1.1', 'connection': 'keep-alive'}}, 
u'OrientationCorrection': u'ROTATE_0'}
```

あとはレスポンスデータの`Labels`を判定すれば、物体認識が実現できます。
私は、以下のように`Hamster`ラベルが存在するかをチェックするようにしています。

```py
def exists_hamster(labels):
    '''
    From amazon rekognition detect label response,
    Detect exisiting hamster
    @return confidencial
    '''
    for label in labels:
        if label['Name'] == 'Hamster':
            return label['Confidence']
    return 0
```

# 動作結果

家のハムスター達に実験台となってもらいました。

撮影画像:

![hamster20170512152007_ok.jpg](https://qiita-image-store.s3.amazonaws.com/0/26693/f2ec30b6-788d-cf8d-de12-5d9796105acf.jpeg)

実行結果：

![hamster-slack.png](https://qiita-image-store.s3.amazonaws.com/0/26693/0a2cae54-40ce-e125-aff4-5c04f5402c4c.png)

みごと、Slackにハムスター画像が通知されました。