Ask Your Question
1

Android app Force closed by memory leak

asked 2015-05-09 02:34:50 -0600

mikia gravatar image

Hey everyone. I'm trying to build a app,which can detect red color form input image , and do Hough line transform ,after sent the result to screen.

i think i finish the program,but the program will be Force closed,about every 30~50 sec.

i'm using opencv 2.4.10 (for android),and eclipse to build the program;

the program is revised from the OPENCV sample "example-tutorial-1-camerapreview", and i revised "public Mat onCameraFrame(CvCameraViewFrame inputFrame) " into below

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    Mat sourceimage = inputFrame.rgba();
    Imgproc.cvtColor(sourceimage , sourceimage, Imgproc.COLOR_RGBA2RGB);
    Imgproc.cvtColor(sourceimage , sourceimage, Imgproc.COLOR_BGR2HSV);

    Mat mRgba = new Mat();
    Mat lines = new Mat();
    Mat filter2= new Mat();

    Core.inRange(sourceimage, new Scalar(50, 70, 100), new Scalar(150, 250, 250), filter2);
    mRgba=filter2.clone();

    Imgproc.cvtColor(mRgba , mRgba, Imgproc.COLOR_GRAY2RGBA);
    Imgproc.Canny(filter2, filter2, 80, 100, 5, true);
    Imgproc.HoughLinesP(filter2, lines, 1, Math.PI/180, 125, 20, 20);
    for (int x = 0; x < lines.cols(); x++) 
    {
          double[] vec = lines.get(0, x);
          double x1 = vec[0], 
                 y1 = vec[1],
                 x2 = vec[2],
                 y2 = vec[3];
          Point start = new Point(x1, y1);
          Point end = new Point(x2, y2);

          Core.line(mRgba, start, end, new Scalar(255,0,0), 2); 
    }
    return mRgba;
}

I think " Core.inRange(sourceimage, new Scalar(50, 70, 100), new Scalar(150, 250, 250), filter2);" will cause the program Force closed,because when i trying to avoid program Force closed,i have removed "Core.inRange(sourceimage, new Scalar(50, 70, 100), new Scalar(150, 250, 250), filter2);" from program,though program can't show image to screen ,but the program won't be Force closed.

Does anyone know how to solve this problem? maybe the problem is not caused by "Core.inRange"

finally ,i'm apology about my poor English,and thanks for your response.

edit retag flag offensive close merge delete

3 answers

Sort by ยป oldest newest most voted
2

answered 2015-05-10 04:25:07 -0600

berak gravatar image

updated 2015-05-10 04:27:25 -0600

i'd rather make all temporary Mat's class members, and allocate them only once.

public class MyActivity extends Activity implements CvCameraViewListener2 {
    CameraBridgeViewBase mOpenCvCameraView;
    Mat mRgba, mGray, mHsv;
   ...
}

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    Mat rgba = inputFrame.rgba();
    // convert to hsv, get binary img:
    Imgproc.cvtColor(rgba , mHsv, Imgproc.COLOR_BGR2HSV);
    Core.inRange(mHsv, new Scalar(50, 70, 100), new Scalar(150, 250, 250), mGray);

    // save a rgba copy of the binary for drawing later: 
    Imgproc.cvtColor(mGray , mRgba, Imgproc.COLOR_GRAY2RGBA);
    // can do Canny in-place:
    Imgproc.Canny(mGray, mGray, 80, 100, 5, true);
    // now, we *need* a new here !
    Mat lines = new Mat();
    Imgproc.HoughLinesP(mGray, lines, 1, Math.PI/180, 125, 20, 20);
    for (int x = 0; x < lines.cols(); x++) 
    {
          double[] vec = lines.get(0, x);
          double x1 = vec[0], 
                 y1 = vec[1],
                 x2 = vec[2],
                 y2 = vec[3];
          Point start = new Point(x1, y1);
          Point end = new Point(x2, y2);

          Core.line(mRgba, start, end, new Scalar(255,0,0), 2); 
    }
    lines.release(); // !!
    return mRgba;
}

public void onCameraViewStarted(int width, int height) {
    // allocate the temporary Mat's only once:
    mGray = new Mat(height,width,CvType.CV_8U);
    mHsv = new Mat(height,width,CvType.CV_8UC3);
    mRgba = new Mat(height,width,CvType.CV_8UC4);
}
edit flag offensive delete link more
1

