我正在开发一个基本应用程序,该应用程序使用OpenCV实时告诉用户视频输入中的轮廓量。我有这个工作,但运行应用程序约一分钟关闭,没有logcat错误。我是一名新开发人员,但通过一些研究认为这是一个内存泄漏问题。我认为这与在每个视频帧上设置文本有关。这是我的代码:
import java.util.ArrayList;
import java.util.List;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.JavaCameraView;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.TextView;
public class MainActivity extends Activity implements CvCameraViewListener2 {
static {
if (!OpenCVLoader.initDebug()) {
Log.d("ERROR", "Unable to load OpenCV");
}
else {
Log.d("SUCCESS", "OpenCV loaded");
}
}
private TextView contourCount;
//TAG for log
private static final String TAG = "Contour Count";
//Mats for image processing
private Mat mRgba;
private Mat mGray;
//Declare the cameraview
private JavaCameraView openCvCameraView;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
//OpenCv
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
//Turn on cameraview
openCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
//OnResume handling
@Override
public void onResume()
{
super.onResume();
openCvCameraView.enableView();
}
//OnCreate tasks
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
//Keep the screen on while app is running
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//Set layout and initialize cameraView
setContentView(R.layout.fragment_main);
openCvCameraView = (JavaCameraView) findViewById(R.id.HelloOpenCvView);
openCvCameraView.setVisibility(SurfaceView.VISIBLE);
openCvCameraView.setCvCameraViewListener(this);
openCvCameraView.enableView();
}
//Handling onPause tasks - Disable Camera
@Override
public void onPause()
{
super.onPause();
if (openCvCameraView != null)
openCvCameraView.disableView();
}
//Handling onDestroy tasks - Disable Camera
public void onDestroy() {
super.onDestroy();
if (openCvCameraView != null)
openCvCameraView.disableView();
}
//New Mats for first onFrame
public void onCameraViewStarted(int width, int height) {
//Initialization of variables used for video analysis
mGray = new Mat();
mRgba = new Mat();
}
//Release the Mats when camera is stopped
public void onCameraViewStopped() {
mGray.release();
mRgba.release();
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
Mat imageHSV = new Mat(mRgba.size(), Core.DEPTH_MASK_8U);
Mat imageBlurr = new Mat(mRgba.size(), Core.DEPTH_MASK_8U);
Mat imageA = new Mat(mRgba.size(), Core.DEPTH_MASK_ALL);
Imgproc.cvtColor(mRgba, imageHSV, Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(imageHSV, imageBlurr, new Size(5,5), 0);
Imgproc.adaptiveThreshold(imageBlurr, imageA, 255,Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY,7, 5);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(imageA, contours, new Mat(), Imgproc.RETR_EXTERNAL,Imgproc.CHAIN_APPROX_SIMPLE);
setContours(contours.size());
return mRgba;
}
public void setContours(final int level) {
runOnUiThread(new Runnable() {
@Override
public void run() {
contourCount = (TextView) findViewById(R.id.contourLevel);
contourCount.setText("" + level);
}
});
}
}
如果我在onCreate()
中声明了contourCount,则会出现同样的问题。我不确定它是否与setContours()
的方法调用中的等级最终有关,但我也尝试使用onCreate()
中声明的处理程序解决此问题并发送contours.size()
内onCameraFrame()
的消息,但这也会导致同样的问题。我究竟做错了什么?我怎么能在将来避免这种情况?我是新手,所以请详细解释问题和未来的回避。
提前谢谢! :)
编辑已解决:
想出来。感谢所有贡献的人。以下是有兴趣的人或将来有同样问题的人的工作代码!
修复来自释放onCameraFrame中使用的垫
import java.util.ArrayList;
import java.util.List;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.JavaCameraView;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.TextView;
public class MainActivity extends Activity implements CvCameraViewListener2 {
static {
if (!OpenCVLoader.initDebug()) {
Log.d("ERROR", "Unable to load OpenCV");
}
else {
Log.d("SUCCESS", "OpenCV loaded");
}
}
//TAG for log
private static final String TAG = "Contour Count";
//Mats for image processing
private Mat mRgba;
private Mat mGray;
private Mat imageHSV;
private Mat imageBlurr;
private Mat imageA;
private Mat hierarchy;
//Declare the cameraview
private JavaCameraView openCvCameraView;
private static String level;
private static TextView contourCount;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
//OpenCv
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
//Turn on cameraview
openCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
//OnResume handling
@Override
public void onResume()
{
super.onResume();
openCvCameraView.enableView();
}
//OnCreate tasks
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
//Keep the screen on while app is running
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//Set layout and initialize cameraView
setContentView(R.layout.fragment_main);
openCvCameraView = (JavaCameraView) findViewById(R.id.HelloOpenCvView);
openCvCameraView.setVisibility(SurfaceView.VISIBLE);
openCvCameraView.setCvCameraViewListener(this);
openCvCameraView.enableView();
contourCount = (TextView) findViewById(R.id.contourLevel);
}
//Handling onPause tasks - Disable Camera
@Override
public void onPause()
{
super.onPause();
if (openCvCameraView != null)
openCvCameraView.disableView();
}
//Handling onDestroy tasks - Disable Camera
public void onDestroy() {
super.onDestroy();
if (openCvCameraView != null)
openCvCameraView.disableView();
}
//New Mats for first onFrame
public void onCameraViewStarted(int width, int height) {
//Initialization of variables used for video analysis
mGray = new Mat();
mRgba = new Mat();
}
//Release the Mats when camera is stopped
public void onCameraViewStopped() {
mGray.release();
mRgba.release();
}
//onCameraFrame image processing
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
imageHSV = new Mat(mRgba.size(), Core.DEPTH_MASK_8U);
imageBlurr = new Mat(mRgba.size(), Core.DEPTH_MASK_8U);
imageA = new Mat(mRgba.size(), Core.DEPTH_MASK_ALL);
hierarchy = new Mat();
Imgproc.cvtColor(mRgba, imageHSV, Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(imageHSV, imageBlurr, new Size(5,5), 0);
Imgproc.adaptiveThreshold(imageBlurr, imageA, 255,Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY,7, 5);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(imageA, contours, hierarchy, Imgproc.RETR_EXTERNAL,Imgproc.CHAIN_APPROX_SIMPLE);
//Imgproc.findContours(imageA, contours, new Mat(), Imgproc.RETR_LIST,Imgproc.CHAIN_APPROX_SIMPLE);
level = "" + contours.size();
setContour();
imageHSV.release();
imageBlurr.release();
imageA.release();
hierarchy.release();
return mRgba;
}
public void setContour() {
runOnUiThread(new Runnable() {
@Override
public void run() {
contourCount.setText(level);
}
});
}
}
答案 0 :(得分:0)
在过去创建内存密集型应用时,我不得不手动增加应用访问的内存量。可能不一定存在OOM错误,但应用程序可能只是内存非常密集。
尝试将其添加到清单中的应用标记:
android:largeHeap="true"
希望这有助于:)