2013-03-10 34 views
5

Próbuję zrobić program, który robi zdjęcie z kamery internetowej, a następnie zmienia rozmiar, konwertuje go na HSV i wykonuje na nim progowanie, aby znaleźć określony kolor. Po wykonaniu tej czynności wykorzystuję obraz progowy do znajdowania konturów i drukowania współrzędnych x, y różnych konturów. Powtarza się to wielokrotnie, aby przetwarzanie z kamery internetowej odbywało się w czasie rzeczywistym.Wyciek pamięci w javacv

Wszystko działa całkiem dobrze, z wyjątkiem faktu, że zużywa około 100 MB pamięci RAM co 2 sekundy, że działa.

Do tej pory odkryłem, że jeśli użyję statycznego obrazu, zamiast obrazów na żywo z kamery internetowej, mogę znacznie zminimalizować wyciek pamięci, chociaż nadal jest zużywana pamięć.

Poniżej mojego kodu jest:

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


} 
} 

grabImage jest po prostu średnia framegrabber z javacv, który wygląda tak:

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

Doceniam jakiejkolwiek pomocy możesz mi dać, a jeśli potrzebujesz więcej informacji, proszę zapytaj!

/Jesper

+0

I trochę aktualizacji, jeśli umieściłem tylko grabber w jego własnej pętli while (true), nie ma wycieku pamięci. Więc prawdopodobnie to nie sam framegrabber powoduje problem. –

+0

Jeśli uruchomisz 'jmap-dump: format = b, file = ' (zobacz [tutaj] (http://docs.oracle.com/javase/6/docs/technotes/tools/share/jmap.html)), i opublikuj zrzut gdzieś w spakowanej formie, przyjrzę się temu. –

+0

Właśnie przesłałem plik zrzutu. Możesz pobrać go tutaj. http://speedy.sh/eaJ7a/javadump.zip –

Odpowiedz

1

ze swojego sterty wysypisko, wybranej pamięci jest cały bajt int i tablice, do których odwołują się od natywnego kodu. Patrząc na twój kod widzę, że nazywasz tylko cvReleaseImage dla sklonowanego obrazu, a nie dla oryginalnego obrazu.

+0

Tak, to prawda, powodem jest to, że w dokumentacji dla FrameGrabbers mówi się, że obraz nie powinien zostać zwolniony, robi to sam grabber. –

+0

W każdym razie jest to pamięć przydzielona z biblioteki macierzystej, więc jest prawdopodobnie związana z niewydanymi obrazami. –

+0

Tak też myślałem. Ale chodzi o to, że jeśli wczytam obraz i wykonuję przetwarzanie na tym statycznym obrazie, zamiast chwytać nową ramkę przez cały czas, wciąż mam wyciek pamięci, jednak jest to "tylko" około 30 mb/sek. –