エンジニア学生日記

情報系の大学生です。主にIoTを研究してます

【成果報告】SORACOM Summer Challenge 2020~避難所における感染症の拡大を抑止するシステムの開発~

SORACOM Summer Challenge 2020 成果報告

こんにちは。

学部4回生でIoT関連の研究をしているryotaです。 普段は大学に通っていてIoTやネットワークなどを学んでいます。

この度はソラコム さんが開催されたオンラインハッカソンのSORACOM Summer Challenge 2020に参加させていただきました。

さっそくですが成果物はこんな感じになっています。 リアルタイムで人物の検知+プライバシーに配慮した混雑状況の可視化を行っています。

これに加えてLTE-M Button Plusを使った換気状態計測装置を作成しました。 コロナウイルスの感染が広がる中、災害時における避難所支援が出来ればと思い作成しました。

f:id:ryota2425:20200811222421p:plain
成果物

SORACOM Summer Challenge 2020とは

まずこのオンラインハッカソンはどんなものかについて説明します!

ハッカソンの概要についてはここに書かれています。 sorazine.soracom.jp

SORACOM Summer Challenge 2020 は 2020 年 8 月 3 日 (月) から 2020 年 8 月 14 日 (金) の約 2 週間にわたり,フルリモート・オンラインで行われるハッカソン型のイベントです.この期間中に SORACOM プラットフォームを用いて,学生の皆様が思い描く理想の IoT システムをバキッと作りきっていただくという趣旨になります.

このイベントに参加することでGPSマルチユニットSORACOM Edition と SORACOM LTE-M Button Plus を自宅に送ってもらえます!

またソラコムさんのプラットフォームが使い放題ということでデータの収集、可視化がスムーズにできるのでそのぶん開発だけに集中することができます!

さらに優秀者には豪華景品として3Dプリンタがいただけることです!魅力的です😊

テーマ決め

新型コロナウイルス感染症(COVID-19)の拡大が各所に大きな影響ををもたらしており それを少しでも解決できるようなシステムを作りたいと考えていました。

「複数人で集まること」自体がリスクとなった現在、飲食店や教育機関、宿泊施設をはじめとする多くの施設は人が密集することを防ぐ必要がでてきています。

さらにこのような状況下において、地震や台風などの災害が発生し、避難所が避難者で密集した状態になると、感染症が拡大してしまうことが懸念されます。 f:id:ryota2425:20200813010651p:plain

避難所における密集状態の検知、避難所の混雑状況を可視化するメリットとして

  • ある特定の避難所に極端に人が集まってしまうことを防ぐ
  • 避難先の選定の手助け
  • 災害で混乱しているなかでも客観的なデータを示すことで、冷静な判断をしてもらう

などが挙げられます。

避難所では、多くの方が生活をされることになるため、避難者のプライバシーを考慮する必要もあります。

迅速で正確な情報の共有が必要な災害時において、この問題を解決できるシステム作りが必要だと思いました。

この危機への対応にどうテックを使えるかを今回のテーマにしました!

システム概要

f:id:ryota2425:20200811182635p:plain
システム全体図

今回作成したシステムは主に2つのノードから構成されています。

それぞれ役割があり空気状態観測ノードでは避難所の空気の状態を観測します。

混雑状況可視化ノードでは避難所の混雑状況を機械学習によって解析、可視化を行います。

空気状態観測ノード

まず空気状態観測ノードでは観測地点のCO2濃度を定期的に計測して、CO2濃度が極端に高くないかを計測します。

避難所といった、人が密集する場所では換気が十分に行われない可能性があり、密閉の環境を作ってしまう可能性があります。 そこでCO2濃度がある一定の閾値を上回った時のみ通知を行います。

通知はLINE Notificationを用いています。

f:id:ryota2425:20200813014117p:plain
空気状態の通知のイメージ

システムの全体像はこのようになっています。

f:id:ryota2425:20200811233910p:plain
CO2濃度観測システム

CO2センサはMHZ19というCO2センサ*1を用いています。

通知はArduinoが受信したセンサの値が閾値を上回った場合にLTE-M Button Plusにデジタル出力を行なっています。 ここらへんの仕組みはこちらの記事が参考になるかと思います

blog.soracom.jp

LTE-M Button Plusは1000ppmを上回った時に注意通知、1500ppmを上回った時に警告通知をLine Notificationを利用して送信します。

LTE-M Button Plusはボタンのクリック、ダブルクリック、長押しの3種類のデータを送信することができます。

1000ppmを上回った時にクリック、1500ppmを上回った時にダブルクリックの通知を行うように割り当てました。

1000ppmを基準とした理由は、良好な換気状態の基準として二酸化炭素濃度(CO2濃度)1,000ppm以下が推奨されていたためです。*2

