2012-03-25 21 views
1

我不能讓周圍的SimpleOpenNI用於處理AO一個奇特的問題,我要求你的幫助。如何從depthMapRealWorld()方法高效地存儲過去的深度像素數據?

我想存儲像素深度數據的快照上離散的時間間隔(由.depthMapRealWorld()方法作爲PVector陣列返回),然後進一步處理它們進行演示。我嘗試將它們添加到ArrayList中,但似乎depthMapRealWorld()方法僅返回對當前深度數據的引用,而不是真正的數組。我嘗試了以下順序:

  1. 只是獲取數據並將其添加到arraylist中。在update()方法的每次調用中,整個數組列表都包含相同的PVector數組,即使零位置的數組添加了許多迭代!

  2. 然後,我提出的PVector陣列,其創建時間,一類的一部分沿。重寫了一下草圖,但沒有幫助。數組列表中的所有數組仍然相同。

  3. 最後,在類的構造函數,I「手動」複製XYZ座標從PVector陣列每向量的成int數組。這似乎解決了這個問題 - 陣列列表中的int數組現在彼此不同。但這個解決方案引入了嚴重的性能問

問題是:是否有更有效的方式來存儲這些PVector數組並保留它們的值?

代碼:

import processing.opengl.*; 
import SimpleOpenNI.*; 

SimpleOpenNI kinect; 


float rotation = 0; 
int time = 0; 
ArrayList dissolver; 
ArrayList<Integer> timer; 
int pSize = 10; 
Past past; 

void setup() { 
    dissolver = new ArrayList(); 
    timer = new ArrayList(); 
    size(1024, 768, OPENGL); 
    kinect = new SimpleOpenNI(this); 
    kinect.enableDepth(); 
    translate(width/2, height/2, -100); 
    rotateX(radians(180)); 
    stroke(255); 
} 

void draw() { 
    background(0); 
    translate(width/2, height/2, 500); 
    rotateX(radians(180)); 
    kinect.update(); 
    stroke (255, 255, 255); 

    past = new Past (kinect.depthMapRealWorld(), time); 
    if (dissolver.size() == pSize) { //remove the oldest arraylist element if when list gets full 
    dissolver.remove(0); // 
    } 

    if (time % 20 == 0) { 
    dissolver.add (past); 
    Past p1 = (Past) dissolver.get (0); 
    float [][] o2 = p1.getVector(); 
    println ("x coord of a random point at arraylist position 0: " + o2[50000][0]); //for testing 
    } 
    if (dissolver.size() == pSize-1) { 
    //dissolve(); 
    } 
    time ++; 
} 

void dissolve() { //from the previous nonworking version; ignore 
    for (int offset = 0; offset < pSize-1; offset ++) { 
    PVector[] offPoints = (PVector[]) dissolver.get (offset); 
    int offTime = timer.get(offset); 
    for (int i = 0; i < offPoints.length; i+=10) { 
     int col = (time-offTime)*2; //why?? 
     stroke (255, 0, col); 
     PVector currentPoint = offPoints[i]; 
     if (currentPoint.z <1500) { 
     point(currentPoint.x, currentPoint.y, currentPoint.z); // - 2*(time-offTime) + random(0, 100) 
     } 
    } 
    } 
} 

class Past { 
    private PVector [] depth; //should contain this, not int 
    private float [][] depth1; 
    private int time; 

    Past (PVector [] now, int t) { 
    //should be like this: depth = now; 
    //clumsy and performancewise catastrophic solution below 
    depth1 = new float [now.length][3]; 
    for (int i = 0; i< now.length; i+=10) { 
     PVector temp = now[i]; 
     depth1 [i][0] = temp.x; 
     depth1 [i][1] = temp.y; 
     depth1 [i][2] = temp.z; 

    } 
    //arrayCopy(now, depth); this didn't work either 
    time = t; 
    } 

    float [][] getVector() { 
    return depth1; 
    } 

