« メモリの断片化によるメモリ確保失敗に関して | メイン | Android で waifu2x 分割処理などに対応 »

2015年06月16日

Android:: RenderScript + Java で waifu2x を実装した

    

2次元超解像拡大(waifu2x)

作っていて躓いたところなど――

Android で標準の org.json.JSONObject 使って、モデル読もうと思ったら例外で落ちる。
5MB強あるけど、大きい JSON ファイルは処理できないのだろうか。
仕方がないので、JsonPullParser を使って読み込むようにするも 8秒も JSON の読み込みにかかる。
最初に MessagePack 使うことも考えたが、色々と検索すると Android での読み込みは JSON の方が早いとベンチマークがあったので、まずは JSON で読むことにしたのだけれど。
これだとどっちにしても遅いだろうから、独自バイナリ化して読むことにした。
要素数、float配列のような形で決め打ちでバイナリ吐いて読む。
読み込むファイルは3パターン決め打ちなので、汎用性は考えない。
すると読み込み速度は 1秒強~2秒辺りまで早くなり、実用的に。

大きめの画像を拡大しようとしたらアプリが例外もなく突然落ちる。
RenderScript の Allocation のサイズを合計してログに吐いて 1.15GB 確保した次に落ちた。
Allocation で null が返るわけでもなく、例外も出ず突然落ちるので、事前にチェックしてはじくことにした。
確保する前に毎回メモリの空きを確認してもいいけど、事前チェックの方が処理走る前に知れていいだろうと言うことで。
開発に使っている端末は Nexus5 でメモリ容量は 2GB。
スマフォではあまり大きな画像は拡大できそうにない。
メモリ容量が大きくて 64bitの端末だとしても、support library 使ってターゲット API レベルを 18 にすると so は 32bit のバイナリが吐かれているようなので、4GB辺りまでしか使えなさそう。
API レベル 21 にして 64bit 吐くようにすると Java の方が対応していないようでエラーになる。
4GB フルに使えても 1024x1024 の拡大までなので、実際にはこれより少し少ない辺りが現状サイズ限界か。
Android 5.0 以降専用にして 64bit に対応すれば 64bit 端末ではもっと行けるけど、まだそんなにメモリ積んだ端末ないだろうからあまり意味もなさそう。
処理速度を無視するのなら、途中の結果を逐一ファイルに書き出して処理すると言うことは出来るけど、処理時間は絶望的なことになるだろうな。

スマフォだと処理時間はちょっとしたことで大きく変わる。
プログレスバーを出していると、処理時間が倍くらいになる。
本体が熱くなるとクロック落とされるので、熱くなってくると処理時間が遅くなる。
RenderScript で GPU が使われるケースは少ないようで、多くは CPU での処理になるっぽい。
色々と制限付きで記述すると GPU で動くこともあるようだけど、全てそのように書くのは難しい。
OpenGL ES 3.0 使ってシェーダーで走らせれば GPU での処理になるだろうけど……

RenderScript での実装自体は楽。
RenderScript が分かれば、waifu2x は極めて適した処理なので楽に書けた。

後は上がってきた不具合等をじわじわ修正していく。


投稿者 Takenori : 2015年06月16日 16:42




comments powered by Disqus
Total : Today : Yesterday : なかのひと