また教育施設は1500ppm以下が推奨されているため、こちらも閾値の基準にしています。*3

AWS Lambdaというサービスを利用して、データを受け取った場合にLINEに通知がいく関数を実装します。

AWA LambdaとLINE Notifyの連携にはこちらの記事が参考になりました。

qiita.com

以下が今回使用したLambda関数になります。

# -*- coding: utf-8 -*-
import os
import urllib.request
import urllib.parse

SINGLEFlag = False
DOUBLEFlag = False

def get_message(data):
    global SINGLEFlag
    global DOUBLEFlag
    message = data
    clicktype = data['clickTypeName']
    if clicktype == 'SINGLE' and SINGLEFlag == False:
        message = u"\nCO2の室内濃度基準 1000ppmを超えました\U0001F514\n換気を行いましょう"
        SINGLEFlag = True
    elif clicktype == 'DOUBLE' and DOUBLEFlag == False:
        message = u"\nCO2の室内濃度基準 1500ppmを超えました\U0001F9F0\n速やかに換気を行う必要があります"
        DOUBLEFlag = True
    elif clicktype == 'LONG':
        message = u'\n結果をリセットします\U00002705'
        SINGLEFlag = False
        DOUBLEFlag = False
    else:
        return
        
        
        
    return message

def line_notify(msg):
    url = "https://notify-api.line.me/api/notify"
    headers = {"Authorization" : "Bearer "+ os.environ['LINE_TOKEN']}
    data = urllib.parse.urlencode({"message" :  msg}).encode('utf-8')
    request = urllib.request.Request(url, data=data, headers=headers)
    r = urllib.request.urlopen(request)
    print(r)

def lambda_handler(event, context):
    message = get_message(event)
    if message != None:
     line_notify(message)
    return
    

これを実行すると以下のようなメッセージがLINEに通知されます。

f:id:ryota2425:20200811232253p:plain
LINE通知の例

これで取得したCO2濃度が基準を超えた時に通知することができました。

工夫した点として、LTE-M Button Plusを物理的に長押しをすることでリセットする機能を追加しました。

理由としては一度閾値を超えると、換気を行うまでずっとLINE通知が鳴り止まないことになりかねません。 CO2濃度は窓を開けてしばらくしてからゆっくり減少していくものなのでそれまでずっと通知がくるのは不都合です。

そこで一度閾値を上回ると、リセットボタンを押すまで通知がいかないようにしています。 利用者は換気をおこなってしばらくしたタイミングで再度ボタンを長押しすることでまた計測できるようになっています。

f:id:ryota2425:20200811232322p:plain
通知のリセットの実行結果

こうすることで窓を開けて換気した時など任意のタイミングでリセットして再度計測を始めるような流れになっています。

Arduino閾値を3分ごとに計測して閾値を上回っていないかをチェックします。 閾値を上回っていた時のみLTE-M Button Plusに信号を送っています。

LTE-M Button Plusに余分に信号を送ってしまうと電池が消耗する原因にもなるため 閾値を上回った時は次までの計測間隔を10分にするようにしています。

Arduinoのコード

#include <Arduino.h>
#include "MHZ19.h"                                        
#include <SoftwareSerial.h>                                

#define RX_PIN 10                                          // Rx pin which the MHZ19 Tx pin is attached to
#define TX_PIN 11                                          // Tx pin which the MHZ19 Rx pin is attached to
#define BAUDRATE 9600                                      // Device to MH-Z19 Serial baudrate (should not be changed)

MHZ19 myMHZ19;                                             
SoftwareSerial mySerial(RX_PIN, TX_PIN);                  
//HardwareSerial mySerial(1);                              

unsigned long getDataTimer = 0;

int relayIn = 2;

void setup()
{
    Serial.begin(9600);                                     // Device to serial monitor feedback

    mySerial.begin(BAUDRATE);                               // (Uno example) device to MH-Z19 serial start   
    //mySerial.begin(BAUDRATE, SERIAL_8N1, RX_PIN, TX_PIN); // (ESP32 Example) device to MH-Z19 serial start   
    myMHZ19.begin(mySerial);                                // *Serial(Stream) refence must be passed to library begin(). 

    myMHZ19.autoCalibration();      
    pinMode(relayIn, OUTPUT);
    digitalWrite(relayIn, LOW);
    // Turn auto calibration ON (OFF autoCalibration(false))
    pinMode(relayIn, OUTPUT);
    digitalWrite(relayIn, LOW);
}
void loop()
{  
        int CO2; 
        CO2 = myMHZ19.getCO2(false);                            
        
        Serial.print("CO2 (ppm): ");                      
        Serial.println(CO2);                                      
        if (CO2 > 1500) { 
            digitalWrite(relayIn, HIGH);
            delay(200);
            digitalWrite(relayIn, LOW);
            delay(500);
            digitalWrite(relayIn, HIGH);
            delay(200);
            digitalWrite(relayIn, LOW);
            delay(1000*60*7); //7分待機
        } else  if (CO2 > 1000) {
             // message : SINGLE
            digitalWrite(relayIn, HIGH);
            delay(200);
            digitalWrite(relayIn, LOW);
            delay(1000*60*7);//7分待機
            }
delay(1000*3);//3分待機
}
混雑状況可視化ノード

