あけましておめでとうございます。犬バカの藤向(ふじさき)です。
去年末にAmazon Rekognitionという画像認識できるサービスがリリースしていたと聞きましたので、さっそく遊びました。
作成の動機
人感センサ+ラズパイを使った監視カメラは、以前から作られてますが、結構ちょっとした動きでゴミデータまで撮ってしまうので、犬や家族のメンバーなど、限定された画像だけ選別して残して、あとは消去できたらいいな、と思った次第です。
##準備
###人感センサ & Raspberry Piで監視カメラを作る
####材料
- Raspberry pi3
- メスメスジャンパケーブル3つ
- Webカメラ(USB) (Logitech HD Webcam C525)
- 人(犬)感センサー (SEEED-101020060 PIRモーションセンサ)
ラズパイと人感センサーの接続方法、またセンサーの動作調整等はcigalecigalesさんの、[Raspberry Pi] 夏だ!人感センサーを使って蝉を鳴かせよう
を参考にさせていただきました。ありがとうございました。
ラズパイとUSBのWebカメラの連携はfswebcamを使います。こちらはオフィシャルページを参考にしました。
- [USING A STANDARD USB WEBCAM]
(https://www.raspberrypi.org/documentation/usage/webcams/)
これをPythonから呼び出すために、os.systemを使います。
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を使いました。ドキュメント通りに~/.aws/credentialsなどを設定した後、上記コードのループ内にS3にアップロードするあたりを足します。
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です。
Download SDKからたどって、ドキュメントを読みます。
Amazon Rekognition Developer Guide 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で使った写真はこんな感じの返答が返ってきました。
{
"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を使うのでクオートをがんばってエスケープします。
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を報告するようにします。。
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から排除します。
else:
s3_client.delete_object(Bucket=bucket_name, Key=strfile)
$ 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
撮れました!
最終的にこんな感じのファイルになります。
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')