2013-03-10 16 views
5

Ich versuche, ein Programm zu machen, das ein Bild von einer Webcam aufnimmt und anschließend die Größe ändert, es in HSV konvertiert und einige Schwellenwerte darauf legt, um eine bestimmte Farbe zu finden. Danach benutze ich das mit einem Schwellenwert versehene Bild, um Konturen zu finden, und drucke die x, y-Koordinaten der verschiedenen Konturen. Dies wird immer wieder wiederholt, um die Verarbeitung von der Webcam in Echtzeit zu ermöglichen.Speicherleck in javacv

Es funktioniert alles ganz gut, außer für die Tatsache, dass ich etwa 100 MB RAM alle 2 Sekunden verbraucht es läuft.

Bisher habe ich entdeckt, dass wenn ich ein statisches Bild anstelle der Live-Bilder von der Webcam verwende, ich das Speicherleck signifikant minimieren kann, obwohl immer noch Speicher verbraucht wird.

Unten ist mein Code:

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


} 
} 

Der Grabimage nur die Standard-Framegrabber von javacv ist, die wie folgt aussieht:

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

ich jede Hilfe dankbar Sie mir geben können, und wenn Sie brauche mehr Informationen, bitte einfach fragen!

/Jesper

+0

Und ein kleines Update, wenn ich nur den Grabber in seiner eigenen Weile (wahr) Schleife, gibt es kein Speicherleck. Es ist also wahrscheinlich nicht der Framegrabber selbst, der das Problem verursacht. –

+0

Wenn Sie 'jmap -dump: format = b, file = ' ausführen (siehe [hier] (http://docs.oracle.com/javase/6/docs/technotes/tools/share/jmap.html)), und poste den Speicher irgendwo in gezippter Form, ich werde es mir ansehen. –

+0

Ich habe gerade die Dump-Datei hochgeladen. Sie können es hier herunterladen. http://speedy.sh/eaJ7a/javadump.zip –

Antwort

1

Von Ihrem Heapdump, ist der verwendete Speicher alle Byte und int-Arrays, die von nativen Code referenziert werden. Wenn Sie Ihren Code betrachten, sehe ich, dass Sie nur cvReleaseImage für das geklonte Bild und nicht für das Originalbild aufrufen.

+0

Ja, das ist richtig, der Grund dafür ist, dass in der Dokumentation für FrameGrabbers gesagt wird, dass das Bild nicht freigegeben werden soll, dies wird vom Grabber selbst gemacht. –

+0

In jedem Fall ist es Speicher aus der nativen Bibliothek zugeordnet, so ist es wahrscheinlich mit nicht freigegebenen Bildern verwandt. –

+0

Das habe ich mir auch gedacht. Aber die Sache ist, wenn ich ein Bild lade, und die Verarbeitung auf diesem statischen Bild mache, anstatt die ganze Zeit einen neuen Rahmen zu ergattern, habe ich immer noch ein Speicherleck, allerdings ist es "nur" ungefähr 30 mb/sek. –