2012-11-08 56 views
0

我對使用Java,Kinect(OpenNI)和Processing的實際項目存在問題。
如果我只使用Processing和Java,一切正常,沒有什麼是絆腳石,我也沒有例外。
但是,如果我坐牢的一個JFrame的處理小程序(解決一些問題處理的小程序風格)我有以下問題:Kinect + Processing + JFrame java.lang.OutOfMemoryError

  • 每3秒Kinect的圖像不久掛起(看起來像Java被清除任何東西了使用垃圾收集器)
  • 20秒後停止的應用的內存,我得到以下錯誤:

    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) 
    

這是我的相關代碼對於可視化:

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

這裏從處理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; 
    } 
} 

我怎樣才能防止內存溢出的異常繪圖功能?
什麼可能導致異常?

+0

增加堆大小http://wiki.eclipse.org/FAQ_How_do_I_increase_the_heap_size_available_to_Eclipse%3F –

+0

我增加HEPS大小( -vmargs -Xms512m -Xmx730m)但它對我的問題沒有影響。 Eclipse會顯示堆空間,但不會溢出。 – Rubberducker

+0

由於JVM的堆內存不足,正在引發異常。 ---由於你的GC正在讓程序掛起,然後內存不足,我懷疑你有內存泄漏問題。 ---在這種情況下,簡單地增加@Bhavik_Shan提示的堆大小將只會掩蓋和延遲您的問題,而不是解決問題。您應該調試您的程序,主要側重於優化內存使用。要做的最重要的事情就是驗證是否所有的臨時內存都被釋放,最好是在不再使用時立即釋放。 – XenoRo

回答

0

既然不能看到完整的代碼,我不能作出準確的假設,但我的猜測是,這個問題是在這裏:

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

我不知道Kinect的API你使用的是什麼(OpenNI/libfreenect),但無論如何,您可能不應每幀創建一個新的圖像多次(如在draw()中所做的那樣)。圖像可以很快填滿內存,而且您不需要多次使用圖像,只需要兩張圖像即可進行更新。 比如你在setup()初始化一次的圖像,然後在draw()

(更新這些圖像的像素另外,如果你使用我推薦一看像SimpleOpenNI爲OpenNI或dLibs Kinect的加工包裝庫處理贏)/ OpenKinect for libfreenect。這是一個簡單得多任何與這些顯示的深度圖像:

隨着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); 
} 

隨着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(); 
} 

隨着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(); 
} 

這取決於你需要什麼樣的操作系統和什麼功能來爲你選擇正確的處理包裝。

simple openni SimpleOpenNI樣品

diwi dlibs dLibs_freenect

OpenKinect P5 OpenKinect P5

+0

格蘭德感謝這個偉大的答案!我會檢查你的建議,並會在這裏發表評論,如果我得到了一些結果!你非常喜歡:) – Rubberducker

相關問題