2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Android の Camera2 API を使って バーストモードで撮影する

Posted at

Android の Camera2 API を使って カメラのプレビュー画面を表示する
の続きです。

バーストモードをサポートしているか

下記のように判定する

     int[] modes = characteristics.get(
                                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
    contains(modes, CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);

バーストモードで撮影する

Camera2 APIには、バーストモードのための APIとして captureBurst が用意されている。

capture を繰り返し呼び出すことでも、同様な処理が行える。

captureBurst と capture の繰り返しの主な違いは、
captureBurst は他の要求と混在しないことを保証されていることです。

通常の capture では、キャプチャー要求のパラメータを
CaptureRequest で指定する。

captureBurst では、複数のキャプチャー要求をまとめて
List として指定する。

それぞれのキャプチャー要求に対して、
CaptureCallback の onCaptureCompleted と
OnImageAvailableListener の onImageAvailable
が呼び出される。

1枚ごとに、キャプチャー要求のパラメータを変更することもできる。
その場合は、マニュアルモードにする。

reference : captureBurst

ImageReader

通常の撮影では、JPEG 形式の ImageReader を使用する。

PEG 形式では、画像データを加工しているので、処理に 200 ms ほどかかる。

高速なバーストモードを実現するときは、YUV_420_888 形式のImageReaderを使用する。

処理時間は、画像の形式とサイズで異なる。
大まかな値は、getOutputStallDuration で取得できる。

reference : getOutputStallDuration

参考 stackoverflow : camera2-capture-burst-is-too-slow

Nexsus5 では、下記の値となる。

形式 サイズ StallDuration (ms)
JPEG 3264x2448 243
YUV_420 3264x2448 0
RAW_SENSOR 3280x2464 200

ファイルに保存する

通常の撮影と同様に、
onImageAvailable が呼び出されたときにファイルに保存する。

YUV_420_888 形式の ImageReader から JPEG 形式に変換して保存するには、
下記のようにする。

// YUV_420_888 形式のImageから NV21 形式のバイト列に変換する
    ByteBuffer buffer0 = image_yuv.getPlanes()[0].getBuffer();
    ByteBuffer buffer2 =  image_yuv.getPlanes()[2].getBuffer();
    int buffer0_size = buffer0.remaining();
    int buffer2_size = buffer2.remaining();
   byte[] bytes_nv21 = new byte[buffer0_size + buffer2_size];
    buffer0.get(bytes_nv21, 0, buffer0_size);
    buffer2.get(bytes_nv21, buffer0_size, buffer2_size);

// NV21 形式のバイト列から YuvImage に変換する
    int width = image_yuv.getWidth();
    int height = image_yuv.getHeight();
    YuvImage yuvImsge = new YuvImage(bytes_nv21, ImageFormat.NV21, width, height, null);

// YuvImage からに JPEG 形式のバイト列に変換する
    int width = yuvImsge.getWidth();
    int height = yuvImsge.getHeight();
    Rect rect = new Rect(0, 0, width, height);
    ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
    yuvImsge.compressToJpeg(rect, 100, output_stream);
     byte[] bytes_jpeg = output_stream.toByteArray();

// JPEG 形式のバイト列をファイルに保存する
    File file;
    FileOutputStream out = new FileOutputStream(file);
    out.write(bytes_jpeg);

画像の回転を補正する

上記のようにファイルに保存すると、画像は90度 回転している

JPEG 形式の ImageReade では、
キャプチャー要求のパラメータに JPEG_ORIENTATION を指定すると、カメラのほうで、回転を補正する。
YUV_420_888 形式の ImageReade では、アプリにて回転を補正する。

reference : JPEG_ORIENTATION

参考 stackoverflow : rotate-an-yuv-byte-array-on-android

// JPEG 形式のバイト列から Bitmap に変換する
    int length = bytes_jpeg.length
    Bitmap bitmap_orig = BitmapFactory.decodeByteArray(bytes_jpeg, 0, length);

// Bitmap を回転する
    int jpegOrientation
    Matrix matrix = new Matrix();
    matrix.postRotate(jpegOrientation);  
    int width = bitmap_orig.getWidth();
    int height = bitmap_orig.getHeight();
    Bitmap bitmap_rotate = Bitmap.createBitmap(bitmap_orig, 0, 0, width, height, matrix, true);

バーストモードのファイル保存

ファイル保存は、処理に 5000 ms ほどの時間がかかる。

上記のように、onImageAvailable
が呼び出されるたびに ファイル保存すると、バーストの間隔が長くなる。

高速なバーストモードを実現するときは、画像情報を一時保存しておき、
バーストが完了した時点でまとめてファイル保存する。

条件を変えて、バースト間隔の時間を実測した。
Nexsus5 では、下記の値となった。

|項番|形式|ファイル保存のタイミング|バースト間隔 (ms)|
|:------------:||:------------:|:------------:||:------------:|
|1|JPEG|onImageAvailable毎|270|
|2|RAW|onImageAvailable毎|580|
|3|YUV|onImageAvailable毎|100|
|4|YUV||完了した時点でまとめて|30|

サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/Camera218

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?