🈳

SORACOM Fluxを使って混雑度を可視化する (export画像を保存するパターン)

2024/11/21に公開

やりたいこと

ソラカメで録画した映像を切り抜いてダッシュボードに表示させたいと思います。
ついでに、その画像に対してAIによる解析をかけて数値化した結果も表示してみたいと思います。
こんな感じのものが出来上がります。

あれ、この内容、
https://zenn.dev/takao2704/articles/soracom-flux-croudness-count
と同じじゃないかと思われるかもしれませんがひとつ違います。

↑のブログでは、画像を切り出すAPIを使って、その画像をそのままダッシュボードに表示していたため、presignedURLの有効期限が切れたあとは画像が表示されなくなってしまうという仕様となっていました。
今の状態がわかればOKという場合はこれで良かったのですが、過去の画像も見たいという場合にはこの方法ではダメでした。

今回のブログは、画像を切り出すAPIを使って、その画像をSORACOM Harvest Dataに保存される方法を紹介します。

準備

必要なもの

  • SORACOM アカウント
  • ソラカメ関連
    • ソラカメ(AtomCam2)
    • Wifi環境
    • ソラカメライセンス(常時録画ライセンス 7日間プラン)
ソラカメが初めての方はこちら(購入から設置まで)!

SORACOMのアカウント作成など

https://users.soracom.io/ja-jp/guides/getting-started/create-account/

カバレッジタイプはJPで。

ソラカメの購入〜セットアップまで

https://sora-cam.com/setup/

実は最近はソラカメのセットアップにアプリを使わなくても良くなっていたりする。

ソラカメの設置

設置に関する知見はここにたくさん溜まっています。
https://weathernews.jp/s/topics/202403/180215/

カメラチェック

何はともあれ、カメラが正常に動作しているか確認しましょう。

「ソラコムクラウドカメラサービス」 -> 「デバイス管理」

alt text

デバイスの一覧表示で、先ほど登録したカメラがオンラインになっていることを確認します。
alt text
images/soracom-flux-croudness-count/image-1.png
ここで重要な情報はデバイスIDになります。
後で使うので、メモをしておくかいつでもここに戻ってこられるようにしておきましょう。

さらに、カメラの名前をクリックすると、カメラの映像が表示されます。
alt text

こちら現在20時過ぎのソラコムの赤坂オフィスです。ホワイト企業なので、この時間にオフィスで働いている人はほとんどいません。

SORACOM Fluxの設定

SORACOM Fluxとは

SORACOM Fluxは2024年7月17日のSORACOM Discovery 2024で発表された新サービスで、デバイスから送信されたセンサーデータ、カメラから送信された画像に対して、ルールを適用し、複数のデータソースや生成 AI を組み合わせて分析/判断し、その結果を IoT デバイスの制御に反映させる IoT アプリケーションをローコードで構築できる IoT アプリケーションビルダーです。

サービスの詳細:
https://soracom.jp/services/flux/

Discovery2024での発表の様子:
https://ascii.jp/elem/000/004/210/4210823/3/

SORACOM Fluxでやりたいこと

今回は、SORACOM Fluxを使って以下の一連の流れを実装していきます。

  1. ソラカメの録画データから画像を切り出す(Exportすると同時にSORACOM Harvest Filesに保存する)
  2. 切り出した画像のデータを取得する
  3. 切り出した画像をAIに読み込ませて解析させる
  4. 解析させた結果(データ)と切り出した画像をSORACOM Harvestに送信する
  5. SORACOM Harvestに送信されたデータをSORACOM Lagoonで表示する

今まではこれを実装しようと思うとAWS Lambdaをwebhookで呼び出してゴニョゴニョしないと難しかったのですが、2024年10月16日にリリースされた「SORACOM API アクション」を使うと、AWS Lambdaで呼び出していたソラカメAPIなどが呼び出せるようになりました。わーい!
https://changelog.soracom.io/ja/soracom-flux-ni-soracom-api-akusiyongazhui-jia-saremasita-1JXTX2

ということでそんな便利な機能を早速使っていきましょう。

その前に

その前にSORACOM Fluxで解析したデータをSORACOM Harvestにいれるための準備をしておきます。
あれ?SORACOM HarvestってSORACOM AirとかSORACOM ArcみたいなSIM的なものが必要なんじゃ・・・と思ったそこのあなた。
こういう場合に使える手段があります。
その名も SORACOM Inventory
いくつかある機能のうちの、デバイスIDとデバイスシークレットを使用した Harvest 連携の機能を使います。

デバイス登録時に払い出されるデバイスIDとデバイスシークレットを使用した HTTP リクエストで > SORACOM Harvest 連携ができます。
SORACOM Air やデバイスエージェントを使用することなく Harvest にデータを蓄積し、可視化することができます。

これは意外と知らない人も多かったのではないかと思いますが、ESP32やM5Stackなどをwifiで利用している皆さんにはとても愛されている方法の一つとなっております。

Inventoryのデバイス追加

ハンバーガーメニューから 「SORACOM INVENTORY」 -> 「Inventory デバイス管理」を探します。

