4

onPreviewFrame で lockCanvas() を使用すると、IllegalArgumentException と戦っています。

基本的に私が達成したいのは、フレームを取得して処理し、SurfacePreview の表面に直接描画することです。

これが onPreviewFrame の私のコードです

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
    Canvas canvas = null;

    if (mHolder == null) {
        return;
    }

    int mImgFormat = mCamera.getParameters().getPreviewFormat();

    try {
        canvas = mHolder.lockCanvas();
        canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
        mHolder.unlockCanvasAndPost(canvas);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (canvas != null)
        {
            mHolder.unlockCanvasAndPost(canvas);
        }
    }
}

Android のカメラに関する多くのドキュメントとトピックを読みましたが、アプリケーション コントロールの範囲を超えているため、フレームが描画されるサーフェスをロックすることはできないと思います。本当ですか?

考えられる解決策の 1 つは、別のビューでサーフェス ビューの上に描画することですが、プレビューと同期して描画された処理済みフレーム (巧妙なエッジ検出と色補正があり、時間がかかる場合があります) を維持したいと考えています。カメラが良好な fps でフレームを吐き続けると、計算が追いつくのに苦労し、最悪の場合、数十フレーム遅れてオーバーレイを描画します。

私はopenCVソースを研究しましたが、私にとっては、CameraBridgeViewBase.javaでこれを行うことができたようです:

protected void deliverAndDrawFrame(CvCameraViewFrame frame) {
    Mat modified;

    if (mListener != null) {
        modified = mListener.onCameraFrame(frame);
    } else {
        modified = frame.rgba();
    }

    boolean bmpValid = true;
    if (modified != null) {
        try {
            Utils.matToBitmap(modified, mCacheBitmap);
        } catch(Exception e) {
            Log.e(TAG, "Mat type: " + modified);
            Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight());
            Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
            bmpValid = false;
        }
    }

    if (bmpValid && mCacheBitmap != null) {
        Canvas canvas = getHolder().lockCanvas();
        if (canvas != null) {
            canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
            canvas.drawBitmap(mCacheBitmap, (canvas.getWidth() - mCacheBitmap.getWidth()) / 2, (canvas.getHeight() - mCacheBitmap.getHeight()) / 2, null);
            if (mFpsMeter != null) {
                mFpsMeter.measure();
                mFpsMeter.draw(canvas, 20, 30);
            }
            getHolder().unlockCanvasAndPost(canvas);
        }
    }
}

私は何かが欠けているか、これには年を取りすぎています:)

また、ここに初めて投稿するので、皆さんこんにちは:)

4

1 に答える 1

1

実際、openCV のカメラにはちょっとしたトリックがあります。CameraBridgeViewBase.java および JavaCameraView.java ファイル内。カメラからフレームを受信するためにSurfaceTextureクラス(api 11から)が使用されていることがわかりました。SurfaceTexture の利点は、常に画面に描画する必要がないことです (メモリに含めることができます)。次に、SurfaceView クラスが onPreviewFrame 関数から処理されたフレームを描画します。この SurfaceView はカメラにバインドされていないことに注意してください。これが助けになることを願っています。

于 2013-08-11T14:26:37.737 に答える