2015-10-22 2 views
0

Я разрабатываю приложение OMR (Optical Mark Recognition) с использованием JavaCV, java-интерфейса для OpenCV. Приложение работает отлично для 200 изображений, но после этого не удается выделить память для IplImage в моем коде Ошибка распределения возникает, когда я пытаюсь клонировать imgx и назначать его imgxc1.Кажется, вы предлагаете программное исправление для него? Увеличение размера кучи кажется временным решением?JavaCV Недостаточно памяти, не удалось выделить память

Вот код инициализации (где происходит исключение):

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) 
+0

Ошибка выглядит так, что проблема не была достигнута, но недостаточно RAM - Java захотела выделить больше, но ОС не смогла дать больше. –

+0

, когда эта ошибка возникла, баран был равен 80 процентам от общего количества 4 ГБ. Это не похоже на проблему с бараном. Приложение занимало 340 мб в диспетчере задач, когда счетчик страниц составлял 200. – afnan1992

+0

Это явно проблема с ОЗУ, и, как сказал @JiriTousek, а не куча Java, так что увеличение размера кучи даже не поможет. – Kayaman

ответ

3

Ваш код выглядит странно. Вы назначаете объекты IplImage своим переменным, чтобы их можно было мгновенно переписать. Вы также протекает по крайней мере, один предположительно нативный ресурс в следующем случае:

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

оригинальный imgxc1 объект, который был создан с cvCreateImage больше не имеет ссылок на него, но не освободить ресурсы.

Если вам неясно, как работают ссылки на 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, но если бы не было вовлечены местные ресурсы, это привело бы только в некоторых дополнительных созданий объектов, которые затем будут обработаны сборщиком мусора.

+0

Я освобождаю ссылку в методе release, но вы правы в отношении избыточных двойных заданий. – afnan1992

+0

@ afnan1992 Нет, вы этого не сделаете. У вас больше нет ссылки на оригинал 'imgxc1', поэтому вы не можете его освободить. Сборщик мусора освободил бы его в противном случае, но поскольку он имеет собственные ресурсы, он не может. Если вы намереваетесь создать надлежащее приложение из этого, я настоятельно рекомендую правильно понять основы. – Kayaman

+0

Использование собственных ресурсов делает его несколько запутанным. imgxc1 - переменная экземпляра, так почему бы мне не ссылаться на исходный imgxc1? Был бы рад, если бы вы могли обучить меня здесь. – afnan1992

Смежные вопросы