14

Android4OpenCVを使用してライブ画像処理を行っていますが、カメラが提供できる最小の解像度を使用したいと考えています。デフォルトの解像度は、カメラが提供できる最大の解像度です。

ユーザーがメニューから解像度を変更できるようにする3 番目の例を見ています。その例を変更して、ユーザーがメニューを通過するのではなく、起動時に解像度を変更したいと思います。これを行うには、空のonCameraViewStarted()関数に次の 2 行を追加するだけです。

public void onCameraViewStarted(int width, int height) {
    android.hardware.Camera.Size res = mOpenCvCameraView.getResolutionList().get(mOpenCvCameraView.getResolutionList().size()-1);
    mOpenCvCameraView.setResolution(res);
}

そして問題は、これは Android 4.2.2 を実行している私の Galaxy Nexus で完全に正常に動作することです。アプリが起動し、解像度が正しく設定されます。

ただし、Android 5.1 を実行している Nexus 7 タブレットでまったく同じアプリを実行すると、アプリは への呼び出しでハングしますsetResolution()。実際には一度は問題なく動作しますが、2 回目に実行しようとするとハングします。アプリを完全に終了したり、実行中のアプリから削除したり、デバイスを再起動したりしても。他のユーザーも同じエラーを報告しているため、Nexus 7 デバイスだけではありません。実際、これが機能するデバイスは私の Galaxy Nexus だけのようです。

具体的には、アプリケーションは関数に入り、次のように をsetResolution()呼び出します。org.opencv.android.JavaCameraView.disconnectCamera()

(注: このコードは OpenCV4Android ライブラリの内部であり、私のコードではありません)

protected void disconnectCamera() {
    /* 1. We need to stop thread which updating the frames
     * 2. Stop camera and release it
     */
    Log.d(TAG, "Disconnecting from camera");
    try {
        mStopThread = true;
        Log.d(TAG, "Notify thread");
        synchronized (this) {
            this.notify();
        }
        Log.d(TAG, "Wating for thread");
        if (mThread != null)
            mThread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        mThread =  null;
    }

    /* Now release camera */
    releaseCamera();
}

ログを見ると、スレッドがsynchronized(this)行に詰まっていることがわかります。そのオブジェクトで同期する他の唯一のものは、JavaCameraView クラスによって開始される、上記のコードJavaCameraView.CameraWorkerの変数である内部クラスです。mThread

(注: このコードは OpenCV4Android ライブラリの内部であり、私のコードではありません)

private class CameraWorker implements Runnable {

    public void run() {
        do {
            synchronized (JavaCameraView.this) {
                try {
                    JavaCameraView.this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            if (!mStopThread) {
                if (!mFrameChain[mChainIdx].empty())
                    deliverAndDrawFrame(mCameraFrame[mChainIdx]);
                mChainIdx = 1 - mChainIdx;
            }
        } while (!mStopThread);
        Log.d(TAG, "Finish processing thread");
    }
}

私はそのコードをいじり、notify() を notifyAll() に変更し、CameraWorker スレッドのリストを維持し、それぞれに参加しようとしました。しかし、何があっても、アプリはdisconnectCamera()通話中にハングします。

私の質問は次のとおりです。

  • 起動時に解像度が設定されるように、3 番目の OpenCV4Android の例を変更するにはどうすればよいですか?

  • アプリがハングする原因は何ですか?

  • 一部のデバイスでは機能するのに、他のデバイスでは機能しないのはなぜですか?

編集: コメントや回答を受け取っていないため、ここの OpenCV フォーラムにクロスポストしました。

編集2 :cyrielの提案に従って、いくつかのフレームが経過した後に解像度を設定しようとしました:

int frames = 0;
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

    frames++;

    if(frames == 6){
        android.hardware.Camera.Size res = mOpenCvCameraView.getResolutionList().get(mOpenCvCameraView.getResolutionList().size()-1);
        mOpenCvCameraView.setResolution(res);

    }

    return inputFrame.rgba();
}

ただし、関数で解像度を設定すると機能するGalaxy Nexusでも、これはまったく同じ場所でスタックしonCameraViewStarted()ます。フレーム数を 7 に、さらには 100 に増やしてみましたが、いつも同じ場所でスタックしてしまいます。

4

1 に答える 1