由于相机预览而产生 OutOfMemoryError
Posted
技术标签:
【中文标题】由于相机预览而产生 OutOfMemoryError【英文标题】:OutOfMemoryError generated due to camera preview 【发布时间】:2017-02-16 12:02:09 【问题描述】:我设法使用 opencv 打开了 android 相机。但是当我使用修复相机方向的代码时 - “请参阅下面 onCameraFrame(..) 方法中提到的代码” - 应用程序在几秒钟后崩溃并且 logcat 在“logcat 部分”中生成 belwo 发布的消息。
解决这个问题:
我尝试使用 SystemClock.sleep 强制应用延迟一段时间,但这不是一个好的解决方案,因为它会延迟相机预览
我尝试尽可能减小帧大小,因此我使用 mOpenCvCameraView.setMaxFrameSize(320, 240) 将其设置为 320x240,“在代码部分中提到了”。但是这个解决方案设法让相机预览时间更长了几分钟,但最终应用程序也崩溃了。
请告诉我这种情况的正确解决方案是什么以及如何避免它?
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;
【问题讨论】:
【参考方案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;
【讨论】:
2020 年的最新解决方案:***.com/a/64493151/12305715(但仍然是解决我问题的好解决方案!!!)【参考方案2】:根据我的经验,OpenCV4Android 在垃圾收集矩阵方面非常非常糟糕,所以我会将每个矩阵保存在单独的变量中并手动清理它们。
@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
【讨论】:
你能告诉我什么是modified.release吗?? 它是从相机拍摄的帧矩阵。但是它使用matToBitmap
转换为位图,因此不再需要此矩阵。
你能解释一下你的代码和我上面发布的代码之间的区别吗?!谢谢
当然,首先您使用帧矩阵初始化 mRGBa,这不是必需的,因为我们在下一条语句中将翻转矩阵放在那里。然后你在 resize 中使用与输入和输出相同的矩阵(这没有什么问题,但正如我所说,GC 在 Android 的 OpenCV 中非常糟糕)。在我的代码中,每个矩阵只初始化一次,并且在其生命周期内不会被修改。
不行,因为我们返回mat2,所以不能释放。【参考方案3】:
您的 cpp 文件中应该存在一个循环,该循环会在每次调用时连续捕获图像。当您将图像大小调整为较低的分辨率时,应用运行时间会稍长一些,但仍会导致内存泄漏和崩溃。
您可以采取一种方法,在处理后清除每个图像并捕获新图像,这样您最终可能不会使用所有 RAM 空间。推荐你this link。
【讨论】:
在您的 c++ 文件中执行发布任务。查看错误,它指的是您的 cpp 文件。以上是关于由于相机预览而产生 OutOfMemoryError的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法知道正确的相机预览尺寸是不是与面部检测器兼容(产生检测到的面部)