「デバイスを追加」ボタンからデバイスを追加します。

デバイス名やグループ名をきめます。

「追加」ボタンで追加します。

デバイスIDとシークレットが発行されるので大切に取っておきます(後で使います)。

これでHarvest Dataにデータを貯める用の仮想的なデバイスは完成です。

Harvest Data の設定

あとはこのデバイスが所属するグループにHarvest Dataの設定を有効化します。

「Inventory デバイス管理」から先ほど登録したデバイスを探し出して、グループのところをクリックします。
alt text

ちょっと下の方にスクロールして、「SORACOM Harvest Data 設定」のトグルスイッチをONして有効化します。

いよいよFluxの設定

このブログのクライマックスです。慌てず落ち着いていきましょう。

タイマー起動の設定

ハンバーガーメニューから「SORACOM Flux」-> 「Fluxアプリ」

新しいFluxアプリを作成します。

名前をつけましょう(何でもよいです)

こんな感じのチャネルを作成するしかやることがないページに飛びます。
大人しくチャネルを作成します。

今回は5分に1回のタイマーで駆動していきたいので、「タイマー」を選択します。

こんな感じで設定します。

これをこのまま放置するとこのあとの工程をやっている間に意図せず駆動されてしまうので、一旦無効化しておきます。

※急に現れてblinkしている、「変更を保存」ボタンは忘れずに押しましょう

STUDIOの画面上はこんな感じになっています。

ソラカメの録画データから画像を切り出す(Exportすると同時にSORACOM Harvest Filesに保存する)

「アクション」のタブに移動します。

「アクションを追加」からの「SORACOM APIアクション」をクリックしてOKします。

検索欄にexportSoraCamDeviceRecordedImageと入力し、表示されたパネルをクリックします。
alt text

こんな感じの画面になります。
alt text

URLのところの{device_id}をソラカメのデバイスIDに置き換えます。

この画面
alt text

の右側のやつです。

HTTPボディには、

{
  "time": ${now()},
  "imageFilters": [],
  "harvestFiles": {
    "pathPrefix": "/takao/images/{device_id}"
  }
}

といった感じのJSONを入れましょう。
"pathPrefix": "/takao/images/{device_id}"の部分は、エクスポートした画像がSORACOM Harvest Dataに保存される際のパスを指定しています。これは例なので、自分の好きなパスに変更しても構いません。
{device_id}と記述するとソラカメのデバイスIDをディレクトリの名前として使うことができます。
(ややこしいですが、このJSONのなかの{device_id}はそのとおり書いておいてOKです。)

SAM Userは新しく作成します。
名前もデフォルトのままでいきます。

こんな感じになります。

alt text

最後にアクションのアウトプットは無効にしておきます。

こんな画面に遷移すればOKです。

alt text

ちゃんと設定できたか試してみる

自分の設定に自身のある方は次に進みましょう。
自信のない方はこのSORACOM APIアクションがちゃんと動くか試してみましょう。

「テスト実行」タブに移動して、BODYに{}と空のJSON(?)を入れて、実行をクリックします。

実行結果が下の方に現れてきます。
緑色でCOMPLETEDとなったらOKです。

alt text

切り出した画像のデータを取得する

SORACOM Harvest Filesに保存された画像を取得します。

ここまでやった結果、こんな感じの状態になっているともいます。
alt text

画像を切り出すためのリクエストをしただけなので、まだ切り出された画像は取得できていません。
切り出された画像を取得するためのAPIを実行します。

先程のSORACOM APIアクションにより、自動的にSORACOM Harvest Filesに保存されます。
SORACOM FluxにはSORACOM Harvest Filesから画像を取得する方法として、SORACOM Harvest Files のディレクトリを指定して、そのディレクトリにファイルが保存や更新されたときにアクションを実行する機能があり、これを使って画像を取得します。

左上の「チャネルを追加する」をクリックします。

「新しいチャネルを作成」で「SORACOM Harvest Files」を選択します。
alt text

次の画面で
ファイルパスには、先程のエクスポートした画像のパスを指定します。
今回の例では/takao/images/{device_id}となっているので、/takao/images/実際のデバイスIDを指定します。

こんなぐあいになります。

alt text

右側に伸びているグレーの土管からは、先程のSORACOM APIアクションでSORACOM Harvest Filesに保存されたソラカメから切り出した画像に関する情報のJSONが流れてきます。

いったんこの状態で、先程の5分タイマーのイベントをテスト実行してみましょう。
テスト実行の結果が緑色でCOMPLETEDとなったら、こんどは新たに作成したHarvest Filesイベントの「メッセージ履歴」を確認してみましょう。

なにか新しいメッセージが出力されているはずです。

alt text

このときの出力の形式を確認すると以下のようになっていると思います。

{
  "eventType": "created",
  "path": "/takao/images/実際のデバイスID/ファイル名.jpg", // SORACOM Harvest Filesに保存されたファイルのパス
  "contentType": "image/jpeg",
  "presignedUrls": {
    "get": "https://soracom-harvest-files.s3.ap-northeast-1.amazonaws.com/ から始まるpresigned URL"
  }
}

