由于相机预览而生成OutOfMemoryError

时间:2016-10-07 13:07:04

标签: android opencv3.0 mat opencv4android camera-view

我设法使用opencv打开Android相机。但当我使用修复相机方向的代码 - “在onCameraFrame(..)方法中看到下面提到的代码” - 几秒钟后应用程序崩溃和logcat 在“logcat部分”中生成belwo发布的消息。

要解决此问题:

  1. 我试图使用SystemClock.sleep来强制App使用一段时间,但这不是一个好的解决方案,因为它会延迟相机预览

  2. 我试图尽可能地减小帧大小,所以我使用mOpenCvCameraView.setMaxFrameSize(320,240)将其设置为320x240“在代码部分提到了belwo”。但是这个解决方案设法让相机预览时间延长了几分钟,但最终App也崩溃了。

  3. 请告诉我这种情况的正确解决方案是什么以及如何避免?

    logcat的

    10-07 14:42:43.445 30510-31656/com.example.bak.opencvcamera_00 E/cv::error(): OpenCV Error: Insufficient memory (Failed to allocate 307200 bytes) in void* cv::OutOfMemoryError(size_t), file /home/maksim/workspace/android-pack/opencv/modules/core/src/alloc.cpp, line 52
    10-07 14:42:43.445 30510-31656/com.example.bak.opencvcamera_00 E/cv::error(): OpenCV Error: Assertion failed (u != 0) in void cv::Mat::create(int, const int*, int), file /home/maksim/workspace/android-pack/opencv/modules/core/src/matrix.cpp, line 411
    10-07 14:42:43.450 30510-31656/com.example.bak.opencvcamera_00 E/org.opencv.core.Mat: Mat::n_1t() caught cv::Exception: /home/maksim/workspace/android-pack/opencv/modules/core/src/matrix.cpp:411: error: (-215) u != 0 in function void cv::Mat::create(int, const int*, int)
    10-07 14:42:43.450 30510-31656/com.example.bak.opencvcamera_00 E/AndroidRuntime: FATAL EXCEPTION: Thread-9334
    Process: com.example.bak.opencvcamera_00, PID: 30510
    CvException [org.opencv.core.CvException: cv::Exception: /home/maksim/workspace/android-pack/opencv/modules/core/src/matrix.cpp:411: error: (-215) u != 0 in function void cv::Mat::create(int, const int*, int)
    at org.opencv.core.Mat.n_t(Native Method)
    at org.opencv.core.Mat.t(Mat.java:852)
    at com.example.bak.opencvcamera_00.MainActivity.onCameraFrame(MainActivity.java:109)
    at org.opencv.android.CameraBridgeViewBase.deliverAndDrawFrame(CameraBridgeViewBase.java:391)
    at org.opencv.android.JavaCameraView$CameraWorker.run(JavaCameraView.java:350)
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    
        setContentView(R.layout.activity_main);
        mOpenCvCameraView = (JavaCameraView) findViewById(R.id.surfaceView);
        mOpenCvCameraView.setOnTouchListener(this);
        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
        mOpenCvCameraView.setCvCameraViewListener(this);
        mOpenCvCameraView.setMaxFrameSize(320, 240);
    }
    ...
    ...
    ...
    @Override
    public Mat onCameraFrame(Mat inputFrame) {
        mRgbaT = inputFrame.t();
        Core.flip(inputFrame.t(), mRgbaT, 1);
        Imgproc.resize(mRgbaT, mRgbaT, inputFrame.size());
        return mRgbaT;
    }
    

    更新

    我修改了下面的方法,mRgbaT被声明为一个字段,我在捕获一个新帧后清除它的内容......但问题仍然存在

    @Override
    public Mat onCameraFrame(Mat inputFrame) {
    
        if (mRgbaT != null) {
            mRgbaT.release();
        }
    
        mRgbaT = inputFrame.t();
        Core.flip(inputFrame.t(), mRgbaT, 1);
        Imgproc.resize(mRgbaT, mRgbaT, inputFrame.size());
        return mRgbaT;
    }
    

3 个答案:

答案 0 :(得分:1)

根据我的经验,OpenCV4Android在垃圾收集Matrix中确实非常糟糕,所以我会将每个矩阵保存在单独的变量中并手动清理它们。

@Override
public Mat onCameraFrame(Mat inputFrame) {

    Matrix mat1 = new Mat();
    Matrix mat2 = new Mat();

    Core.flip(inputFrame.t(), mat1, 1);
    Imgproc.resize(mat1, mat2, inputFrame.size());

    mat1.release();
    inputFrame.release();

    return mat2;
}

如果您使用源代码形式的OpenCV4Android,我还建议您添加modified.release(); here

答案 1 :(得分:1)

我通过避免执行两次矩阵转置操作来解决它,如下面的代码所示:

@Override
public Mat onCameraFrame(Mat inputFrame) {
    if (mRgbaT != null) {
        mRgbaT.release();
    }

    mRgbaT = inputFrame.t();
    Core.flip(mRgbaT, mRgbaT, 1);
    Imgproc.resize(mRgbaT, mRgbaT, inputFrame.size());
    return mRgbaT;
}

答案 2 :(得分:0)

cpp文件中应该存在一个循环,它会在每次调用时连续捕获图像。当您将图像调整为较低分辨率时,应用程序会运行一段时间,但仍然会导致内存泄漏并崩溃。

您可以制作一种方法,在处理后清除每个图像并捕获一个新图像,这样您就不会最终使用所有RAM空间。引用您this link