java - Android4OpenCV : setting resolution at startup

标签 java android opencv opencv4android

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

我正在查看 3rd example ,它允许用户通过菜单更改分辨率。我想修改该示例以在启动时更改分辨率,而不是要求用户浏览菜单。为此,我只需向空的 onCameraViewStarted() 函数添加两行:

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() 时挂起。实际上它一次运行正常,但第二次尝试运行它时挂起 - 即使您完全退出应用程序,将其从正在运行的应用程序中删除,或重新启动设备。其他用户也报告了同样的错误,所以它不仅仅是 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.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");
    }
}

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

我的问题是:

  • 如何修改第三个 OpenCV4Android 示例,以便在启动时设置其分辨率?

  • 导致应用挂起的原因是什么?

  • 为什么这在某些设备上有效而在其他设备上无效?

编辑:我没有收到任何评论或答案,所以我已经交叉发布到 OpenCV 论坛 here .

编辑 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,但我总是卡在同一个地方。

最佳答案

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

关于java - Android4OpenCV : setting resolution at startup,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30112935/

相关文章:

android - com.android.volley.NoConnectionError - 带有 Charles Proxy 的 Android 模拟器

java - 如果语句没有按预期工作

python - OpenCV:如何计算白色区域的面积?

java - 为什么我没有获得正常运行的 JScrollPane?

java - 将两个数组放入 Jtable 行

java - JMesa:对表进行预排序

java - 使用 JDBC 从 Oracle 获取唯一索引的所有外键

android - 在 Navigation Drawer Android 上添加 EditText

java - Imgproc.findContours()的用法

android - opencv 2.4.4 for android 不工作