はじめに
この記事では、次の構成図のようにJetson TX2上にKafkaとNode-REDを構成し、DeepStreamの出力をKafkaとNode-REDに連携させる手順を説明しています。
構成図
完成イメージ
物体検出したラベルと位置情報をNode-REDのコンソールに出力しています。
環境情報
Jetson TX2
Jetpack 4.3
カメラ:LOGICOOL HD PRO WEBCAM C920
Kafka 2.4.0
Node-RED 1.0.3
Node.js 12.14.1
手順概要
- Kafkaセットアップ
- Node-REDセットアップ
- DeepStreamサンプルアプリ起動
1. Kafkaセットアップ
1-1. Javaの導入
Kafkaを動かすためにはJavaが必要なため、導入します。
$ sudo apt install openjdk-11-jre
$ java --version
1-2. Kafkaの導入と起動
以下のKafkaのquickstartの手順を参考にシングルノードのKafkaを導入し、起動します。
https://kafka.apache.org/quickstart
以下のサイトからKafkaのコードをDownloadします。
https://www.apache.org/dyn/closer.cgi?path=/kafka/2.4.0/kafka_2.12-2.4.0.tgz
解凍します。
$ tar -xzf kafka_2.12-2.4.0.tgz
zookeeperを起動します。zookeeperを起動したターミナルは起動したままにしておきます。
$ cd kafka_2.12-2.4.0
$ bin/zookeeper-server-start.sh config/zookeeper.properties
kafkaサーバーを起動します。kafkaサーバーを起動したターミナルは起動したままにしておきます。
$ cd kafka_2.12-2.4.0
$ bin/kafka-server-start.sh config/server.properties
トピックを作成します。この記事では”test”という名前のトピックを作成しています。
$ cd kafka_2.12-2.4.0
$ bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic test
$ bin/kafka-topics.sh --list --bootstrap-server localhost:9092
2.Node-REDセットアップ
2-1. Node.jsインストール
Node.jsのインストールは以下の記事が参考になります。
TX2でも同様の手順でインストールできました。
以下のコマンドを実行してNode.jsを導入します。
$ sudo apt install -y nodejs npm
$ sudo npm install n -g
$ sudo n stable
$ sudo apt purge -y nodejs npm
$ exec $SHELL -l
$ node -v
$ npm -v
2-2. Node-REDの導入と起動
Node-REDの導入は以下のNode-REDのDocumentにある以下のコマンドを実行します。
Node-RED Document
https://nodered.org/docs/getting-started/local#installing-with-npm
以下のようにコマンドを実行し、Node-REDを導入します。
sudo npm install -g --unsafe-perm node-red
以下のコマンドでNode-REDを起動します。
$ node-red
ブラウザーでlocalhost:1880にアクセスすると以下のような画面が表示されます。
Kafka接続用のNodeを追加します。
右上のメニューをクリックし、「Manage palette」を選択します。
「Install」のタブを選択し、「kafka」で検索し、「node-red-contrib-kafka-manager」をインストールします。
左側のパレットに「Kafka Consumer」や「Kafka Producer」が追加されているのが確認できます。
2-3. Node-REDのフロー作成
「Inject」「Kafka Producer」「Kafka Consumer」「Debug」のノードを以下のキャプチャー画面のように構成します。
「Kafka Consumer」のノードの設定は以下のキャプチャー画面のようになります。
Topicには、前のステップで作成した「test」を設定しています。
Kafka Brokerの設定に、今回はローカルに構成しているためNameに「127.0.0.1」,Portに「9092」を設定します。
「Kafka Comsumer」のノードの設定は以下のキャプチャー画面のようになります。
Topicの設定には、前のステップで作成した「test」を設定しています。
右上の「デプロイ」ボタンを押すと作成したフローがデプロイされ、Kafka Producer、Kafka ConsumerのノードからKafka Serverへの接続が行われます。
Injectノード(以下の図の水色のノード)のボタンを押して、Kafkaサーバーへの書き込みと読み込みができることを確認します。挿入されたタイムスタンプが、Kafka Server経由でDebugノードに渡され右側のデバッグタブに出力されるのが確認できます。
3. DeepStreamサンプルアプリの起動
3-1. DeepStreamのサンプルコード、構成ファイルをコピー
サンプルコードと構成ファイルを作業ディレクトリにコピーします。
$ mkdir ~/work
$ cp -r /opt/nvidia/deepstream/deepstream-4.0/samples ~/work
$ cp -r /opt/nvidia/deepstream/deepstream-4.0/sources/ ~/work
3-2. Webカメラの確認
l4l2-ctlコマンドでWebカメラが接続されていることを確認します。
下の例では/dev/video0で接続されていることがわかります。
$ v4l2-ctl --list-devices
vi-output, ov5693 2-0036 (platform:15700000.vi:2):
/dev/video1
HD Pro Webcam C920 (usb-3530000.xhci-2):
/dev/video0
3-3. 構成ファイル
サンプルの構成ファイルtest5_config_file_src_infer.txtを参考にしてtest5_config_usb_src_infer.txtという名前で構成ファイルを作成します。
$ cd ~/work/sources/apps/sample_apps/deepstream-test5/configs/
$ ls
$ vi test5_config_file_src_infer.txt
構成ファイルは以下のような内容で作成します。
注意点が2点あります。
・「camera-v4l2-dev-node」に設定する番号は、前のステップで確認したWebカメラの/dev/videoXの番号
・camera-fps-nを30に設定すると処理が遅延するため、カメラ入力は15FPSに設定
[application]
enable-perf-measurement=1
perf-measurement-interval-sec=5
# gie-kitti-output-dir=streamscl
[tiled-display]
enable=1
rows=1
columns=1
width=640
height=360
gpu-id=0
# (0): nvbuf-mem-default - Default memory allocated, specific to particular platform
# (1): nvbuf-mem-cuda-pinned - Allocate Pinned/Host cuda memory, applicable for Tesla
# (2): nvbuf-mem-cuda-device - Allocate Device cuda memory, applicable for Tesla
# (3): nvbuf-mem-cuda-unified - Allocate Unified cuda memory, applicable for Tesla
# (4): nvbuf-mem-surface-array - Allocate Surface Array memory, applicable for Jetson
nvbuf-memory-type=0
[source0]
enable=1
# Type - 1=CameraV4L2 2=URI 3=MultiURI
type=1
camera-width=640
camera-height=360
camera-fps-n=15
camera-fps-d=1
camera-v4l2-dev-node=0
[sink0]
enable=1
# Type - 1=FakeSink 2=EglSink 3=File
type=2
sync=1
source-id=0
gpu-id=0
nvbuf-memory-type=0
[sink1]
enable=1
# Type - 1=FakeSink 2=EglSink 3=File 4=UDPSink 5=nvoverlaysink 6=MsgConvBroker
type=6
msg-conv-config=dstest5_msgconv_sample_config.txt
# (0): PAYLOAD_DEEPSTREAM - Deepstream schema payload
# (1): PAYLOAD_DEEPSTREAM_MINIMAL - Deepstream schema payload minimal
# (256): PAYLOAD_RESERVED - Reserved type
# (257): PAYLOAD_CUSTOM - Custom schema payload
msg-conv-payload-type=0
msg-broker-proto-lib=/opt/nvidia/deepstream/deepstream-4.0/lib/libnvds_kafka_proto.so
# Provide your msg-broker-conn-str here
msg-broker-conn-str=127.0.0.1;9092;test
topic=test
# Optional:
# msg-broker-config=../../deepstream-test4/cfg_kafka.txt
[sink2]
enable=0
type=3
# 1=mp4 2=mkv
container=1
# 1=h264 2=h265 3=mpeg4
## only SW mpeg4 is supported right now.
codec=3
sync=1
bitrate=2000000
output-file=out.mp4
source-id=0
[osd]
enable=1
gpu-id=0
border-width=1
text-size=15
text-color=1;1;1;1;
text-bg-color=0.3;0.3;0.3;1
font=Arial
show-clock=0
clock-x-offset=800
clock-y-offset=820
clock-text-size=12
clock-color=1;0;0;0
nvbuf-memory-type=0
[streammux]
gpu-id=0
## Boolean property to inform muxer that sources are live
live-source=0
batch-size=4
## time out in usec, to wait after the first buffer is available
## to push the batch even if the complete batch is not formed
batched-push-timeout=40000
## Set muxer output width and height
width=1920
height=1080
## Enable to maintain aspect ratio wrt source, and allow black borders, works
## along with width, height properties
enable-padding=0
nvbuf-memory-type=0
[primary-gie]
enable=1
gpu-id=0
batch-size=4
## 0=FP32, 1=INT8, 2=FP16 mode
bbox-border-color0=1;0;0;1
bbox-border-color1=0;1;1;1
bbox-border-color2=0;1;1;1
bbox-border-color3=0;1;0;1
nvbuf-memory-type=0
interval=0
gie-unique-id=1
model-engine-file=../../../../../samples/models/Primary_Detector/resnet10.caffemodel_b4_int8.engine
labelfile-path=../../../../../samples/models/Primary_Detector/labels.txt
config-file=../../../../../samples/configs/deepstream-app/config_infer_primary.txt
# infer-raw-output-dir=../../../../../samples/primary_detector_raw_output/
[tracker]
enable=1
tracker-width=600
tracker-height=300
ll-lib-file=/opt/nvidia/deepstream/deepstream-4.0/lib/libnvds_mot_klt.so
# ll-config-file required for DCF/IOU only
# ll-config-file=tracker_config.yml
# ll-config-file=iou_config.txt
gpu-id=0
# enable-batch-process applicable to DCF only
enable-batch-process=0
[tests]
file-loop=0
3-4. DeepStreamサンプルアプリの起動
以下のコマンドでサンプルアプリを起動します。
cd ~/work/sources/apps/sample_apps/deepstream-test5/configs/
$ deepstream-test5-app -c test5_config_usb_src_infer.txt
3-5. 結果の確認
ブラウザーでlocalhost:1880を開いて、Node-REDにデータが連携されていることを確認します。
以下のように車や人などが検出されるとNode-REDのdebugタブに検出結果が出力されるのが確認できると思います。
まとめ
簡単な設定を行うだけでDeepStream SDKとNode-REDの連携ができることを確認できました。