2012-02-11 5 views
3

Я пытаюсь прочитать данные с нескольких датчиков Kinect (3 на данный момент) и имеет проблемы, когда есть более двух устройств.Проблемы с чтением данных с 3 камер Kinect

Я использую Daniel Shiffman's OpenKinect Processing wrapper, слегка модифицированный, поэтому он позволяет открывать несколько экземпляров устройства. Все работает нормально с двумя устройствами. Проблема в том, что я использую 3. Один Kinect подключается прямо к одному из доступных двух портов USB, а два других подключаются к USB 2.0 Hub (у которого есть собственный адаптер питания).

Устройства все инициализации успешно:

[email protected] initialized 
[email protected] initialized 
[email protected] initialized 

Проблема заключается в том, когда я пытаюсь получить карту глубины от 3-го устройства, я получаю массив, заполненный нулями. Я думал, что это устройство, но если они меняются, это всегда 3-е (последнее подключенное устройство), которое представляет такое поведение.

Вот мой код до сих пор:

package librarytests; 

import org.openkinect.Context; 
import org.openkinect.processing.Kinect; 

import processing.core.PApplet; 
import processing.core.PVector; 

public class PointCloudxN extends PApplet { 

    // Kinect Library object 
    int numKinects;// = 3; 
    Kinect[] kinects; 
    int[] colours = {color(192,0,0),color(0,192,0),color(0,0,192),color(192,192,0),color(0,192,192),color(192,0,192)}; 

    // Size of kinect image 
    int w = 640; 
    int h = 480; 

    // We'll use a lookup table so that we don't have to repeat the math over and over 
    float[] depthLookUp = new float[2048]; 

    // Scale up by 200 
    float factor = 200; 

    public void setup() { 
     size(800,600,P3D); 
     numKinects = Context.getContext().devices(); 
     kinects = new Kinect[numKinects]; 
     for (int i = 0; i < numKinects; i++) { 
      kinects[i] = new Kinect(this); 
      kinects[i].start(i); 
      kinects[i].enableDepth(true); 
      kinects[i].processDepthImage(false); 
     } 
     // Lookup table for all possible depth values (0 - 2047) 
     for (int i = 0; i < depthLookUp.length; i++) { 
      depthLookUp[i] = rawDepthToMeters(i); 
     } 
    } 

    public void draw() { 
     background(0); 

     translate(width/2,height/2,-50); 
     rotateY(map(mouseX,0,width,-PI,PI)); 
     rotateX(map(mouseY,0,height,-PI,PI)); 
     int skip = 4;//res 
     //* 
     for (int i = 0; i < numKinects; i++) { 
      Kinect kinect = kinects[i]; 
      int[] depth = kinect.getRawDepth(); 
      //if(frameCount % 60 == 0 && i == 2) println(depth); 
      if (depth != null) { 

       // Translate and rotate 

       for(int x=0; x<w; x+=skip) { 
        for(int y=0; y<h; y+=skip) { 
         int offset = x+y*w; 

         // Convert kinect data to world xyz coordinate 
         int rawDepth = depth[offset]; 
         PVector v = depthToWorld(x,y,rawDepth); 

         stroke(colours[i]); 
         // Draw a point 
         point(v.x*factor,v.y*factor,factor-v.z*factor); 

        } 
       } 
      } 
     } 


     //*/ 
    } 

    public void stop() { 
     for (int i = 0; i < numKinects; i++) kinects[i].quit(); 
     super.stop(); 
    } 

    public static void main(String _args[]) { 
     PApplet.main(new String[] { librarytests.PointCloudxN.class.getName() }); 
    } 

    // These functions come from: http://graphics.stanford.edu/~mdfisher/Kinect.html 
    float rawDepthToMeters(int depthValue) { 
     if (depthValue < 2047) { 
      return (float)(1.0/((double)(depthValue) * -0.0030711016 + 3.3309495161)); 
     } 
     return 0.0f; 
    } 

    PVector depthToWorld(int x, int y, int depthValue) { 

     final double fx_d = 1.0/5.9421434211923247e+02; 
     final double fy_d = 1.0/5.9104053696870778e+02; 
     final double cx_d = 3.3930780975300314e+02; 
     final double cy_d = 2.4273913761751615e+02; 

     PVector result = new PVector(); 
     double depth = depthLookUp[depthValue];//rawDepthToMeters(depthValue); 
     result.x = (float)((x - cx_d) * depth * fx_d); 
     result.y = (float)((y - cy_d) * depth * fy_d); 
     result.z = (float)(depth); 
     return result; 
    } 








} 

Единственное серьезное изменение, которое я сделал в классе Kinect Даниэля добавлял дополнительный старт() метод:

public void start(int id) { 

     context = Context.getContext(); 
     if(context.devices() < 1) 
     { 
      System.out.println("No Kinect devices found."); 
     } 
     device = context.getDevice(id); 
     //device.acceleration(this); 

     device.acceleration(new Acceleration() 
     { 
      void Acceleration(){ 
       System.out.println("new Acceleration implementation"); 
      } 
      public void direction(float x, float y, float z) 
      { 
       System.out.printf("Acceleration: %f %f %f\n", x ,y ,z); 
      } 
     }); 

     kimg = new RGBImage(p5parent); 
     dimg = new DepthImage(p5parent); 
     running = true; 

     super.start(); 
    } 

Я также попытался с MaxMSP/Jitter и jit.freenect external, и я получаю такое же поведение: я могу получить 2 карты глубины, но третий не обновляется.

jit.freenect test

Таким образом, кажется, что проблема связана с драйвером, а не обертку, так как то же самое поведение присутствует с использованием 2 разных оберток для libfreenect (Java/Обработка и Макс), но я невежествен, почему это бывает честно.

У кого-нибудь была аналогичная проблема (получение глубины подачи из 3-х устройств) с использованием драйвера OpenKinect/libfreenect? Любые идеи о том, как я могу преодолеть эту проблему?

ответ

2

Kinect чрезвычайно требовательна к USB - как правило, вы можете получить только один контроллер Kinect на USB-хост на материнской плате (на большинстве ПК и ноутбуков два). Единственное решение, которое я видел, - купить USB-контроллер PCI-E и подключить к нему третий.

Кроме того, вы можете быть счастливым, если уменьшить требования к пропускной способности путем отключения потока RGB на всех Kinects (я беспечно если вы не используете его, так как он не был упомянут)