5

I'm trying to make a program that takes a picture from a webcam, and afterwards resizes it, converts it to HSV, and makes some thresholding on it, to find a specific color. After this is done, I use the thresholded image to find contours, and print the x,y coords of the different contours. This is repeated over and over, to make the processing from the webcam realtime.

It all works quite well, except for the fact that I am using up about 100 mb of RAM every 2 second it runs.

So far I have discovered that if I use a static picture, instead of the live images from the webcam, I can minimize the memory leak significantly, although still there is memory being consumed.

Below my code is:

public class Application {
private CaptureImage ci;
private ImageUtils iu;
private CanvasFrame canvasContours;

IplImage grabbedFrame;
IplImage resizedFrame;
IplImage thresholdedFrame;
IplImage clonedImage;

public Application(){
    ci = new CaptureImage();
    iu = new ImageUtils();
    canvasContours = new CanvasFrame("contours");

}

public void frameProcessing(){

    grabbedFrame = ci.grabImage();
    //below call used for testing purposes
    //grabbedFrame = (IplImage) opencv_highgui.cvLoadImage("testingImage.jpg");
    //cloning image due to highgui guidelines.
    clonedImage = opencv_core.cvCloneImage(grabbedFrame);
    resizedFrame = iu.resizeImage(clonedImage);

    opencv_core.cvReleaseImage(clonedImage);

    thresholdedFrame = iu.thresholdImage(resizedFrame);


    IplImage contoursFrame = iu.findContours(thresholdedFrame, resizedFrame);

    canvasContours.showImage(contoursFrame);


}
}

The grabImage is just the standard frameGrabber from javacv, which looks like this:

public class CaptureImage {
private final OpenCVFrameGrabber grabber;
private IplImage img = null;


public CaptureImage(){
    // 0-default camera, 1 - next...so on
            grabber = new OpenCVFrameGrabber(0);
            try {
                grabber.start();
            } catch (Exception e) {
                System.err.print("Failed to initialize camera");
                e.printStackTrace();
            }

}

public IplImage grabImage(){

    try {

    //A grabbed image from Logitech webcam is in following resolution: 1200x800px

        img = grabber.grab();



    } catch (Exception e) {

        e.printStackTrace();
    }
    return img;
}

I appreciate any help you can give me, and if you need any more information, please just ask!

/Jesper

Jesper Plantener
  • 229
  • 3
  • 16
  • And a little update, if I put just the grabber in it's own while (true) loop, there is no memory leak. So it's probably not the framegrabber itself that causes the problem. – Jesper Plantener Mar 10 '13 at 16:53
  • If you run `jmap -dump:format=b,file= ` (see [here](http://docs.oracle.com/javase/6/docs/technotes/tools/share/jmap.html)), and post the dump somewhere in zipped form, I'll have a look at it. – Ingo Kegel Mar 11 '13 at 08:41
  • I've just uploaded the dump file. You can download it here. http://speedy.sh/eaJ7a/javadump.zip – Jesper Plantener Mar 11 '13 at 09:20

1 Answers1

1

From your heap dump, the used memory is all byte and int arrays that are referenced from native code. Looking at your code I see that you only call cvReleaseImage for the cloned image and not for the original image.

Ingo Kegel
  • 46,523
  • 10
  • 71
  • 102
  • Yep that's right, the reason for this is that in the documentation for FrameGrabbers it is told that the image should not be released, this is done by the grabber itself. – Jesper Plantener Mar 11 '13 at 10:18
  • In any case it's memory allocated from the native library, so it is probably related to unreleased images. – Ingo Kegel Mar 11 '13 at 10:26
  • That is what I have been thinking as well. But the thing is, if I load an image, and do the processing on that static image instead of grabbing a new frame all the time, I still have a memory leak, however it is "only" about 30 mb/sek. – Jesper Plantener Mar 11 '13 at 10:31
  • WHere do you release resizedFrame and thresholdedFrame? – Ingo Kegel Mar 11 '13 at 10:45
  • For some reason, I got errors while trying to release those earlier on. However I can release those now without trouble. I am looking into all places that I return something without releasing right now, and it seems to do some good, since the memory leak has been significantly reduced. Not yet fully gone though. In my util class i do a 'CvMemStorage storage = CvMemStorage.create();' which I believe has something to do with it. Although the program crashes if I release it, so I gonna look into that. – Jesper Plantener Mar 11 '13 at 10:47
  • Alright I seem to have stabilized the memory. It's jumping a bit up and down, and might be loosing a few mb over time, but not much though, and it is acceptable at the moment. The is definately caused from unreleased images. Thanks for the help!. – Jesper Plantener Mar 11 '13 at 11:42