リアルタイムで来場者の入退場をカウントするシステムを作ってみた

2023-05-02
日常で楽しむクラウドテクノロジー

Author : 大前 遼、Chongmyung Park、三宅 穂波、齋藤 幹生

builders.flash 読者のみなさん、こんにちは !

イベント会場や建物内で入場者数を自動でカウントしたい、と考えたことはないでしょうか?
例えば、入場者と退場者をカウントすることで、その空間に人がどのくらい密集しているのか、どこが空いているのかをリアルタイムに把握することができます。

本記事では、AWS サービスを用いて、カメラで撮影した映像を ML で人物認識することでリアルタイムに人の入退場をカウントするシステムについてご紹介します。このシステムをイベントブースに導入することで、ブース全体の総来場者数や、その中にある各展示毎に現在の人気度の把握や可視化することが可能になります!

そして私たちはこのシステムを、実際に 2022 年に幕張メッセにて開催された『CEATEC』の AWS/intel ブースで運用してみました。
イベント開催時は、約 320㎡ の AWS / intel ブース内に 16 台の ネットワークカメラと人検知用に 7 台のノート PC を用意して臨みました。開催 4 日間で 2 万人のブース来場者を本システムでカウントすることができました。

今回紹介するシステムアーキテクチャは、実際に展示したシステムをもとにお手元の環境でより簡単に実装できるようにしたものになります。

このクラウドレシピ (ハンズオン記事) を無料でお試しいただけます »

毎月提供されるクラウドレシピのアップデート情報とともに、クレジットコードを受け取ることができます。 


1. アーキテクチャ

今回ご紹介するシステムアーキテクチャです。今回のプロジェクトでは開発期間が 2 か月間と短かったこともあり、サーバレスを意識した構成としました。また、提供するコードは東京リージョン (ap-northeast-1) で動作するものとなっています。

  • エッジデバイス上にデプロイした AWS IoT Greengrass コンポーネントの ML アプリケーションにて、カメラで撮影した映像から人検知・人数カウント処理を行います。今回、映像をクラウド上ではなく、エッジデバイス上での処理にした理由は、リアルタイム性を重視したためです。映像をクラウドに送信する場合、大容量回線が必要となり、処理遅延も生じることになります。エッジデバイス上で映像を処理し、カウント結果だけを送信することで、帯域にとらわれず、リアルタイムでブラウザから確認することが可能になります。
  • カウント結果を Amazon Kinesis Data Streams、 AWS Lambda でリアルタイムに処理し、AWS AppSync の Mutation を使って、Amazon Dynamo DB にデータを保存します
  • カウント結果が更新される毎に、AWS AppSync の Subscription によってウェブアプリケーションが動的に値を取得し、ブラウザ上に表示します

2. フロントエンド・バックエンドの設定

2-1. フロントエンド・バックエンドの構築

今回使用頂くコードは、東京リージョン (ap-northeast-1) で動作するものとなっています。
まず、フロントエンド・バックエンドの構築のために、AWS Cloud9 を使用します。事前に GitHub から cloud9CloudFormation.yaml をローカル環境にダウンロードしておきます。

AWS Cloud9 の環境を立ち上げるためにするために、AWS CloudFormation のスタックを作成します。テンプレートでの指定では、[テンプレートファイルのアップロード] を選択し、先ほどダウンロードした cloud9CloudFormation.yaml をアップロードします。

クリックすると拡大します

任意のスタック名を入力し、その他の設定はデフォルトのままにして、スタックをデプロイします。

クリックすると拡大します

デプロイ完了後、AWS Cloud9 のコンソールに移動し、テンプレートによって作成された WorkshopCloud9 環境に接続します。

クリックすると拡大します

AWS Cloud9 コンソールのターミナルから以下のコマンドを実行し、GitHub からソースをクローンします。
AWS Cloud9 の操作についての詳細は、本リンク をご覧ください。

> cd /home/ec2-user/environment
> git clone https://github.com/aws-samples/people-counter-for-events.git

