IoTとAWSでサービスを作ってみた

こんにちは、呉屋です。
今回は、IoTとAWSで作ったサービスを紹介します。

これまで「ラズパイ」・「カメラ」・「熱検知センサー」・「AWS」を検証してきました。
それぞれのできることが分かってきましたので、組み合わせてサービスを作ってみました。
それでは見ていきましょう!

サービスの紹介

ラズパイの前を人が通ると、自動的に撮影されて人数をカウントするものです。

Web

構成図

構成図と処理の流れは、このようになります。

①熱検知センサーで"人"を検知
②カメラで画像撮影
③AWSに連携・処理
④Web画面確認

AWS構成図

AWSサービス

利用するサービスは、こちらです。

・IoT Core
・Lambda
・S3
・DynamoDB
・Rekognition
・Api Gateway
・IAM ROLE

今回、初登場なものが「DynamoDB」です。
IoTから送られる撮影画像の履歴を管理するために使用します。
残りのサービスは、これまで投稿したものとなります。
参考までにリンクを載せますので、興味のある方は見てみて下さい。

①・②・③について

リンク

④について

リンク

IoTについて

ラズパイ、熱検知センサー、カメラの3つを使いました。
実物は、こちらです。

IoT

起動プログラム

ラズパイ側で実行するPythonプログラムは、こちらです。

ポイントは、二つあります。
一つ目は、カメラの撮影方法を"コマンドラインツール"から"Pythonモジュール"に変更したところです。
これまでは、"raspistillコマンド"を使っていましたが、撮影するまでのタイムラグがありました。
人を検知しても、もうすでに写っていなくて一歩遅い。。。という課題がありました。
これをPythonモジュールの"picamera"を使うことで、撮影処理を速くすることができました!

二つ目は、画像の解像度を変更することです。
IoT CoreでMQTT通信を使用する場合は、画像サイズが大きすぎると、転送処理がうまくいきません。
そのため、転送可能なサイズを調整しました!
ここは最初、原因が分からずに苦戦しました。

import time
from datetime import datetime, timedelta, timezone
import json
import base64
import AWSIoTPythonSDK.MQTTLib as AWSIoTPyMQTT
import RPi.GPIO as GPIO
import picamera
 
# IoT Core設定
endpoint = “XXXXX-ats.iot.ap-northeast-1.amazonaws.com"
clientId = “RaspberryPi_dev01"
certKey = “./cert/certificate.pem.crt"
privateKey = “./cert/private.pem.key"
rootKey = “./cert/root-ca.pem"
topic = “topic_s3_push"
bucket = “XXXXX"
 
# IoT Core MQTT設定
myAWSIoTMQTTClient = AWSIoTPyMQTT.AWSIoTMQTTClient(clientId)
myAWSIoTMQTTClient.configureEndpoint(endpoint, 8883)
myAWSIoTMQTTClient.configureCredentials(rootKey, privateKey, certKey)
 
# 熱検知センサー設定
GPIO_PIN = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_PIN, GPIO.IN)
 
# カメラのインスタンス生成
camera = picamera.PiCamera()
 
# 接続開始
myAWSIoTMQTTClient.connect()
print(“センサー検証を開始します。「Ctrl + C」で終了します。")
print(“")
 
# Cameraファンクション
def capture():
  # 解像度指定
    camera.resolution = (300,300)
 # 撮影
    camera.capture('/home/pi/dev/contest/camera.jpg’)
 # 待機
    time.sleep(1)
   
# AWS IoTファンクション
def main():
  # 画像読み込み
  img  = open(“/home/pi/dev/contest/camera.jpg", 'rb’).read()
  # binaryからbase64変換
  base64Img = base64.b64encode(img).decode(“utf-8")
  # タイムスタンプ取得
  jst = timezone(timedelta(hours=+9), 'JST’)
  timestamp = datetime.now(jst)
  timestamp = timestamp.strftime('%Y-%m-%d-%H%M%S’)
  key = timestamp + “.jpg"
  # json形式に変換   
  obj = json.dumps({
      “img" : base64Img,
      “bucket" : bucket,
      “key" : key})
  # 画像転送
  print(“転送開始 ファイル名 : " + key)
  myAWSIoTMQTTClient.publish(topic, obj, 1)
  print(“転送終了")
  print(“")
 
# メイン処理
try:
    while True:
   # 検知待機待機
        if(GPIO.input(GPIO_PIN) == GPIO.HIGH):
            print(“物体検知しましたので、撮影します。")
            capture()
            main()
finally:
    # 切断
    myAWSIoTMQTTClient.disconnect()
    GPIO.cleanup

検証してみよう

ここからは、実際に動かしてみましょう!
色々なパターンで検証してみます。

正面の場合

ラズパイに接続して、実行します。

実行

ラズパイの前を通ってみます。
すると、検知して、撮影・AWSに転送されます!

実行

どのような画像が取れたのか、確認してみましょう!

Web

しっかり、撮影されていることが分かります!
ラズパイの位置と人が通る場所を熱検知センサーで調整することが難しかったです。

後ろ姿の場合

Web

顔の一部が見えていないと、カウントされていないことが分かります。

複数人の場合

Web

実際には3人いますが、2人と認識されていますね。
やはりこの基準は、AWSのRekognitionです。
精度を上げたいのであれば、RekognitionのカスタムラベルやSageMakerを使って学習させる必要があります。

さいごに

IoTとAWSを使って、少しずつサービスが作れるようになりました。
次は、検知した人物が"誰なのか"を判定できるようにしていきたいです。
また、登録していない人物の場合は、動画を撮影したり、アラートを出したりなど展開していきたいと思います。
まだまだやることたくさんです٩( 'ω’ )و