setText的内存泄漏问题(可能?)

时间:2014-07-17 14:55:14

标签: java android opencv memory-leaks

我正在开发一个基本应用程序,该应用程序使用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);
            }
        });
    }
}

1 个答案:

答案 0 :(得分:0)

在过去创建内存密集型应用时,我不得不手动增加应用访问的内存量。可能不一定存在OOM错误,但应用程序可能只是内存非常密集。

尝试将其添加到清单中的应用标记:

android:largeHeap="true"

希望这有助于:)