RekognitionとRaspberry piでペット監視

あけましておめでとうございます。犬バカの藤向(ふじさき)です。
去年末にAmazon Rekognitionという画像認識できるサービスがリリースしていたと聞きましたので、さっそく遊びました。
###### 作成の動機
人感センサ＋ラズパイを使った監視カメラは、以前から作られてますが、結構ちょっとした動きでゴミデータまで撮ってしまうので、犬や家族のメンバーなど、限定された画像だけ選別して残して、あとは消去できたらいいな、と思った次第です。

##準備
###人感センサ & Raspberry Piで監視カメラを作る
####材料
- [ ] Raspberry pi3 
- [ ] メスメスジャンパケーブル3つ
- [ ] Webカメラ(USB)　(Logitech HD Webcam C525)
- [ ] 人(犬)感センサー　(SEEED-101020060 PIRモーションセンサ)

ラズパイと人感センサーの接続方法、またセンサーの動作調整等は[cigalecigales](http://qiita.com/cigalecigales)さんの、[[*Raspberry Pi*] 夏だ！人感センサーを使って蝉を鳴かせよう](http://qiita.com/cigalecigales/items/4cf9c16f24d1de92ec7d)
を参考にさせていただきました。ありがとうございました。
![KIMG1860.JPG](https://qiita-image-store.s3.amazonaws.com/0/5848/a361be8c-daf5-a3ac-0595-f0df3a5ebd70.jpeg)

ラズパイとUSBのWebカメラの連携はfswebcamを使います。こちらはオフィシャルページを参考にしました。

- [USING A STANDARD USB WEBCAM]
(https://www.raspberrypi.org/documentation/usage/webcams/)

これをPythonから呼び出すために、os.systemを使います。

```py3:RekogDogCamera.py
import time
from time import gmtime,strftime
import RPi.GPIO as GPIO

INTERVAL = 3
SLEEPTIME = 5
SENSOR_PIN = 25

GPIO.setmode(GPIO.BCM)
GPIO.setup(SENSOR_PIN, GPIO.IN)

st = time.time()-INTERVAL
while True:
        if( GPIO.input(SENSOR_PIN) == GPIO.HIGH ) and (st + INTERVAL < time.time() ):
                st = time.time()
                strf = strftime("%Y%m%d-%H:%M:%S")
                strfile = strf + '.jpg'
                print("movement detected " + strf)
                os.system('fswebcam --no-banner /home/pi/myphoto/'+ strfile)
              
        time.sleep(SLEEPTIME)
GPIO.cleanup()
```

###撮影した画像をS3にあげる
[Boto3](https://github.com/boto/boto3#quick-start)を使いました。ドキュメント通りに~/.aws/credentialsなどを設定した後、上記コードのループ内にS3にアップロードするあたりを足します。

```py3:RekogDogCamera.py
import boto3
bucket_name = 'mybucket'
s3_client = boto3.client('s3')
s3_client.upload_file('/home/pi/myphoto/' + strfile ,bucket_name, strfile)
```

これで準備は完了です。
##さあ新しいもので遊んでみよう！
###Rekognition使ってうちの子の写真だけ残す
Rekognitionのデモを試してみました。今回興味あるのは、Object and scene detectionです。
![rekognitiondemo.JPG](https://qiita-image-store.s3.amazonaws.com/0/5848/bb01ac28-d711-f466-ba25-dd6e0bcaa5bd.jpeg)


Download SDKからたどって、ドキュメントを読みます。
[Amazon Rekognition　Developer Guide](https://aws.amazon.com/documentation/rekognition/)　PDF 28ページ目くらいに欲しいものがありましたので一度コンソールから試します。
追記：HTML版はこちらにありました。→[Exercise 1: Detect Labels in an Image (API)]
(http://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/get-started-exercise-detect-labels.html)

> $ aws rekognition detect-labels --image '{"S3Object":{"Bucket":"mybucket", "Name":"mydog.jpg"}}' --region us-east-1 --profile default  

先ほどDemoで使った写真はこんな感じの返答が返ってきました。

```json:result
 {
    "Labels": [
        {
            "Confidence": 98.25569915771484,
            "Name": "Animal"
        },
        {
            "Confidence": 98.25569915771484,
            "Name": "Canine"
        },
        {
            "Confidence": 98.25569915771484,
            "Name": "Dog"
        },
        {
            "Confidence": 98.25569915771484,
            "Name": "Husky"
        },
        {
            "Confidence": 98.25569915771484,
            "Name": "Mammal"
        },
        {
            "Confidence": 98.25569915771484,
            "Name": "Pet"
        },
        {
            "Confidence": 95.74263763427734,
            "Name": "Eskimo Dog"
        },

```

(※余談：エスキモー犬でもハスキーでもなく、うちの子は紀州犬です...)

先ほどのPythonコードからの呼び出しを試します。お手軽にos.systemを使うのでクオートをがんばってエスケープします。

```py3:RekogDogCamera.py
result = os.system("aws rekognition detect-labels --image \'{\"S3Object\":{\"Bucket\":\""+bucket_name+"\", \"Name\":\""+ strfile +"\"}}\' --region us-east-1 --profile default > temp.json")
                
```

帰ってくる返答をループにかけて、もし"Name" に "Canine" があって、しかも"Confidence" が55以上なら、"Canine found"と、Confidenceを報告するようにします。。

```py3:RekogDogCamera.py
with open('temp.json') as json_data:
    data = json.load(json_data)
    for d in data["Labels"]:
        if (d["Name"] == "Canine" and d["Confidence"] > 55.0):
            print ("Canine found: " + str(d["Confidence"]))
        break
                     
```
(※最初Confidenceを95くらいにしていたのですが、暗めの室内の写真だと60以上あまり行かないので、55にしました)

そして、犬が検知されなかった写真は、S3から排除します。

```py3:RekogDogCamera.py                      
        else:
            s3_client.delete_object(Bucket=bucket_name, Key=strfile) 
```

実行します。
![KIMG1858 (1).jpg](https://qiita-image-store.s3.amazonaws.com/0/5848/218e3963-eab9-999e-ae98-0910ff73f10f.jpeg)


$ python3 RekogDogCamera.py
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
Adjusting resolution from 384x288 to 352x288.
--- Capturing frame...
Captured frame in 0.00 seconds.
--- Processing captured image...
Disabling banner.
Writing JPEG image to '/home/pi/myphoto/20170103-00:08:15.jpg'.
**Canine found: 71.327880859375**
![20170102-23-57-58.jpg](https://qiita-image-store.s3.amazonaws.com/0/5848/ab603a27-148d-abdf-6e55-33a030e22176.jpeg)

撮れました！
* * *
最終的にこんな感じのファイルになります。

```py3:RekoDogCamera.py
import time
from time import gmtime,strftime
import RPi.GPIO as GPIO
import json
import os
import boto3

INTERVAL = 3
SLEEPTIME = 5
SENSOR_PIN = 25
#使用するアクセス権のあるバケットを指定
bucket_name = 'mybucket'

GPIO.setmode(GPIO.BCM)
GPIO.setup(SENSOR_PIN, GPIO.IN)

st = time.time()-INTERVAL
s3_client = boto3.client('s3')
while True:
         #犬感センサーからデータの流入があり、なおかつ時間間隔が規定以上なら…
        if( GPIO.input(SENSOR_PIN) == GPIO.HIGH ) and (st + INTERVAL < time.time() ):
                st = time.time()
                strf = strftime("%Y%m%d-%H:%M:%S")
                strfile = strf + '.jpg'
                #写真を撮ります
                os.system('fswebcam --no-banner /home/pi/myphoto/'+ strfile)
                #撮った写真をS3のバケットに移動します。
                s3_client.upload_file('/home/pi/myphoto/' + strfile ,bucket_name, strfile)
                #Rekognitionに、写真の中に犬がいるかどうか訊きます。
                result = os.system("aws rekognition detect-labels --image \'{\"S3Object\":{\"Bucket\":\""+bucket_name+"\", \"Name\":\""+ strfile +"\"}}\' --region us-east-1 --profile default > temp.json")
                #Rekognitionから帰ってきたJsonデータに犬がいたら…
                with open('temp.json') as json_data:
                    data = json.load(json_data)
                    for d in data["Labels"]:
                        if (d["Name"] == "Canine" and d["Confidence"] > 55.0):
                                #犬がいたよ！とConfidentと併せて報告します
                                print ("Canine found: " + str(d["Confidence"]))
                                break
                        else:
                                
                                #そうでなければ、容赦なく削除します。
　　　　　　　　　　　　　　　　s3_client.delete_object(Bucket=bucket_name, Key=strfile)

        time.sleep(SLEEPTIME)
# Clean Up
GPIO.cleanup()
os.system('rm /home/pi/myphoto/* temp.json')

```