简体   繁体   English

JavaCV内存不足,分配内存失败

[英]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? 我正在使用JavaCV,OpenCV的Java接口开发OMR(光学标记识别)应用程序。该应用程序可以很好地运行200张图像,但是此后它无法在我的代码中为IplImage分配内存。当我尝试克隆imgx时出现分配错误并将其分配给imgxc1。您能提出一个针对程序的修复程序吗? 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)

Your code looks weird. 您的代码看起来很奇怪。 You're assigning IplImage objects to your variables, only to overwrite them instantly. 您正在将IplImage对象分配给变量,只是为了立即覆盖它们。 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. 使用cvCreateImage创建的原始imgxc1对象不再引用它,但是您没有释放资源。

If how references work in Java is unclear to you, I'd suggest you do some work on that before continuing with your work. 如果您不清楚Java中引用的工作方式,建议您在继续工作之前先做一些工作。 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. 编辑:由于我已经在此上浪费时间,让我们逐行通过init()

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. 该代码显示了对Java的巨大误解,但如果没有涉及本机资源,则只会导致一些额外的对象创建,然后由垃圾收集器处理这些对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM