ブラウザ上で画像をアニメ化する。
(noteに投稿した記事をこちらに引っ越しさせました。note)
はじめに
前回は顔の入れ替え(Faceswap的なもの)と背景の入れ替え(バーチャル背景的なもの)をブラウザで動かした話をしました。今回は画像をアニメ化する機能をブラウザ上で動かしてみたいと思います。
例えばこんな感じのもの。左の画像が右のような絵になります。なお、左の絵は、https://thispersondoesnotexist.com/ で作成したものです。
今回やりたいこと
画像をアニメ化するAIモデルはいくつか提案されています。今回は品質に定評のあるWhite-Box-Cartoonを用いてブラウザ上での稼働を実現してみたいと思います。
やること
公式のページで提供されているモデルはtensorflowのモデルです。これをブラウザで動くようにtensorflowjsのモデルに変換します。tensorflowのモデルからtensorflow liteのモデルへの変換方法はこちらに公開されていますので、これを参考にして変換を行います。そして、これをwebworkerとして組み込みます。
なお、tensowflow liteのモデルへの変換については@PINTO03091さんに教えていただきました。
やったこと
まずは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のモデルが作成できました。
この作業内容はこちらのノートにも実行ログとして残してあります。
ファイルサイズ確認
ファイルサイズは次のようになりました。量子化しない場合は5.7M, 量子化したものは1.5Mほどになりました。
動作確認
作成したUINT8の量子化モデルを用いて動作を確認してみます。インプットされる画像のサイズによって処理時間と品質が変わりますので、いくつかサイズを変えてやってみたいと思います。なお、ここでは、GeForce GTX 1660を搭載しているLinux PC&Chromeで実験しています。(後でMacBookとThinkpadでもやってみます。)
まずは256x256の画像をインプットにした場合です。約11FPSくらいは出そうです。少し顔が潰れてしまっているので残念な感じかな。
次に320x320で試してみます。一気に2~3FPSに下がってしまいました。顔が少し見えて来ましたね。
更に解像度をあげて512x512で試します。結結構顔も見えてきました。クオリティとしてはかなりよいですね。ただ、FPSが0.2程度であり、リアルタイムで使うには絶望的です。
次に、解像度を下げてみます。
128x128を試します。40FPS程度出ておりとても高速ですが、クオリティが少し残念な感じですね。もともと小さな画像をアニメ化するには良いかもしれませんが、ある程度の大きな画像を対象にするのは無理があるかもしれません。
ちなみに、256x256で映像を変換するとこんな感じになります。
320x320の場合はこんな感じ。
リアルタイムで見る場合は、256x256が限界ですかね。
以上がUINT8の量子化版での結果です。デモは下記のページにあるので、是非お試しください。
また、今回使ったデモのソースは下記のリポジトリに置いてあります。今回のモデルをwebworkerとして利用するnpmモジュールも同リポジトリで公開していますので、ご活用ください。
なお、今回の動作確認では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やスマホの性能向上に期待したいです。
リファレンス
画像は下記のページのものを利用させていただきました。
動画は下記のページのものを利用させていただきました。
Discussion