Jetson AGX Xavier と Momo で背景ぼかしの映像を配信する
Published: 2020-12-19 11:59:27

---
title: Jetson AGX Xavier と Momo で背景ぼかしの映像を配信する
published: true
description: 
tags: 
//cover_image: https://direct_url_to_image.jpg
---

最近、[Jetson AGX Xavier](https://www.nvidia.com/ja-jp/autonomous-machines/embedded-systems/jetson-agx-xavier/) 上で [Momo](https://momo.shiguredo.jp/) を使って、背景ぼかしの映像を配信するのを試してみました。

こんな感じに配信できるようになります。

[Momo で背景ぼかしの映像を配信している様子 - YouTube](https://youtu.be/usv1Zgp5qFg)
[![Momo で背景ぼかしの映像を配信している様子](http://img.youtube.com/vi/usv1Zgp5qFg/0.jpg)](http://www.youtube.com/watch?v=usv1Zgp5qFg)

自分の顔を映すのは嫌だったので、ディスプレイにヒカキンを表示して、それをWebカメラで撮影して配信しています。

元動画はこちらです: [【昔は好きだったけど今は嫌い】でエゴサしたらメンタル崩壊…【ヒカキンTV】【ツイッター】 - YouTube](https://youtu.be/BbbSULr3kBs)

ちゃんと背景がぼかされて配信されているのが分かります。

jtop コマンドで確認した CPU や GPU、メモリ使用量はこんな感じになっています。

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6pgyhgk1uevevknydnrr.png)

ちゃんと GPU も使って計算していることが分かります。

## 構成

今回の構成はこんな風になっています。

![構成図](https://dev-to-uploads.s3.amazonaws.com/i/afxos9m8bjo8pjxqp5up.png)

Python の [tf-bodypix](https://pypi.org/project/tf-bodypix/) を使って、実カメラの映像を取り込んで、背景ぼかしした映像に変換し、それを v4l2loopback という仮想カメラ(仮想ビデオデバイス)に出力しています。
あとは、Momo がその仮想カメラのデータを読んで Sora に配信しているだけです。

つまり、今回はほぼコードを書いていません。
tf-bodypix に Web カメラから読み取る部分も、仮想カメラへ出力する実装も入っていたため、単にいろいろインストールしてコマンドラインから実行するだけでした。

## 実際に動かすまでの手順

### 準備

まず Tensorflow を入れます。これは [Jetson 用のインストール方法](https://docs.nvidia.com/deeplearning/frameworks/install-tf-jetson-platform/index.html) があるので、それの通りに入れるだけです。
（インストール方法が変わっている可能性もあるので、最新の情報に関してはドキュメントを参照して下さい）

```bash
# apt で入れるパッケージのインストール
sudo apt-get update
sudo apt-get install libhdf5-serial-dev hdf5-tools libhdf5-dev zlib1g-dev zip libjpeg8-dev liblapack-dev libblas-dev gfortran

# pip3 のインストール
sudo apt-get install python3-pip
sudo pip3 install -U pip testresources setuptools==49.6.0 

# 依存ライブラリのインストール
sudo pip3 install -U numpy==1.16.1 future==0.18.2 mock==3.0.5 h5py==2.10.0 keras_preprocessing==1.1.1 keras_applications==1.0.8 gast==0.2.2 futures protobuf pybind11

# tensorflow のインストール
sudo pip3 install --pre --extra-index-url https://developer.download.nvidia.com/compute/redist/jp/v44 tensorflow
```

virtualenv とかを使っても良いです。詳細は上記のドキュメントを見てください。

次に tf-bodypix を入れます。
既に Tensorflow は入っているので不要で、Web カメラと JS モデルは必要なので、以下のようにインストールします。

```
sudo pip3 install tf-bodypix[tfjs,webcam]
```

次に、v4l2loopback な仮想デバイスを作成するためのパッケージをインストールします。

```
sudo apt install v4l2loopback-dkms
```

あとは Momo のパッケージを [Momo のリリース](https://github.com/shiguredo/momo/releases) からダウンロードして展開して配置しておきます。

### 修正

tf-bodypix は、そのまま利用すると GPU を使ってくれなかったので、ちょっとだけコードを弄る必要があります。

`/usr/local/lib/python3.6/dist-packages/tf_bodypix/cli.py` を開いて、以下のように書き換えます。

```diff
--- a/cli.py    2020-12-19 20:49:46.398000000 +0900
+++ b/cli.py    2020-12-19 20:49:41.145000000 +0900
@@ -1,3 +1,6 @@
+import tensorflow as tf
+tf.config.experimental.list_physical_devices('GPU')
+
 import argparse
 import logging
 import os
@@ -14,7 +17,6 @@
 # pylint: disable=wrong-import-position
 # flake8: noqa: E402

-import tensorflow as tf
 import numpy as np

 from tf_bodypix.utils.timer import LoggingTimer
```

詳細は分からないのですが、Tensorflow を先に import して特定の関数を読んでおくことで、GPU を使うための初期化が正常に走って、GPU が使えるようになります。いろいろ弄ってたら偶然動きました。

### 実行

まず仮想ビデオデバイスを作成します。今回は `/dev/video1` になるようにしましたが、適当に変えても良いです。

```
sudo modprobe v4l2loopback video_nr=1 card_label=BlurCamera
```

次に tf-bodypix を実行します。
CLI 上から、Web カメラから映像を読んで、背景ぼかしをして、仮想ビデオデバイスに出力するところまで全部出来るので、凄く楽です。

```
python3 -m tf_bodypix \
    blur-background \
    --internal-resolution 0.5 \
    --source-width 640 \
    --source-height 480 \
    --source-fps 30 \
    --source webcam:0 \
    --background-blur 20 \
    --output /dev/video1 \
    --threshold 0.5
```

あとはこの仮想ビデオデバイスを入力として、Momo で配信するだけです。
tf_bodypix での出力は YUYV 形式で、MJPEG ではないため、ハードウェア MJPEG デコーダが使えないことに注意して実行します。

```
./momo \
  --hw-mjpeg-decoder=false \
  --no-audio-device \
  --video-device=/dev/video1 \
  sora wss://<適切な接続先>/signaling <適切なチャンネル名> \
  --audio=false \
  --role=sendonly
```

これで配信できます。あとは Sora 経由で送られてきた映像をブラウザで見れば、最初の動画のようになります。

## 感想

Momo で背景ぼかしを配信するのは大変だと思ってたのですが、仮想ビデオデバイスを使って、tf-bodypix を使えばすごく楽でした（その後 GPU を使ってくれない問題を解決するのは大変でしたが）。
Momo 本体を弄るのではなく、仮想ビデオデバイスを使って解決していく方法は、割と良さそうな気がします。