answered 2020-07-21 15:32:41 -0600

necip gravatar image

Make sure there's no any Mat describing method in onCameraFrame function. I assume it's because in every frame operation it creates new Mat without closing previous and forces to a memory leak. (didnt try to code, but having similar issue is solved this method)

public class ... {

  Mat sourceimage, mRgba, lines, filter2;

  public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    sourceimage = inputFrame.rgba();
    Imgproc.cvtColor(sourceimage , sourceimage, Imgproc.COLOR_RGBA2RGB);
    Imgproc.cvtColor(sourceimage , sourceimage, Imgproc.COLOR_BGR2HSV);

    mRgba = new Mat();
    lines = new Mat();
    filter2= new Mat();

    Core.inRange(sourceimage, new Scalar(50, 70, 100), new Scalar(150, 250, 250), filter2);
    mRgba=filter2.clone();

    Imgproc.cvtColor(mRgba , mRgba, Imgproc.COLOR_GRAY2RGBA);
    Imgproc.Canny(filter2, filter2, 80, 100, 5, true);
    Imgproc.HoughLinesP(filter2, lines, 1, Math.PI/180, 125, 20, 20);
    for (int x = 0; x < lines.cols(); x++) 
    {
          double[] vec = lines.get(0, x);
          double x1 = vec[0], 
                 y1 = vec[1],
                 x2 = vec[2],
                 y2 = vec[3];
          Point start = new Point(x1, y1);
          Point end = new Point(x2, y2);

          Core.line(mRgba, start, end, new Scalar(255,0,0), 2); 
    }
    return mRgba;
  }
}
edit flag offensive delete link more

Comments

+1 for encouraging contribution ( i have no idea about correct answer)

sturkmen gravatar imagesturkmen ( 2020-07-22 00:44:18 -0600 )edit
1

answered 2015-05-09 06:17:27 -0600

updated 2015-05-10 03:59:05 -0600

Your problem is caused by explicitly stating the new operator. If you do so than the garbage collector will not automatically delete your objects once they run out of scope. You can avoid this by changing your code to:

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    Mat sourceimage = inputFrame.rgba();
    Imgproc.cvtColor(sourceimage , sourceimage, Imgproc.COLOR_RGBA2RGB);
    Imgproc.cvtColor(sourceimage , sourceimage, Imgproc.COLOR_BGR2HSV);

    Mat mRgba, lines, filter2;

    Core.inRange(sourceimage, new Scalar(50, 70, 100), new Scalar(150, 250, 250), filter2);
    mRgba=filter2.clone();

    Imgproc.cvtColor(mRgba , mRgba, Imgproc.COLOR_GRAY2RGBA);
    Imgproc.Canny(filter2, filter2, 80, 100, 5, true);
    Imgproc.HoughLinesP(filter2, lines, 1, Math.PI/180, 125, 20, 20);
    for (int x = 0; x < lines.cols(); x++) 
    {
          double[] vec = lines.get(0, x);
          double x1 = vec[0], 
                 y1 = vec[1],
                 x2 = vec[2],
                 y2 = vec[3];
          Point start (x1, y1);
          Point end (x2, y2);

          Core.line(mRgba, start, end, new Scalar(255,0,0), 2); 
    }
    return mRgba;
}

And the memory leaking should be a thing of the past. Other way is to explicitly delete every object yourself!

edit flag offensive delete link more

Comments

1

hmm, calling new less often is obviously the answer, but you can't do away with it totally in java, e.g. ommitting it for lines will throw a null pointer exception.

berak gravatar imageberak ( 2015-05-10 03:34:11 -0600 )edit

@berak, since I only have cpp experience I removed em all. Looks better now?

StevenPuttemans gravatar imageStevenPuttemans ( 2015-05-10 03:59:33 -0600 )edit
1

I was try to allocate Mat only once,but fault(maybe i'm do something wrong) Now i solve the problem of memory leak by the command System.gc

mikia gravatar imagemikia ( 2015-05-10 10:05:05 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-05-09 02:34:50 -0600

Seen: 2,566 times

Last updated: Jul 21 '20