Camera Previewのbyte[] YUV420SPをBitmapのint[] ARGBにする話 - ReDo

2013年2月25日

Camera Previewのbyte[] YUV420SPをBitmapのint[] ARGBにする話

gn-java.png
[GN, VGA Preview YUV420SP->ARGB Java only]

Q. Javaは遅いのですか?
A. お前がそう思うんならそうだろう お前ん中ではな

○Camera Previewって?

Androidでは撮影(takePicture)とは別にPreview画像を連続して取得することができます。

昔はPreviewの取得と取得したデータの処理が順次動作していたのですが、API Lv.8(FroyoなのでこのAPIの追加も十分昔なのですけどね)からsetPreviewCallbackWithBufferと「キューイングされたバッファに対して順次プレビューを取得しろ」というものが増えたので、バッファがある限りパラで動作できる様になりました。

Single CoreでJava heapが16M/24M時代には色々苦しかったのですが、Quad Coreとか48M/64Mとかの世界になってくると、Java層でえいやでぶん回してもそこそこリアルタイム加工がいけそうという話です。

○YUV420SP→ARGB

YUV420SPは今更説明するまでも無いと思いますが、「YUVの一種」ぐらいの人は今ここで覚えましょう。

interleaved/Packed
→データの並びとしてYUVが規則的に混じってるもの。画像としての範囲切り出しがしやすい、RGBはPackedしか大抵ないので分かりやすい。

Planer
→データの並びとしてYとUとVが独立しているもの。まずYのデータ列があって、Uのデータ列があって、最後にVのデータ列がある。Yだけ取り出したいとかUだけ取り出したいとかそういう際に楽。

Semi Planer
→まずYだけのデータ列があって、UVが混ざってる。AndroidのYUV420SPはこれ。つまりエッジ検出とか、「輝度成分だけ前半から取り出したい」際にはもってこいということ。

『RGBとYUVの違い』に関しては
http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html が、
『Semi Planer』については
http://ameblo.jp/ekispresso/archive-201106.html の図が、
『英語表現としてpackedとかinterleavedってどう使い分けるの』については
http://wiki.videolan.org/YUV が、
素敵な感じで分かりやすいですが、いかんせん変換式も含め複雑な話なのでいくつか読みながらじんわりと覚えた方が良さそうです。


○Javaでいいの?ダメなの?

そんなわけでそのあたりのサンプルを作ってみました。

https://github.com/youten/YUV420SP
READMEの通りですがy1CameraPreviewがJava only、y2NDKYUV420SPがNDKでYUV420SPを変換してます。

【結論】
VGAあたりまでを上限として輝度成分(グレースケール)だけ取り出して...みたいな際にはJava層だけでもなんとかなる気がします。それ以上はNDKで、HD超えになるとRenderScriptでGPUの並列処理に期待するのが妥当そうです。

以下、GN,N7,N10で比較した結果。全部サイズはVGAです。
そもそもCameraの性能(というより暗所で感度あげてノイズ処理するつくりこみ)の都合上、結構数字が揺れます。
本当は変換処理のみ測定すべきですが、wholeでこのオーダですよ、ということで。


【GN 4.2.2 JDQ39】
Javaのみ JIT無効 min 227ms max 276ms ave. 233ms
Javaのみ JIT有効 min 29ms max 59ms ave. 40ms
Native armeabi min 23ms max 41ms ave. 28ms
Native armeabi-v7a min 12ms max 28ms ave. 18ms Dualのせいかfpsが不安定

【N7 4.2.2 JDQ39】
Javaのみ JIT無効 min 234ms max 263ms ave. 240ms
Javaのみ JIT有効 min 26ms max 55ms ave. 34ms
Native armeabi min 22ms max 48ms ave. 28ms
Native armeabi-v7a min 11ms max 31ms ave. 18ms Quadのせいかfpsが高め安定

【N10 4.2.2 JDQ39】
Javaのみ JIT有効 min 18ms max 32ms ave. 24ms
Native armeabi-v7a min 8ms max 23ms ave. 11ms

n7-java.png
[N7, VGA Preview YUV420SP->ARGB Java only]
n10-ndk.png
[N10, VGA Preview YUV420SP->ARGB JNI Native]

やっぱりひとまわり1.7GHz DualのN10が速いですね。2.3GHz QuadのSnapdragon 800あたりでどうなるか楽しみです。

コメントする