    int getTime() { 
    return time; 
    } 
} 

回答

3

如果我理解正確的,你想存儲每一幀的3D位置(PVectors的ArrayList),對不對? 如果是這樣,您應該能夠簡單地存儲PVectors並稍後參考它們。 這裏有一個基本的草圖說明這一點:

import processing.opengl.*; 
import SimpleOpenNI.*; 

SimpleOpenNI kinect; 
ArrayList<ArrayList<PVector>> frames = new ArrayList<ArrayList<PVector>>(); 
ArrayList<PVector> frame; 
boolean isRecording = true; 
boolean isRecFrame; 

void setup() { 
    size(1024, 768, OPENGL); 
    kinect = new SimpleOpenNI(this); 
    kinect.enableDepth(); 
    stroke(255); 
} 

void draw() { 
    background(0); 
    translate(width/2, height/2, 500); 
    rotateX(PI); 
    translate(0,0,-1000); 

    kinect.update(); 

    if(isRecording){ 

    isRecFrame = (frameCount % 20 == 0);//record every 20 frames 
    int[] depthMap = kinect.depthMap(); 
    int  steps = 5; // to speed up the drawing, draw every N point 
    int  index; 
    PVector realWorldPoint; 
    if(isRecFrame) frame = new ArrayList<PVector>(); 

    for(int y=0;y < kinect.depthHeight();y+=steps) 
    { 
     for(int x=0;x < kinect.depthWidth();x+=steps) 
     { 
     index = x + y * kinect.depthWidth(); 
     if(depthMap[index] > 0) 
     { 
      realWorldPoint = kinect.depthMapRealWorld()[index]; 
      point(realWorldPoint.x,realWorldPoint.y,realWorldPoint.z); 
      if(isRecFrame) frame.add(realWorldPoint.get()); 
     } 
     } 
    } 
    if(isRecFrame) frames.add(frame); 

    }else{//playback 
    ArrayList<PVector> currentFrame = frames.get(frameCount%frames.size());//playback is faster than recording now for testing purposes - add a decent frame counter here at some point 
    for(PVector p : currentFrame) point(p.x,p.y,p.z); 
    } 

} 

void keyPressed(){ 
    if(key == ' ') isRecording = !isRecording; 
} 

使用SPACE鍵錄製和播放之間切換。 需要注意的主要事情是我存儲每個深度像素(frame.add(realWorldPoint.get());)真實世界位置的副本。還有一點需要記住的是,目前您將這些座標存儲在內存中,這些座標在某些時候會填滿。如果你只存儲有限數量的幀,應該沒問題,否則你可能想保存到磁盤的點。這樣您可以重複使用其他草圖的錄音。一個基本的方法是瘡他們在一個CSV文件:

void saveCSV(ArrayList<PVector> pts){ 
    String csv = "x,y,z\n"; 
    for(PVector p : pts) csv += p.x + "," + p.y + "," + p.z + "\n"; 
    saveStrings("frame_"+frameCount+".csv",csv.split("\n")); 
} 

另一個辦法是使用更合適的格式點雲,像PLY。 保存的ASCII層是相當直截了當:

void savePLY(ArrayList<PVector> pts){ 
    String ply = "ply\n"; 
    ply += "format ascii 1.0\n"; 
    ply += "element vertex " + pts.size() + "\n"; 
    ply += "property float x\n"; 
    ply += "property float y\n"; 
    ply += "property float z\n"; 
    ply += "end_header\n"; 
    for(PVector p : pts)ply += p.x + " " + p.y + " " + p.z + "\n"; 
    saveStrings("frame_"+frameCount+".ply",ply.split("\n")); 
} 

以後,您可以打開/瀏覽/進程與像MeshLab工具,這些文件。

+0

謝謝!我認爲這足以說:PVector [] frame = kinect.depthMapRealWorld(),然後將frame []添加到ArrayList。顯然不是這樣:) – Solipsy 2012-03-26 15:55:36