konchangakita

KPSを一番楽しんでいたブログ 会社の看板を背負いません 転載はご自由にどうぞ

KPS アプリ開発 with Jetson Nano で DeepStream

===この記事はNutanix Advent Calendar 2020の12月5日分として書きました===
ニッチな独自路線でいきます

Jetson Nano の KPS での有効活用方法を考えてみます
AWS Greengrass や Azure IoT Edge の IoTサービスは、エッジで重たい処理こそさせますが、当然ながら処理結果はそれぞれのクラウドへ送信する必要があります。特定の分野で処理結果のデータもクラウドには出したくないというケースもあるので、注意が必要です
一方、KPS は処理結果も含めエッジ側で完結することができるので、Azure IoT と連携で使った DeepStream on Jetson Nano を Azure から切り離し Nutanix KPS との連携をおこなってみます
NVIDIA DeepStream は、「AI ベースのビデオおよび画像を理解するための完全なストリーミング分析ツールキット」というもので、まだあまり使い込んでいないので、そこから掘り下げていきます

<イメージ図>
f:id:konchangakita:20201205232921p:plain

Jetson Nano への DeepStream インストール

Jetson Nano への Deep Stream 設定方法は↓コチラ
【Jetson Nano】JetPack のアップデートとDeepStream インストール - konchangakita


DeepStream の Python サンプルのセットアップ

Python サンプルの利用方法はこちらを参考にしながら、下記を進めていきます
Python Sample Apps Source Details — DeepStream DeepStream Version: 5.0 documentation

Python サンプルをダウンロード

githubからサンプルを入手します

git clone https://github.com/NVIDIA-AI-IOT/deepstream_python_apps

ダウンロードしたファイルを
<DeepStream ルートフォルダ/source>:/opt/nvidia/deepstream/deepstream-5.0/source
の配下へ持っていきます

$ sudo cp -r deepstream_python_apps /opt/nvidia/deepstream/deepstream-5.0/source


サンプルをとりあえず実行してみる

いくつかサンプルが用意されていますが、とりあえず分かりやすいものをこの2つをピックアップしてテスト

deepstream-test1 h264ストリームを解析
deepstream-test1-usbcam USBカメラからの映像を解析



deepstream-test1の実行方法
Jetson Nano 上でターミナルを開いて
python3 deepstream_test_1.py <h264ファイルへのパス>

(実行例)

$ cd /opt/nvidia/deepstream/deepstream-5.0/sources/deepstream_python_apps/apps/deepstream-test1
$ python3 deepstream_test_1.py /opt/nvidia/deepstream/deepstream-5.0/samples/streams/sample_720p.h264

ビデオが表示されて、解析結果も出力されます
f:id:konchangakita:20201205134358p:plain

Frameごとに「オブジェクト認識数、車の数、人の数」を出力しています
Objects=6 Vehicl_count=4 Person_count=2



deepstream-test1-usbの実行方法
USB Webカメラから映像を読み込んで表示するので、ビデオデバイスを指定します
Jetson Nano 上でターミナルを開いて
python3 deepstream_test_1_usb.py <ビデオデバイスのパス>

(実行例)

$ cd /opt/nvidia/deepstream/deepstream-5.0/sources/deepstream_python_apps/apps/deepstream-test1-usbcam
$ python3 deepstream_test_1_usb.py /dev/vidio0



処理結果を MQTT で KPS へ送信

きっと 正しくは DeepStream のパイプラインを使ったりするのが良いような気がするのですが、Python が使えるならなんとでもなるという感覚から、やみくもに paho-mqtt を使って KPS へ向かって送信してやります

<イメージ図>
f:id:konchangakita:20201205192344p:plain

JetPack には pip3 入っていないので
まずは、pip3からインストール

$ sudo apt install python3-pip

つづいて paho mqttモジュールのインストール

$ pip3 install paho-mqtt

