Android4OpenCV:启动时设置分辨率

Kev*_*man 14 java android opencv opencv4android

我正在使用Android4OpenCV进行一些实时图像处理,我想使用相机可以提供的最小分辨率.默认分辨率是相机可以提供的最大分辨率.

我正在看第三个例子,它允许用户通过菜单更改分辨率.我想修改该示例以在启动时更改分辨率,而不是要求用户通过菜单.为此,我只需在其他空onCameraViewStarted()函数中添加两行:

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

问题是,这在我的Galaxy Nexus上完全运行,运行Android 4.2.2.应用程序启动,分辨率设置正确.

但是,当我在Nexus 7平板电脑上运行完全相同的应用程序,运行Android 5.1时,该应用程序会挂起电话setResolution().实际上它可以正常工作,但是第二次尝试运行它时会挂起 - 即使您完全退出应用程序,将其从正在运行的应用程序中删除,或重新启动设备.其他用户也报告了相同的错误,因此它不仅仅是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();
}
Run Code Online (Sandbox Code Playgroud)

查看日志,我可以看到线程卡synchronized(this)在线上.在该Object上同步的唯一另一件事是内部JavaCameraView.CameraWorker类,它是mThread上面代码中的变量,由JavaCameraView类启动:

(注意:此代码是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");
    }
}
Run Code Online (Sandbox Code Playgroud)

我已尝试使用该代码,将notify()更改为notifyAll(),并维护一个CameraWorker线程列表并加入每个线程.但无论如何,该应用程序仍然挂在disconnectCamera()通话中.

我的问题是:

  • 如何修改第三个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();
}
Run Code Online (Sandbox Code Playgroud)

然而,现在这个卡在相同的位置,甚至在我的Galaxy Nexus上,如果我在onCameraViewStarted()函数中设置分辨率,它也可以工作.我已经尝试将帧数增加到7甚至100,但我总是卡在同一个地方.

cyr*_*iel 5

在您的情况下,最重要的问题是,如果您根本不修改代码,它是否正常工作 - 您是否能够在不崩溃应用程序的情况下更改分辨率(通过菜单)?
如果是,答案很可能很简单 - 这与OpenCV中的错误一样,在Windows版本中:在更改相机分辨率或fps(很可能是任何属性)之前,您需要至少抓取一个(使用3-5来确定)更改此属性前的帧.
如果不是最有可能你自己无能为力 - 填写错误报告并等待评论.唯一的选择是使用其他库从相机抓取帧,然后将其转换为OpenCV对象.