从3台Kinect摄像机读取数据时出现问题

时间:2012-02-11 17:45:00

标签: java processing kinect

我正在尝试从多个Kinect传感器(目前为3个)读取数据,并且当有超过2个设备时出现问题。

我正在使用Daniel Shiffman's OpenKinect Processing wrapper,稍加修改,因此它允许打开多个设备实例。 2台设备一切正常。问题是当我使用3.一个Kinect直接连接到一个可用的两个USB端口,另外两个插入USB 2.0集线器(它有自己的电源适配器)。

设备都成功初始化:

org.openkinect.Device@1deeb40 initialized
org.openkinect.Device@2c35e initialized
org.openkinect.Device@1cffeb4 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;
    }








}

我对Daniel的Kinect类所做的唯一重大改变是添加了一个额外的start()方法:

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个深度图,但第3个没有更新。

jit.freenect test

所以它似乎是一个与驱动程序有关的问题,而不是包装器,因为使用2个不同的libfreenect(Java / Processing和Max)包装器会出现相同的行为,但是为什么这是诚实的呢? / p>

有没有人使用OpenKinect / libfreenect驱动程序有类似的问题(从3个设备获取深度提要)?关于如何解决这个问题的任何想法?

1 个答案:

答案 0 :(得分:2)

Kinect对USB的要求非常高 - 通常,主板上每个USB主机控制器只能获得一个Kinect(大多数PC和笔记本电脑都有两个)。我见过的唯一解决方案是购买PCI-E USB控制器并将第三个插入其中。

此外,如果您通过在所有Kinect上禁用RGB流来减少带宽需求,那么您可能会很幸运(我很乐意假设您没有使用它,因为没有提及)