# インストール後の確認
$ pip3 freeze |grep paho
paho-mqtt==1.5.1


あとはMQTT送信用の関数を Pythonサンプルコードに追記
mqtt-certificates は、KPSでの Data Source登録の際に入手して設置すること!)

###########################
# MQTT start
###########################
import os,time,json
import paho.mqtt.client as mqtt

# KPS用 初期化
EDGE_SERVER = os.getenv('EDGE_SERVER','192.168.199.99')
EDGE_PORT = os.getenv('EDGE_PORT',1883)
res_data = {}

# 動画解析結果を受け取ってMQTTで送信
def send_mqtt(res_data):
    #res_data = "test"
    print(res_data)
    mqclient.publish("data/deepstream", json.dumps(res_data))


def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))

    # Subscribing in on_connect() means that if we lose the connection and
    # reconnect then subscriptions will be renewed.
    client.subscribe("deepstream")

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    print(msg.topic+" - "+str(msg.payload))

#launch MQTT subsystem
mqclient = mqtt.Client()
mqclient.on_connect = on_connect
mqclient.on_message = on_message

# 注意!mqtt-cert は KPS の Data Source登録で入手して設置!!
mqclient.tls_set(ca_certs="mqtt-cert/CACertificate.crt", certfile="mqtt-cert/certificate.crt", keyfile="mqtt-cert/privateKey.key")
mqclient.tls_insecure_set(True)

mqclient.connect(EDGE_SERVER, EDGE_PORT, 60)
mqclient.loop_start()
###########################
# MQTT end
###########################

動画解析処理結果を出力しているあたりで、関数を呼び出します

send_mqtt(pyds.get_string(py_nvosd_text_params.display_text))


<プログラム全体>


KPS の設定

ここからは KPS 定番の設定していきます
最終的には Node-RED で受信確認します
f:id:konchangakita:20201205232808p:plain

Data Sourceに登録

f:id:konchangakita:20201205173821p:plain

+ Gnerate Certificates」でダウンロードして、Pythonコード内で記述した場所に設置すること!
f:id:konchangakita:20201205173955p:plain

topic」 も Pythonコード内で指定してもの
f:id:konchangakita:20201205174751p:plain

カテゴリは後で Data Pipeline で呼び出す用
f:id:konchangakita:20201205174916p:plain

KPS の Data Pipeline で受信設定

プロジェクトを選んで、Data Pipeline を作ります
f:id:konchangakita:20201205175621p:plain

「インプット」のカテゴリと「アウトプット」をMQTTを選択 Endpoint Name が、Data Pipeline から出力されるトピック名になります
Functionはとりあえず無しで
f:id:konchangakita:20201205175755p:plain

KPS Kubernetes Apps で受信内容確認

KPS の Kubernetes Apps に用意しておいた Node-RED で Data Pipeline から送信されている MQTT を受信設定
f:id:konchangakita:20201205181337p:plain

Jetson Nano上で MQTT送信設定を追記した DeepStream 実行

$ python3 deepstream_test_1_withmqtt.py /opt/nvidia/deepstream/deepstream-5.0/samples/streams/sample_720p.h264 

Node-RED上で、DeepStream での解析結果が受信できているのが確認できました
f:id:konchangakita:20201205182915p:plain


さいごに

今回は、DeepStream のサンプルプログラムだけ試してみましたが、簡単に KPS にも連携できました。
ここまでくればあとは KPS 内で Elasticsearchなり、SlackやLineに通知するなりすべてエッジ内で処理が可能です
もともと KPS は KPS自身のエッジデバイスで推論処理をすることも強力ですが、Jetson Nano側で重ための推論処理やってくれているので、一台の KPS Service Domain で複数台分と連携することも可能になります

Jetson Nanoって安いから、センサーと一緒にばら撒いてしまう使い方もありなのかな
f:id:konchangakita:20201205194419p:plain


Jetson Nano自体を KPS Service Domain として使うというのおもしろそう