afnan1992
afnan1992

Reputation: 57

JavaCV Insufficient memory, failed to allocate memory

I am developing an OMR(Optical Mark Recognition) application using JavaCV,java interface for OpenCV.The application runs fine for 200 images but after that it fails to allocate memory for IplImage in my code.The allocation error comes when I try to clone imgx and assign it to imgxc1.Can you please suggest a programmatic fix for it? Increasing the heap size seems to be a temporary solution?

Here is the initialization code(where the exception occurs):

protected boolean init () throws UnableToLoadImage{
    imgx = new IplImage();
    imgxc1 = new IplImage();
    imgxd1 = new IplImage();
    imgx = cvLoadImage(path+DR+filename);
    if(imgx == null)throw new UnableToLoadImage(path+DR+filename);
    //cvSaveImage("debug/"+filename, imgx);
    imgxc1 = cvCreateImage(cvGetSize(imgx), imgx.depth(), imgx.nChannels());
    imgxc1 = imgx.clone();//error comes here
    imgxd1 = cvCreateImage(cvGetSize(imgx), IPL_DEPTH_8U, 1);
    cvCvtColor(imgxc1, imgxd1, CV_BGR2GRAY);
    return (imgx != null && imgxc1 != null && imgxd1 != null)?true:false;
}

Here is the cleaning up code:

public void release() {
    if(imgx != null){

        imgx.release();
        imgxc1.release();
        imgxd1.release();

        cvReleaseImage(imgx);
        cvReleaseImage(imgxc1);
        cvReleaseImage(imgxd1);
    }

}

Stack trace:

OpenCV Error: Insufficient memory (Failed to allocate 6454368 bytes) in cv::OutOfMemoryError, file ..\..\..\..\opencv\modules\core\src\alloc.cpp, line 52

at org.bytedeco.javacpp.opencv_core.cvCloneImage(Native Method)
at org.bytedeco.javacpp.helper.opencv_core$AbstractIplImage.clone(opencv_core.java:1005)
at com.omr.app.OmrModel.init(OmrModel.java:200)
at com.omr.app.OmrController$2.doInBackground(OmrController.java:328)
at com.omr.app.OmrController$2.doInBackground(OmrController.java:1)
at javax.swing.SwingWorker$1.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at javax.swing.SwingWorker.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Upvotes: 0

Views: 926

Answers (1)

Kayaman
Kayaman

Reputation: 73568

Your code looks weird. You're assigning IplImage objects to your variables, only to overwrite them instantly. You're also leaking at least one presumably native resource in the following case:

imgxc1 = cvCreateImage(cvGetSize(imgx), imgx.depth(), imgx.nChannels());
imgxc1 = imgx.clone();//error comes here

The original imgxc1 object that was created with cvCreateImage has no longer references to it, but you didn't release the resources.

If how references work in Java is unclear to you, I'd suggest you do some work on that before continuing with your work. You'll get rid of your redundant double assignment lines and the code will be clearer too.

Edit: Since I've already wasted time on this, let's go through init() line by line.

protected boolean init () throws UnableToLoadImage{
    imgx = new IplImage();    // Create a new IplImage() even though we won't use it

    imgxc1 = new IplImage();  // Same here. Just food for the garbage collector

    imgxd1 = new IplImage();  // Third completely unnecessary object creation

    imgx = cvLoadImage(path+DR+filename);  // Load an image, the previously created object in imgx is now GC food

    if(imgx == null)throw new UnableToLoadImage(path+DR+filename);
    //cvSaveImage("debug/"+filename, imgx);

    imgxc1 = cvCreateImage(cvGetSize(imgx), imgx.depth(), imgx.nChannels());  // Create an image with native resources, previous object is GC food

    imgxc1 = imgx.clone();    // Third time assignment to imgxc1, previous object isn't GC food since it holds native resources
    imgxd1 = cvCreateImage(cvGetSize(imgx), IPL_DEPTH_8U, 1);  // The first proper use of cvCreateImage
    cvCvtColor(imgxc1, imgxd1, CV_BGR2GRAY);  // Presumably ok
    return (imgx != null && imgxc1 != null && imgxd1 != null)?true:false;  // Doesn't need the ternary operator at all
}

The code shows a huge misunderstanding of Java, but if there hadn't been native resources involved, it would only result in some extra object creations which would then be handled by the garbage collector.

Upvotes: 3

Related Questions