ここまで確認できたら、AIに読み込ませるためのアクションを作成に移っていきます。

切り出した画像をAIに読み込ませて解析させる

ここの土管をクリックします

alt text

AIアクションを選択します。

アクションの実効条件は空白でOKです。

AIモデルはGPT-4o等のマルチモーダルに対応したモデルを選択します。

今回の例では画角の映像から着席している人数と着席割合から混雑度を解析するため、プロンプトを以下のようにしてみました。
自由にいじってみてください。

画像の様子を説明してください。

また、だいたいどのぐらいの人数の人がいるか、正確でなくて良いので教えて下さい。

出力の形式は以下のようなJSON形式でお願いします。

{
 "state": 状態を表現する文章
 "person_count": 人数
 "crowding_level":定員に対する人数の割合(0-100)
 "url":"${payload.path}"
}

AIからの返答をJSON形式にするとAIに画像を読み込ませるにチェックを入れます。

AIに読み込ませる画像のところにはURLを入れますがSORACOM Harvest Filesに保存された画像のディレクトリの方はAI
返ってきたexport画像を取得するAPIにはpresigned URLが入っていますのでそこを参照させるように以下を設定します。

${payload.presignedUrls.get}

ちなみにプロンプトの中で${payload.path}としているのは、先程のHarvest Filesのイベントで出力されたJSONの中のpathを後段のアクションで使うために設定しています。
これをやるとどうなるかはこのあとのアクションで確認してみましょう。

出力は新しいチャネルに出す設定でこのアクションを作成します。
alt text

テストはの実施方法は省略しますが、うまくいくと以下のようなレスポンスがAIから返ってくるはずです。

解析させた結果(データ)と切り出した画像をSORACOM Harvestに送信する

STUDIOに戻ると以下のようになっていると思います。

alt text

最後のアクションは青い箱から出ている土管に接続します。

今回はwebhookのアクションを使います。

名前をHarvestにデータを送信などとして、アクションの実行条件はそのまま(空白)で、
HTTPメソッド:POST
URL:https://api.soracom.io/v1/devices/デバイスID/publish
HTTPヘッダー:x-device-secret:シークレットキー

URLの中のデバイスIDと、HTTPヘッダーのシークレットキーは後で使うと予告してあった、こちらのものを利用します。

こんな感じで設定したら更新して閉じます。
BODYはAIアクションのレスポンスのボディからoutputを抜き出して設定するので、${payload.output}となります。

テストしてちゃんと送信できたか確認してみましょう。
webhookアクションの実行履歴が緑色でcompletedとなっていればOKですが、念の為Harvest Dataの方でも確認してみます。

「データ収集・蓄積・可視化」から、「SORACOM Harvest Data」を選択します。

Inventoryを使っているので、「デバイス」の中からリソースを指定して、

確認するとちゃんと送られているようです。

SORACOM Harvestに送信されたデータをSORACOM Lagoonで表示する

Harvest DataまでくればあとはいつもどおりLagoonで可視化するだけです。

「データ収集・蓄積・可視化」から、「SORACOM Lagoon」を選択します。

Lagoonの契約がない場合は、こちらを参考にセットアップしましょう。今回の可視化はフリープランでも実施可能です。
https://users.soracom.io/ja-jp/docs/lagoon-v3/getting-started/

Lagoon3のコンソールにログインします。

こんな感じのダッシュボードを作っていきたいと思います。

一番上に様子(文章)を表示

「add a new panel」します。

  • visualizationは「logs」を選択
  • Queryは左から、「Device」, 「Inventoryで設定したデバイス名」,「Standard」、「-All-」でOKです

    その他はデフォルトのままにします。

左側上段に混雑度と人数を表示

「add a new panel」します。

  • Visualizationは「Stat」を選択
  • Queryは2系列
    • A:「Device」, 「Inventoryで設定したデバイス名」,「Standard」、「crowding_level」
    • B:「Device」, 「Inventoryで設定したデバイス名」,「Standard」、「person_count」

左側下段に混雑度と人数(時系列推移)を表示

「add a new panel」します。

  • Visualization は「Time series」
  • Queryは2系列
    • A:「Device」, 「Inventoryで設定したデバイス名」,「Standard」、「crowding_level」
    • B:「Device」, 「Inventoryで設定したデバイス名」,「Standard」、「person_count」
  • Query optionsを選択して、Relative timeを少し長めに設定(下記の例では6h)。

右側は大きめにソラカメのエクスポート画像を表示

「add a new panel」します。

  • Visualizationは「Soracom Dynamic Image Panel」

  • Queryは「Device」, 「Inventoryで設定したデバイス名」,「Standard」、「-All-」

  • Settings

    • Mode:「Harvest Files」
    • Name:「A-url」
      alt text

各パネルの設定が完了したら、ダッシュボードのTime Rangeをnow-6m ~ nowとなるように設定します。

(SORACOM Fluxの駆動が5分おきのため、マージンを1分取って6分で設定しています。)

Save current time range as dashboard defaultのチェックを入れて保存したらダッシュボードの完成です。

お疲れ様でした!!

GitHubで編集を提案

Discussion