ブラウザ上で画像をアニメ化する。

6 min読了の目安(約5800字TECH技術記事

(noteに投稿した記事をこちらに引っ越しさせました。note)

はじめに

前回は顔の入れ替え(Faceswap的なもの)と背景の入れ替え(バーチャル背景的なもの)をブラウザで動かした話をしました。今回は画像をアニメ化する機能をブラウザ上で動かしてみたいと思います。

例えばこんな感じのもの。左の画像が右のような絵になります。なお、左の絵は、https://thispersondoesnotexist.com/ で作成したものです。

picture_pc_140cf277a0d2caaa47e66071c6736f26

今回やりたいこと

画像をアニメ化するAIモデルはいくつか提案されています。今回は品質に定評のあるWhite-Box-Cartoonを用いてブラウザ上での稼働を実現してみたいと思います。

やること

公式のページで提供されているモデルはtensorflowのモデルです。これをブラウザで動くようにtensorflowjsのモデルに変換します。tensorflowのモデルからtensorflow liteのモデルへの変換方法はこちらに公開されていますので、これを参考にして変換を行います。そして、これをwebworkerとして組み込みます。

なお、tensowflow liteのモデルへの変換については@PINTO03091さんに教えていただきました。

picture_pc_388c1e1f254e72efac737a80b30859d3

やったこと

まずはgithubからwhite-bix-cartoonizationをcloneしてきます。

!git clone --branch inference-tf-2.x https://github.com/steubk/White-box-Cartoonization.git

このリポジトリの"White-box-Cartoonization/test_code/saved_models"にトレーニング済みのチェックポイントが格納されています。これをロードしてSavedModelを作成します。

上記のTFLiteモデルへの変換のブログを参考に、プレースホルダを作成してからGenerator部分の重みを取得してSavedModelを生成します。

model_path = './White-box-Cartoonization/test_code/saved_models'
tf.reset_default_graph()
 
config = tf.ConfigProto()
config.gpu_options.allow_growth = True

with tf.Session(config=config) as sess:
   input_photo = tf.placeholder(tf.float32, [1, None, None, 3], name='input_photo')
   network_out = network.unet_generator(input_photo)
   final_out = guided_filter.guided_filter(input_photo, network_out, r=1, eps=5e-3)
   final_out = tf.identity(final_out, name='final_output') # Create an identical filtering layer 

   all_vars = tf.trainable_variables()
   gene_vars = [var for var in all_vars if 'generator' in var.name]
   saver = tf.train.Saver(var_list=gene_vars)
   sess.run(tf.global_variables_initializer())
   saver.restore(sess, tf.train.latest_checkpoint(model_path))

   # Export to SavedModel
   tf.saved_model.simple_save(
       sess,
       'saved_model_dir',
       inputs={input_photo.name: input_photo},
       outputs={final_out.name: final_out})

次に、生成したSavedModelからtensorflowjsのモデルを作成します。これは下記のようなコマンドを実行すれば良いです。今回は、uint8の量子化もしてみました。

!tensorflowjs_converter --input_format=tf_saved_model --output_node_names="final_output" --saved_model_tags=serve saved_model_dir/ web_model_dir/
!tensorflowjs_converter --input_format=tf_saved_model --output_node_names="final_output" --saved_model_tags=serve saved_model_dir/ web_model_dir_int8/ --quantize_uint8=*

以上でtensorflowjsのモデルが作成できました。

この作業内容はこちらのノートにも実行ログとして残してあります。
https://github.com/w-okada/image-analyze-workers/blob/master/doc/white-box-cartoonization-tensorflowjs-convert.ipynb

ファイルサイズ確認

ファイルサイズは次のようになりました。量子化しない場合は5.7M, 量子化したものは1.5Mほどになりました。

picture_pc_d93dda875ffbeea1bf9da24cc857f702

動作確認

作成したUINT8の量子化モデルを用いて動作を確認してみます。インプットされる画像のサイズによって処理時間と品質が変わりますので、いくつかサイズを変えてやってみたいと思います。なお、ここでは、GeForce GTX 1660を搭載しているLinux PC&Chromeで実験しています。(後でMacBookとThinkpadでもやってみます。)

まずは256x256の画像をインプットにした場合です。約11FPSくらいは出そうです。少し顔が潰れてしまっているので残念な感じかな。
picture_pc_7694b1efc1c2ebb93ed4296a939cca2f

次に320x320で試してみます。一気に2~3FPSに下がってしまいました。顔が少し見えて来ましたね。
picture_pc_9a039e8cf0ba97a18a78b1b0be330407

更に解像度をあげて512x512で試します。結結構顔も見えてきました。クオリティとしてはかなりよいですね。ただ、FPSが0.2程度であり、リアルタイムで使うには絶望的です。
picture_pc_1e1490d39c19454fbb4b7de8df2b072c

次に、解像度を下げてみます。
128x128を試します。40FPS程度出ておりとても高速ですが、クオリティが少し残念な感じですね。もともと小さな画像をアニメ化するには良いかもしれませんが、ある程度の大きな画像を対象にするのは無理があるかもしれません。
picture_pc_b9729dbf976ef0f345ffbe69be6e8659

ちなみに、256x256で映像を変換するとこんな感じになります。
picture_pc_c3839e55ca2b0b5309fea2b4dcf3b72f (1)

320x320の場合はこんな感じ。
picture_pc_74c84f12ecf6ecc9cc47dd997e0d8385 (1)

リアルタイムで見る場合は、256x256が限界ですかね。

以上がUINT8の量子化版での結果です。デモは下記のページにあるので、是非お試しください。
https://flect-lab-web.s3-us-west-2.amazonaws.com/P01_wokers/t07_white-box-cartoonization/index.html

また、今回使ったデモのソースは下記のリポジトリに置いてあります。今回のモデルをwebworkerとして利用するnpmモジュールも同リポジトリで公開していますので、ご活用ください。

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

なお、今回の動作確認ではUINT8で量子化したものを使いました。上記デモページでは量子化無し版もお試しいただけますので、ご興味がございましたら、上記のデモページで確認してください。(画質、処理速度に大きな違いは見られませんでした。)

動作確認 (Appendix)

追加で、Mac BookとThinkPadで動作を確認してみました。
今回使うMac Bookのスペックはcorei5 2.4GHzのものです。Safariで動かします。上記デモでお試しになる場合は、SafariはWebworker上でWebGLが使えないので、右上のコントローラからprocessOnLocalをONにして、reload modelボタンを押してください。
また、ThinkPadのスペックはcorei5 1.7GHzのものです。

Mac Bookの場合、256x256のときは約2.2FPS、320x320の場合は、約1.5FPSくらいでした。また、ThinkPadの場合、256x256のときは1.1FPS、320x320の場合は、約0.5FPSくらいでした。リアルタム処理には辛い結果ですね。

まとめ

ブラウザ上で画像をアニメ化にするチャレンジをしてみました。GPU搭載のPC上であれば、そこそこの画質でリアルタイムに変換できそうです。GPU非搭載だと、かなり厳しそうです。今後のPCやスマホの性能向上に期待したいです。

リファレンス

画像は下記のページのものを利用させていただきました。
https://www.pakutaso.com/

動画は下記のページのものを利用させていただきました。
https://pixabay.com/ja/videos/