【今更だけどandroid.hardware.Cameraを使う】プレビューフレームデータの取得方法

このエントリーを Google ブックマーク に追加
Pocket
[`yahoo` not found]

android.hardware.Cameraを使うことで、Android端末にあるカメラデバイスにアクセスして使うことができます。
android.hardware.Cameraは、現在では非推奨となっていますがOpenCV等ではまだまだ使われています。

Android端末に実装されているカメラデバイスは固有の性能があります。
そのため、ある端末では出来るのに別の端末では出来ないということが多々あります。
今回はプレビューフレームデータの取得方法を説明します。
下記の実装はすべて前回までに作ったクラスを修正しています。
プレビューフレームデータを取得する方法は3つの方法があります。
  • Camera#setPreviewCallbackを使ってプレビューフレームデータを連続して取得する。
  • Camera#setOneShotPreviewCallbackを使ってプレビューフレームデータを一度だけ取得する。
  • Camera#setPreviewCallbackWithBufferを使って事前に用意したバッファにプレビューフレームデータを保存する。

Camera.PreviewCallbackの使い方

Camera.PreviewCallbackはプレビューフレームデータを取得するコールバックインターフェースです。
Camera.PreviewCallback#onPreviewFrame(byte[] data, Camera camera)はプレビューフレームデータが生成されたタイミングで呼ばれるコールバックメソッドです。
第一引数には、カメラデバイスに設定されているフォーマット(Camera.Parameters#getPreviewFormatで確認可能)のデータが渡されます。
このデータは画像として保存したり、画像認識等のライブラリに渡すことができます。


    private Camera.PreviewCallback mPreviewCallback = new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            Log.d(TAG, "PreviewFormat : " + camera.getParameters().getPreviewFormat());
            Log.d(TAG, "PreviewFrameData : " + data.length);
        }
    };


Camera#setPreviewCallbackの使い方

final void setPreviewCallback(Camera.PreviewCallback cb)はプレビューフレームデータが生成されたタイミングで呼ばれるコールバックインターフェースを設定するメソッドです。
Camera#setPreviewCallbackでCamera.PreviewCallbackを設定した場合、プレビューフレームデータが生成されるたびにコールバックメソッドが呼ばれます。そのためコールバックメソッドは連続して一定間隔で呼ばれます。
コールバックを停止するにはCamera#setPreviewCallbackにnullを設定する必要があります。

    public void startPreviewCallback() {
        mCamera.setPreviewCallback(mPreviewCallback);
    }

    public void stopPreviewCallback() {
        mCamera.setPreviewCallback(null);
    }

Camera#setOneShotPreviewCallbackの使い方

final void setOneShotPreviewCallback(Camera.PreviewCallback cb)はプレビューフレームデータが生成されたタイミングで呼ばれるコールバックインターフェースを設定するメソッドです。
Camera#setOneShotPreviewCallbackでCamera.PreviewCallbackを設定した場合、最初のプレビューフレームデータが生成されるとコールバックメソッドが呼ばれます。そのためコールバックメソッドは一度だけ呼ばれます。


    public void startOneShotPreviewCallback() {
        mCamera.setOneShotPreviewCallback(mPreviewCallback);
    }

Camera#setPreviewCallbackWithBufferの使い方

final void setPreviewCallbackWithBuffer(Camera.PreviewCallback cb)はプレビューフレームデータが生成されたタイミングで呼ばれるコールバックインターフェースを設定するメソッドです。
また、このメソッドではプレビューフレームデータが任意のバッファに格納されます。これにより、プレビューフレームメモリの再利用が可能になり、フレームレートの向上が期待できます。
Camera#setPreviewCallbackWithBufferでCamera.PreviewCallbackを設定した場合、プレビューフレームデータが生成されるたびにコールバックメソッドが呼ばれます。そのためコールバックメソッドは連続して一定間隔で呼ばれます。しかし、設定したバッファが利用できなくなるとコールバックは停止します。
Camera#setPreviewCallbackWithBufferを使うにはCamera#addCallbackBuffer(byte[] callbackBuffer)を使って事前にバッファを設定しておく必要があります。


    private byte[] mBuffer;

    public void startPreviewCallbackWithBuffer() {
        Camera.Parameters parameters = mCamera.getParameters();
        Camera.Size previewSize = parameters.getPreviewSize();
        int bitsPerPixel = ImageFormat.getBitsPerPixel(parameters.getPreviewFormat());
        mCamera.setPreviewCallback(null);
        int size = previewSize.width * previewSize.height * bitsPerPixel / 8;
        mBuffer = new byte[size];
        mCamera.addCallbackBuffer(mBuffer);
        mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {
                Log.d(TAG, "onPreviewFrame: C-" + data.length);
                mCamera.addCallbackBuffer(mBuffer);
            }
        });
    }