AWS Cloud9 コンソールのターミナルから以下のコマンドを実行し、フロントエンド、バックエンド環境をデプロイします。

> cd /home/ec2-user/environment/people-counter-for-events/people_count_back
> . development.sh

デプロイが完了すると、フロントエンド環境と下記のバックエンド環境が構築されていることが確認できます。

AWSサービス名 名前
AWS AppSync people_count_appsync
AWS Lambda 関数 people_count_function
Amazon Kinesis Streams people_count_stream
Amazon DynamoDB テーブル videostream

バックエンド環境のサービス一覧

AWS AppSync の認証情報を設定するため、/home/ec2-user/environment/people-counter-for-events/people_count_front/src/aws-exports.js を以下のように編集します。

const awsmobile = {
    aws_appsync_graphqlEndpoint: "<AWS AppSync の API URL>",
    aws_appsync_region: "ap-northeast-1",
    aws_appsync_authenticationType: "API_KEY",
    aws_appsync_apiKey: "<AWS AppSync の API KEY>",
};

export default awsmobile;

※ AWS AppSync のAPI URL 、API KEY の確認方法
AWS コンソールから AWS AppSync を検索し、AWS AppSync のサービス画面に遷移します。

クリックすると拡大します

API の項目から、「 people_count_ appsync」を選択し、設定をクリックします。
以下項目の内容を控えておきます。

  • API URL
  • API KEY

クリックすると拡大します

上記 API URL、API KEY の値をそれぞれ aws_appsync_graphqlEndpoint、aws_appsync_apiKey に貼り付けて保存してください。

クリックすると拡大します

以下のコマンドでフロント UI を立ち上げます。

> cd /home/ec2-user/environment/people-counter-for-events/people_count_front
> npm run serve

正常的に起動されたら Cloud9 の上段にある「Preview」ボタンをクリックし UI を開きます。
※今回のハンズオンでは、 AWS Cloud9 を使用しましたが、ローカル環境での動作も可能です。

img_aws-drill-twitter-bot-10_05.png

[総来場者数]には検知エリアに入場した合計人数、[現在の来場者数]には検知エリア内の現在人数が表示されます。この後の手順でカメラ映像から人検知を行い、その結果がリアルタイムに反映されることを確認いただきます。

フロントエンド・バックエンドの設定はここまでの手順で完了ですが、サービスの設定内容について少しご紹介します。

2-2. AWS AppSync の動作について

AWS AppSync での処理についてご説明します。
まず、 AWS Lambda から AWS AppSync にデータを送信すると、updatevideostream の Mutation リゾルバが実行されます。更新時の処理の内容としては、「current_count」及び「total_count」の値をインクリメントし、「camera_timestamp」及び「 update_timestamp」の値を最新の時間に上書きします。

{
    "version": "2017-02-28",
    "operation": "UpdateItem",
    "key": {
      "video_stream_id": { "S": $util.toJson($ctx.args.input.video_stream_id)},
    },
    "update" : { 
      "expression" : "ADD current_count :current_val, total_count :total_val SET camera_timestamp = :camera_timestamp, update_timestamp =:update_timestamp",
      "expressionValues" : {
          ":current_val" : { "N" :  $util.toJson($ctx.args.input.current_count) },
          ":total_val" : { "N" :  $util.toJson($ctx.args.input.total_count) }, 
          ":camera_timestamp": { "S" : $util.toJson($ctx.args.input.camera_timestamp)},
          ":update_timestamp": { "S" : $util.toJson($ctx.args.input.update_timestamp)},
      }
  }
  }

Mutation が実行されると Subscription が動作し、データを取得します。 Mutation と異なり、リゾルバを作成しておく必要はなく、スキーマの設定をもとにサブスクライブされます。今回は、このサブスクライブ内容をフロントエンドで受け取ることで、 Amazon DynamoDB に直接クエリする必要なく最新データを取得することが可能になっています。

