6

私はOpenCVを使用して、ライブビデオ処理を試みています。処理がかなり重いため、出力フレームが大幅に遅延し、ライブストリームが途切れ途切れに見えます。

処理の一部をAsyncTaskにオフロードしたいと思います。私はそれを試しました、そしてそれは実際にビデオをはるかに滑らかにします。ただし、一度に大量のタスクを開始することになり、その後、ゆっくりと戻ってきて、いくつかの結果が得られます。

Synchronizeステートメントまたは他の方法を使用して、これを遅くし、結果を待つ方法はありますか?

各カメラフレームで、これらのタスクの1つを開始します。DoImgProcessingは長い処理を実行し、文字列の結果を返します。

private class LongOperation extends AsyncTask<Mat, Void, String> {

    @Override
    protected String doInBackground(Mat... params) {
        Mat inputFrame = params[0];
        cropToCenter(inputFrame);
        return doImgProcessing(inputFrame);
    }      

    @Override
    protected void onPostExecute(String result) {
        Log.d(TAG, "on post execute: "+result);

    }

    @Override
    protected void onPreExecute() {
        Log.d(TAG, "on pre execute");
    }
}

public Mat onCameraFrame(Mat inputFrame) {
    inputFrame.copyTo(mRgba);//this will be used for the live stream
    LongOperation op = new LongOperation();
    op.execute(inputFrame);
    return mRgba;
}
4

2 に答える 2

3

私はそのようなことをします:

// Example value for a timeout.
private static final long TIMEOUT = 1000L;

private BlockingQueue<Mat> frames = new LinkedBlockingQueue<Mat>();

Thread worker = new Thread() {
    @Override
    public void run() {
        while (running) {
            Mat inputFrame = frames.poll(TIMEOUT, TimeUnit.MILLISECONDS);
            if (inputFrame == null) {
                // timeout. Also, with a try {} catch block poll can be interrupted via Thread.interrupt() so not to wait for the timeout.
                continue;
            }
            cropToCenter(inputFrame);
            String result = doImgProcessing(inputFrame);
        }
    }
};
worker.start();

public Mat onCameraFrame(Mat inputFrame) {
    inputFrame.copyTo(mRgba);//this will be used for the live stream
    frames.put(inputFrame);
    return mRgba;
}

onCameraFrameはフレームをキューに配置し、ワーカースレッドはキューからポーリングします。

これは、フレームのレセプションと処理を飾ります。を使用して、キューの増加を監視できますframes.size()

これは典型的な生産者/消費者の例です。

于 2013-02-19T18:41:00.110 に答える
1

フレームごとにこれを行う場合は、代わりにスレッドが必要なようです。AsyncTaskは、別のスレッドで1回限りのアクティビティを実行する場合に使用します。ここでは繰り返しやりたいと思います。スレッドを作成し、フレームが終了したら、ハンドラーにメッセージを投稿して、UIスレッドで投稿ステップを実行します。次のフレームの準備ができるまで、ループの上部にあるセマフォを待つことができます。

于 2013-02-19T17:34:22.593 に答える