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

标签 java opencv image-processing javacv omr

我正在使用 JavaCV(OpenCV 的 java 接口(interface))开发 OMR(光学标记识别)应用程序。该应用程序对于 200 个图像运行良好,但之后它无法在我的代码中为 IplImage 分配内存。当我尝试时,会出现分配错误克隆 imgx 并将其分配给 imgxc1。您能否建议对其进行编程修复?增加堆大小似乎是一个临时解决方案?

这是初始化代码(发生异常的地方):

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;
}

这是清理代码:

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

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

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

}

堆栈跟踪:

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)

最佳答案

你的代码看起来很奇怪。您将 IplImage 对象分配给变量,只是为了立即覆盖它们。在以下情况下,您还会泄漏至少一种可能的 native 资源:

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

使用 cvCreateImage 创建的原始 imgxc1 对象不再引用它,但您没有释放资源。

如果您不清楚 Java 中的引用如何工作,我建议您在继续工作之前先做一些工作。您将摆脱多余的双重赋值行,代码也会更加清晰。

编辑:因为我已经在这上面浪费了时间,所以让我们逐行查看 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
}

该代码显示了对 Java 的巨大误解,但如果不涉及 native 资源,它只会导致一些额外的对象创建,然后由垃圾收集器处理。

关于JavaCV内存不足,分配内存失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33276073/

相关文章:

image - Hessian 矩阵的特征向量和特征值

matlab - 绘制霍夫变换 MATLAB

image - 如何使用空间掩码限制光栅处理范围?

java - G1 old generation committed 内存突然增加,Eden size 减少

java - 我在 Scala 中可以做什么在 Java 中不能做的事情?

python,opencv,图像数组到二进制

qt - 无法在项目文件中包含OpenBR库文件

java - 为什么 Stack 在 JDK 中扩展了 Vector?

java - 如何双击打开 kotlin 类文件?

python - 提取Tensorflow对象检测API的图像对象