type Subscription {
      :
    (省略)
      :
    onUpdatevideostream(
        current_count: Int,
        total_count: Int,
        camera_timestamp: String,
        update_timestamp: String,
        video_stream_id: String
    ): videostream
        @aws_subscribe(mutations: ["updatevideostream"])
}

フロントエンドから最初に Amazon DynamoDB に格納されているアイテムのデータを取得する必要があるため、getvideostream に Query リゾルバも作成しています。プライマリキーを指定して Query を実行することでデータを取得することができます。

{
    "version" : "2017-02-28", 
    "operation" : "GetItem", 
    "key" : { 
        "video_stream_id" : $util.dynamodb.toDynamoDBJson($ctx.args.video_stream_id) 
        }, 

}

3. AWS IoT Greengrass の設定

3-1. AWS IoT Greengrass の設定

ローカル環境に GitHubpeople_count 配下のソースをすべて、任意のディレクトリにダウンロードします。

今回の手順では、AWS IoT Greengrass を Windows マシンにインストールして、映像データの処理を行います。まず、本リンクのステップ 7 まで実施してください。AWS IoT Greengrass のインストールが完了後、Windows のサービスから AWS IoT Greengrass が実行されていることを確認します。

クリックすると拡大します

AWS IoT Greengrass のコアデバイスに必要な IAM ポリシーをアタッチします。
AWS IoT のコンソール画面から [セキュリティ]→[ロールエイリアス]→[GreengrassV2TokenExchangeRoleAlias] を選択します。IAM ロール「GreengrassV2TokenExchangeRole」をクリックします。

クリックすると拡大します

IAM ロール「GreengrassV2TokenExchangeRole」に、以下の IAM ポリシーをアタッチします。

  • AmazonKinesisFull
  • AccessAmazonS3FullAccess

3-2. ツール準備

Python のインストール

Python の公式サイトから、Windows 向けの Python 3.10.10 をインストールします。
[Customize installation] を選択し、[Add python.exe to PATH] が、チェックされていることを確認します。

クリックすると拡大します

手順 3-1 で作成したユーザー「ggc_user」 が Python を扱えるようにするため、インストール時には [Install Python 3.10 for all users] と [Add Python on environment variables] にチェックを入れ、全ユーザをインストール対象にしてください。
インストール先のパスとして C:\Program Files\Python310 を指定します。
※ここからの手順では、上記パスに Python 3.10 系がインストールされていることを前提とします。

クリックすると拡大します

ライブラリのインストール

Visual Studio Community 2022 をインストールし、「C++によるデスクトップ開発」をインストールします。これは、後ほどインストールする dlib のコンパイルで使用します。

クリックすると拡大します

PowerShell を、[管理者として実行する] を選択して開きます。
※重要 : PowerShell でのすべての作業は、管理者ユーザで実行してください。本作業により C:\Program Files\Python310\ 配下に、ライブラリがインストールされます。

クリックすると拡大します

pip コマンドで、cmake をインストールします。

> pip install cmake==3.26.1

cmake の インストール先が、C:\Program Files\Python310\Lib\site-packages 配下になっていることを確認します。

> pip show cmake 

クリックすると拡大します

AWS IoT Greengrasss のコンポーネントを作成するために、 GDK CLI (AWS IoT Greengrass Development Kit Command-Line Interface) をインストールします。インストール方法は、本URL を参照してください。

people_count をクローンしたフォルダへ移動し、 pip を使って requirements_dev.txt 内の必要なライブラリをインストールします (requirements.txt とは異なるため注意してください)。requirements_dev.txt では、動作確認のため GUI での表示が可能なライブラリをインストールします。以下の例では Desktop フォルダ配下に people_count をダウンロードした想定で進めています。

> cd ~/Desktop/people_count
> pip install -r .\requirements_dev.txt

※ requirements_dev.txt にある dlib は、インストール時に 10 分弱かかる場合があります。

3-3. PeopleCount での Parameter の調整

Python プログラムの動作確認

まずは、動画ファイルで people_counter.py が起動することを確認します。

> python .\people_counter.py -p models/ssd_mobilenet_v2_coco/output.pbtxt -m models/ssd_mobilenet_v2_coco/frozen_inference_graph.pb -t models/coco_label.txt -i videos/test.mp4 -g
> python .\people_counter.py -p models/ssd_mobilenet_v2_coco/output.pbtxt -m models/ssd_mobilenet_v2_coco/frozen_inference_graph.pb -t models/coco_label.txt -i videos/test.mp4 -g

以下のような画面が表示されれば正常に動作しています。PowerShell 上で Ctrl + C を押すことで、終了します。
次に、パソコン内蔵カメラ又は USB 接続カメラでも people_counter.py が正常動作することを確認します。-i 以降の記述を削除することで、パソコン内蔵カメラ又はUSB接続カメラからフレームを取得することができます。

> python .\people_counter.py -p models/ssd_mobilenet_v2_coco/output.pbtxt -m models/ssd_mobilenet_v2_coco/frozen_inference_graph.pb -t models/coco_label.txt -g

検知エリアの調整

次に検知エリアを設定します。エリアを指定するには先ほどの引数に、—area パラメータを追加します。
座標系は以下の画像のようになっています。対象となるエリアを {左端のx座標 (x1)},{上端のy座標 (y1)},{右端のx座標 (x2)},{下端のy座標 (y2)}という形式で指定します。(例: 0,0,100,100)

クリックすると拡大します

クリックすると拡大します

では、エリアを指定して people_counter.py を起動しましょう。以下のようなコマンドになります。

> python .\people_counter.py -p models/ssd_mobilenet_v2_coco/output.pbtxt -m models/ssd_mobilenet_v2_coco/frozen_inference_graph.pb -t models/coco_label.txt -i videos/test.mp4 -g --area 200,200,700,400

指定したエリアは青枠で表示されます。エリア内に人が入ると、カウントされ、フレーム左下赤色の Enter の数字が増加することが確認できます。

クリックすると拡大します

GUI 画面を見ながら、青色の枠が所定の位置にくるよう、area として指定する座標を調整してください。
調整完了後の座標値はメモしておいてください。後ほど、 AWS IoT Greengrass コンポーネントの作成に利用します。

Greengrass デプロイ用設定の変更

テキストエディタで recipe.yaml を開き、18 行目の Run コマンドを編集します。
--area 以降の数値を先ほど調査した値に変更します。また、送信先の Amazon Kinesis Streams 名を指定するため、—stream people_count_stream という引数を追加します。AWS Lambda での集計処理のため、--vsid 0 を指定します。
編集後は以下のようになります。

Run: "python -u {artifacts:decompressedPath}/people_count/people_counter.py -p {artifacts:decompressedPath}/people_count/models/ssd_mobilenet_v2_coco/output.pbtxt -m {artifacts:decompressedPath}/people_count/models/ssd_mobilenet_v2_coco/frozen_inference_graph.pb -t {artifacts:decompressedPath}/people_count/models/coco_label.txt --stream people_count_stream --vsid 0 --area 200,200,700,400"

テキストエディタで gdk-config.json を開き、4 行目と 10 行目の内容を編集します。4 行目の<Authorの名前>と10 行目の<S3 バケット名>をそれぞれ任意の Author 名、S3 バケット名に書き換えます。S3 バケット名はユニークかつ、下記の命名規則に従う必要があります。 この処理によって、新たに S3 バケットが作成され、 AWS IoT Greengrass コンポーネントのアーティファクトが格納されます。
※S3 バケット名の命名規則

  • バケット名は 3 ~ 63 文字の長さで、小文字、数字、ピリオド、ダッシュのみを使用できます。
  • バケット名の各ラベルは、小文字または数字で始まっている必要があります。
  • バケット名では、アンダースコア、末尾のダッシュ、連続するピリオド、隣接するピリオドとダッシュは使用できません。
{
  "component": {
    "com.vizcounter.people-counter": {
      "author": "<Authorの名前>",
      "version": "NEXT_PATCH",
      "build": {
        "build_system": "zip"
      },
      "publish": {
        "bucket": "<S3バケット名>",
        "region": "ap-northeast-1"
      }
    }
  },
  "gdk_version": "1.0.0"
}

