フレクトのクラウドblog re:newal

http://blog.flect.co.jp/cloud/からさらに引っ越しています

Webworkerを使ってFaceSwapとバーチャル背景を同時に行う話。

こんにちは。研究開発室の岡田です。

前回は、Amazon Chime SDKを用いてPPTのスライドをバーチャル背景にしたビデオ会議を行う方法をご紹介しました。

cloud.flect.co.jp

前回ご紹介した方法は、AIの処理や画像の処理をブラウザ上で行うことで実現していました。 今回はこれらの処理をwebworkerを用いて実行する方法についてご紹介したいと思います。

webworkerを使うことで、重いAI処理や画像処理を複数並列実行できるようになり、fpsの改善をはかることができます。 例えば、次の様な加工をリアルタイムで実施できるようになります。 f:id:Wok:20201018023426g:plain

今回やりたいこと

ビデオ会議では、プライバシー保護の観点から、背景を別の画像に入れ替えるバーチャル背景機能が使われることが多いと思います。 また、youtubeなどの動画サイトでは、話者を別のアバターに入れ替えるということもよく行われています*1。 今回は、この2つを同時にブラウザ上で行ってみます。具体的には、バーチャル背景を行いつつ、話者の別の顔に入れ替えてみます。 また、少し唐突ですが説明の都合上(*1)、手の動きの検出も併せて実施します。

(*1) 後で理由を示します。

実現の基本要素

今回やりたいことをブラウザ上で行うためには、AIを用いて、次のことを行う必要があります。

  • バーチャル背景:人物と背景の識別
  • 顔の入れ替え:目、鼻、口といった顔のランドマーク検出
  • 手の検出:手の検出

これらを行うためのトレーニング済みAIモデルは下記のサイトで提供されています。

今回は、これらのトレーニング済みAIモデルを活用して機能実現をしていきたいと思います。

課題

・・・と、意気込んでみましたが、実は課題が2つあります。

1つ目は各AIモデルが前提とするTensorflowjsのバージョンの違いです。 Bodypixはtensorflowjsの1.x系が前提となっています。FacemeshとHandposeは2.x系が前提となっています。 tensorflowjsはバージョン間でAPIの名前やパッケージ名が変更になっているものがあります。 この影響で、同時に異なるバージョンを前提とするAIモデルを動かそうとするとどちらか一方がAPI呼び出しに失敗します。 例えば、下記のような例外が発生します。 もしかしたら、うまい回避策があるのかもしれませんが、私が調べた範囲では回避方法は見つけられませんでした。 (どなたかご存知でしたら教えていただけると幸いです。)

f:id:Wok:20201018022357p:plain

2つ目は処理時間の問題です。 AIの処理は比較的重い処理なので、複数の処理を単一のスレッドで実行するとどうしてもfpsが悪化します。

解決方法

ということで、最初の方にネタバレしていますが、今回はwebworkerを用いてこれらの課題を解決します。 webworkerで実行される処理は独立したプロセスで動きますので、プロセス間で異なるバージョンのtensorflowjsモジュールをロードできます。 また、それぞれのプロセスは並列して実行されますので、リソースの空き具合にもよりますが、fpsの悪化を抑えることが期待できます。

デモアプリの作成と動作検証

それでは、期待通りの動作をするか、デモアプリを作成して検証してみましょう。

ざっくりと構成は次のようにします。 ウェブカメラから取得した各フレームに対し、BodyPix, Facemesh、HandPoseを用いて、人物の位置、顔の位置、手の位置を取得します。 また、予め入れ替える顔をFacemeshを用いて顔の位置を取得しておきます。 これらの各パーツの位置情報を用いて、各イメージ(ウェブカメラのフレーム、背景画像、入れ替え先の画像)をマージして最終的な画像を生成します。 この中のAIの処理(BodyPix, Facemesh, HandPose)はWebworkerを用いてバックグラウンドで処理を行うようにします。

f:id:Wok:20201019033745p:plain

では、作成したデモを動かしてみます。 次のように、異なるバージョンのtensorflowjsを前提としているAIモデル(Bodypix, Facemesh, HandPose)も動かすことができていることがわかります。

f:id:Wok:20201018023426g:plain

こちらのURLで実際に触っていただけます。(chromeのみ。safariは未サポート)

https://flect-lab-web.s3-us-west-2.amazonaws.com/P01_wokers/exp01_multi-worker-performance/index.html

性能検証

それでは、fpsの方は改善されているでしょうか?これも検証してみましょう。 ただ、残念ながら、上記のとおりbodypixとその他のモデルは同一スレッド上で動かすことができません。 なので、今回はbodypixの代わりに画像をasciiart化する処理を入れてみます。 なお、これが今回唐突に手の検出を行っている理由です。 本来は、BodyPixとFacemeshのみでよかったのですが、性能評価のため単一スレッドで2つを動かした場合と、 webworkerで異なるプロセスに分離した場合のFPS比較ができるように、 BodyPixの代わりにFacemeshとHandPoseを同時に動かすことにしました。

次の映像は私のメインマシン(core i9-9900KF, GeForce GTX 1660)で動かしたときのものです。 上がwebworkerを使った場合です。下がwebworkerを使わなかった場合です。 webworkerを使わなかった場合は12fps程度ですが、webworkerを使ったときは17fps程度出ています。

f:id:Wok:20201018024048g:plain

f:id:Wok:20201018024114g:plain

参考までに、ThinkpadMacBookで動かした場合のFPSも載せておきます。 なお、MacBookChromeで動かしています。 f:id:Wok:20201018031939p:plain

このデモも次のURLで実際に触っていただけます。(chromeのみ。safariは未サポート)

https://flect-lab-web.s3-us-west-2.amazonaws.com/P01_wokers/exp02_multi-worker-performance_sub/index.html

まとめ

以上のとおり、webworkerを用いることで複数の重いAIモデル、tensorflowjsのバージョンが異なるAIモデルを同時にブラウザ上で動かすことができました。 今回のデモは単一のブラウザ上で動くものでしたが、画像処理後の画像はHTMLCanvasElement上に描画していますので、 以前ご紹介した方法(こちらとか、こちらとか)で簡単にAmazon Chime SDKを用いたビデオ会議システムに組み込むことができます。

ただ、webworkerを使用するのはそれなりの前提知識が必要となりますので、今回使用した処理については簡単に導入できるようにnpm化してあります。 ソースや使い方は次のリポジトリに置いてあります。また、今回の動作検証に用いたデモのソースもおいてあります。ぜひご活用ください。

https://github.com/w-okada/image-analyze-workers

最後に

弊社FLECTは、Salesforceを中心にAWS, GCP, Azureを用いたマルチクラウドシステムの提案、開発を行っております。 また、ビデオ会議システムとしては、Amazon Chime SDKを中心とした各種ビデオ会議用SDKを用いたシステムの開発を行っております。 興味をお持ちいただけたら是非ご相談をいただければと思います。

参考

顔入れ替えのやり方はこちらを参考にさせていただきました。

github.com

本ページのデモで使用している顔はこちらのサイトで生成した画像を使用しています。 (リンク先のデモは別画像を用いています。)

thispersondoesnotexist.com