2012-11-08 5 views
0

J'ai un problème concernant un projet réel utilisant Java, Kinect (OpenNI) et Processing.
Si j'utilise seulement Processing et Java tout fonctionne bien rien ne trébuche et je ne reçois aucune exception.
Mais si je prison le traitement Applet dans un JFrame (pour résoudre certains problèmes avec l'Applet Style traitement) Je suis le problème suivant:Kinect + Processing + JFrame java.lang.OutOfMemoryError

  • Toutes les 3 secondes les images kinect pend peu (ressemble à Java déblaie quoi que ce soit de la mémoire en utilisant le garbage collector)
  • au bout de 20 secondes, l'application se arrête et je reçois l'erreur suivante:

    Exception in thread "Animation Thread" java.lang.OutOfMemoryError: Java heap space 
    at java.awt.image.DataBufferInt.<init>(Unknown Source) 
    at java.awt.image.Raster.createPackedRaster(Unknown Source) 
    at java.awt.image.DirectColorModel.createCompatibleWritableRaster(Unknown Source) 
    at java.awt.image.BufferedImage.<init>(Unknown Source) 
    

Voici mon code pertinentes relatives à la visualisation:

public boolean drawGrayscaleImage(){  

    //init PApplet and build JFrame 
    GrayscalePApplet grayscalePApplet = new GrayscalePApplet(); 
    grayscalePApplet.init();   
    this.grayscaleJFrame = this.initFrame(grayscalePApplet); 

    //Set Uplink for PApplet and begin drawing 
    grayscalePApplet.setGraphicP(this);  

    return false; 
} 

Ici, la fonction de dessin de la classe traitement PApplet

public void draw(){ 

    if(graphicP != null){ 
     //creat the relevant image Buffers for java and Processing 
     BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_BYTE_GRAY);   
     PImage pimage = new PImage(image.getWidth(),image.getHeight(),PConstants.ARGB); 

     //fill up the databuffer using a converted Kinect Grayscale Image 
     DataBufferByte dataBuffer = new DataBufferByte(graphicP.getImage(ImageType.GRAYSCALE), this.imageWidth * this.imageHeight); 
     Raster raster = Raster.createPackedRaster(dataBuffer,imageWidth, imageHeight, 8, null); 
     image.setData(raster); 

     //draw image to Processing 
     image.getRGB(0, 0, pimage.width, pimage.height, pimage.pixels, 0, pimage.width); 
     pimage.updatePixels(); 
     image(pimage, 0, 0); 

     // null everything to get Garbagecollection to work (?) 
     image = null; 
     pimage = null; 
     dataBuffer = null; 
    } 
} 

Comment puis-je éviter que OutOfMemory Exception?
Qu'est-ce qui peut provoquer cette exception?

+0

augmenter la taille de segment http://wiki.eclipse.org/FAQ_How_do_I_increase_the_heap_size_available_to_Eclipse%3F –

+0

I augmenté la taille de heps (-vmargs -Xms512m -Xmx730m) mais cela n'a eu aucun effet sur mon problème. Eclipse me montre l'espace du tas mais il ne déborde pas. – Rubberducker

+0

L'exception est levée car votre machine virtuelle Java n'a plus de mémoire de tas. --- Puisque votre GC bloque le programme, puis manque de mémoire, je suppose que vous avez des problèmes de fuite de mémoire. --- Dans ce cas, augmenter simplement la taille du tas comme le suggère @Bhavik_Shan ne fera que masquer et retarder votre problème, et non le résoudre. Vous devriez plutôt déboguer votre programme, en vous concentrant principalement sur l'optimisation de l'utilisation de la mémoire. La chose la plus importante à faire est de vérifier si toute la mémoire temporaire est libérée, de préférence immédiatement dès qu'elle n'est plus utilisée. – XenoRo

Répondre

0

Depuis que je ne vois pas le code complet, je ne peux pas faire une hypothèse précise mais je pense le problème est ici:

BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_BYTE_GRAY);   
     PImage pimage = new PImage(image.getWidth(),image.getHeight(),PConstants.ARGB); 

     //fill up the databuffer using a converted Kinect Grayscale Image 
     DataBufferByte dataBuffer = new DataBufferByte(graphicP.getImage(ImageType.GRAYSCALE), this.imageWidth * this.imageHeight); 
     Raster raster = Raster.createPackedRaster(dataBuffer,imageWidth, imageHeight, 8, null); 
     image.setData(raster); 

Je ne suis pas sûr de ce que l'API Kinect vous utilisez (OpenNI/libfreenect), mais peu importe, vous ne devriez probablement pas créer une nouvelle image plusieurs fois par image (comme vous le faites dans draw()). Les images remplissent la mémoire assez rapidement et vous n'avez pas besoin de plusieurs images tout le temps, vous avez simplement besoin de deux images que vous continuez à mettre à jour. Par exemple, vous initialiser les images une fois dans setup() et mettre à jour les pixels de ces images dans draw()

De plus, si vous utilisez le traitement que je recommande d'avoir un regard sur les bibliothèques wrapper Kinect traitement comme SimpleOpenNI pour OpenNI ou dLibs (Win)/OpenKinect pour libfreenect. Il est beaucoup plus simple pour afficher l'image en profondeur avec l'un de ces:

Avec SimpleOpenNI:

import SimpleOpenNI.*; 

SimpleOpenNI ni; 

void setup(){ 
    ni = new SimpleOpenNI(this); 
    ni.enableDepth() 
    size(ni.depthWidth(), ni.depthHeight()); 
} 

void draw(){ 
    ni.update(); 
    image(context.depthImage(),0,0); 
} 

Avec dLibs freenect:

import dLibs.freenect.toolbox.*; 
import dLibs.freenect.constants.*; 
import dLibs.freenect.interfaces.*; 
import dLibs.freenect.*; 

Kinect kinect;      // main kinect-object 
KinectFrameDepth kinectDepth;  // depth frame 
PImage depthFrame; 

void setup(){ 
    size(640,480); 
    kinect = new Kinect(0); 
    kinectDepth = new KinectFrameDepth(DEPTH_FORMAT._11BIT_);// create a depth instance 
    kinectDepth.connect(kinect); //connect the created depth instance to the main kinect 
    depthFrame = createImage(DEPTH_FORMAT._11BIT_.getWidth(), DEPTH_FORMAT._11BIT_.getHeight(), RGB); 
} 
void draw(){ 
    assignPixels(depthFrame, kinectDepth); 
    image(depthFrame, 0, 0); 
} 
void assignPixels(PImage img, Pixelable kinectDev){ 
    img.loadPixels(); 
    img.pixels = kinectDev.getPixels(); // assign pixels of the kinect device to the image 
    img.updatePixels(); 
} 
void dispose(){ 
    Kinect.shutDown(); 
    super.dispose(); 
} 

Avec OpenKinect P5:

import org.openkinect.*; 
import org.openkinect.processing.*; 

Kinect kinect; 

void setup() { 
    size(640,480); 
    kinect = new Kinect(this); 
    kinect.start(); 
    kinect.enableDepth(true); 
} 

void draw() { 
    background(0); 
    image(kinect.getDepthImage(),0,0); 
} 

void stop() { 
    kinect.quit(); 
    super.stop(); 
} 

C'est à quel système d'exploitation et quelles sont les fonctionnalités dont vous avez besoin pour choisir le bon emballage de traitement pour vous.

simple openni échantillon SimpleOpenNI

diwi dlibs dLibs_freenect

OpenKinect P5

OpenKinect P5
+0

Merci beaucoup pour cette excellente réponse! Je vais vérifier vos suggestions et commenterai ici, si j'ai un résultat! Thy beaucoup :) – Rubberducker