3-4. コンポーネント作成

gdk コマンドを使用して、AWS IoT Greengrass コンポーネントをビルドします。
※事前に gdk が下記フォルダにインストールされ、Path が通っていることを確認します。

クリックすると拡大します

> gdk component build

クリックすると拡大します

ビルドが成功したら、コンポーネントをクラウドにパブリッシュします。

> gdk component publish 

コンポーネントが、AWS クラウド上に登録されていることを確認します。

クリックすると拡大します

3-5. デプロイ準備

デプロイを作成します。
AWS IoT Core のコンソールの左側のメニューより 、[Greengrass デバイス] >[デプロイ] を選択します。
画面右上の[作成]をクリックします。

クリックすると拡大します

デプロイターゲットに、「3.1.AWS IoT Greengrass の設定」の手順で作成されたモノのグループを選択します。

クリックすると拡大します

マイコンポーネントから、先ほど作成したコンポーネント「com.aws.vizcounter.people-counter」を選択します。次に、パブリックコンポーネントとして、「aws.greengrass.StreamManager」と 「aws.greengrass.Cli」 を選択します。(リストに表示されない場合は、[選択したコンポーネントのみを表示] の選択を外してください。)

クリックすると拡大します

ステップ 3、ステップ 4 はスキップし、[デプロイ] をクリックします。デプロイ後、デプロイのステータスが成功していることを確認してください。デプロイには 10 分ほど時間がかかる場合があります。

クリックすると拡大します

カメラで撮影された映像がリアルタイムで人検知され、その結果が AWS Cloud9 でデプロイした Web 画面に出力されます。

手順でエラーが発生した場合、よくある質問集 をご参照ください。


4. リソースの削除

使ったリソースをそのままにしておくと、利用していなくとも S3 バケットなど、コストが継続的に掛かるサービスもあるため、不要になった場合は削除してください。
作成した AWS CloudFormation スタック 「people-count-stack」を削除することで、バックエンド環境が削除できます。その他 AWS Cloud9 の環境、S3 バケット 、AWS IoT Greengrass の削除も忘れず行いましょう。


5. まとめ

本記事ではカメラで撮影した映像から人検知を行い、リアルタイムでウェブアプリケーションでカウント結果を表示させるシステムについて紹介しました。

ML・IoT・サーバレスといったモダンな技術をより身近に感じていただけたのではないでしょうか ?

今回はカメラ 1 台の構成で実装しましたが、カメラ台数が増えた場合でも、アーキテクチャを大きく変更することなく実装できます。そのため、イベント用途に限らず、オフィスや施設への来訪者のカウント、防犯用途など幅広いユースケースに活用していただけます。


builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます

筆者プロフィール

大前 遼

アマゾン ウェブ サービス ジャパン合同会社
ソリューションアーキテクト

主にエンタープライズのお客様に対して技術支援を行なっています。趣味はバイクで、好きな AWS サービスはAmazon SageMakerです。

Chongmyung Park

アマゾン ウェブ サービス ジャパン合同会社
ソリューションアーキテクト

ソリューションアーキテクトとしてお客様の技術支援を行なっています。 好きな AWS サービスは AWS Amplify です。

三宅 穂波

アマゾン ウェブ サービス ジャパン合同会社
ソリューションアーキテクト

普段はエンタープライズのお客様に対して技術支援を行っています。好きな食べ物はラーメンです。好きな AWS サービスは AWS Lambda です。

齋藤 幹生

アマゾン ウェブ サービス ジャパン合同会社
ソリューションアーキテクト

主に商社業界のお客様に対して技術支援しています。趣味は筋トレで、好きな AWS サービスは、 AWS IoT Greengrass です。

さらに最新記事・デベロッパー向けイベントを検索

下記の項目で絞り込む
1

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する