混雑状況可視化ノードでは、避難者のプライバシーを考慮しつつ、避難所における混雑状況の迅速な情報共有を可能にします。

避難所における受入可能人数は決まっており、避難所に避難したくても出来ない場合もあります。

実際に、昨年度の10月における台風の被害では東京都の13自治体で避難所に行ったのに受け入れてもらえなかった事例が報告されています。

www9.nhk.or.jp

今年はさらに感染症拡大防止のために受け入れ人数を大幅に減らしている自治体が多く、 これらの問題を解決するシステムを作成する必要があるのではないかと思いました。

そこでリアルタイムで避難所の混雑状況を可視化するシステムを作成しました。

f:id:ryota2425:20200811222421p:plain
実行結果

人を検知するとマスキングし、中央にカメラとの距離を表示しています。 右下にはカメラが検知した人数の合計が表示されています。

避難所において避難者は生活を行う必要があるためカメラをそのまま撮影してしまうと、プライバシー上の問題があります。 そこでベースになる避難所の背景を撮影しておき、そこに検出したマスク画像を投影することで人物が映り込まないようにしています。

f:id:ryota2425:20200811223555j:plain
ベースとなる背景画像
カメラはZED2カメラとよばれるステレオカメラ *4を用いることで、検出した物体の距離データを取得しています。

取得した画像をエッジ側で解析するための機器として、Jetson Xavier NXを用いました。

今回は混雑度をわかりやすくするためにステレオカメラを使用していますが もし深度データを利用しない場合は市販のWEBカメラでも大丈夫です。

実行速度は2FPSとなっており、高速とまではいわないものの混雑状況を把握するには十分な速度になっています。

画像認識としてfacebookが開発していたpytorchベースのmaskrcnn-benchmarkを用いてプログラムを作成しています。

github.com

2人の場合はこのようになりました。 きちんと奥行きの深度値もとれていることが確認できます。

f:id:ryota2425:20200813182618p:plain
2人の検知の様子

(背景に対して人物が大きくなっていますが、これは自宅で実験を行っているためです.. 笑

ベースとなる画像の場所で実験を行えば問題ありません)

さらに姿勢推定モデルでの解析を行うことで人物がなにをしているかがわかりやすくなるような可視化も行いました。

モデルはe2e_keypoint_rcnn_R_50_FPN_1x_caffe2を使用させていただいています。

f:id:ryota2425:20200813181827p:plain
姿勢推定モデルの実行結果

こうすることで避難者の様子(立っている、座っている、寝ている人)を知ることが出来て、より避難所の様子がわかるのではないかと思います。

f:id:ryota2425:20200813182139p:plain
床に座っている様子

これらの情報をソラコムさんが提供しているダッシュボードサービスであるSoracom Lagoonで可視化することで避難所選びの手助けをすることができます。

画像を定期的にSORACOM Harvest Fileにアップロードを行っています。 人数のデータはSORACOM Harvest Dataに送信しており、それらの情報をまとめてSoracom Lagoonで表示するような仕組みになっています。

f:id:ryota2425:20200813204648p:plain
SORACOM Lagoonでの可視化

左側が避難所の様子、右側に検出された避難者の人数の推移が表示されています。

また、Lagoonには閾値を設けおいて、超えた場合にアラームを送信する機能があります。 今回は3人以上検知した場合にアラームを送信する設定をしている例になります。

これを利用すれば避難所における最大収容人数をあらかじめ設定しておいて、 人数がおおくなってきたタイミングで知らせるような仕組みを作ることも可能です。

最後に

密閉した状態を防ぐことは、避難所だけでなく 日頃からの飲食店や学校などにおいても重要になってきているのではないかと思います。

今回は避難所をテーマにしていますが、他の多くの場面でも活用できるシステムではないかと考えています。

まだまだ改善の余地はありますがこうして一つのシステムとして作成することができて嬉しく思います。

最後となりますが、メンターの方々が丁寧にサポートしていただけたのでスムーズに開発出来ました😊 みなさん優しくしていただいて、本当に助かりました。

ぜひまたいつか直接オフィスにお伺いさせていただける日がくればと思います!