2011-07-27 28 views

Respuesta

8

La clave para esto es la llamada a 'Runtime.NuiCamera.GetColorPixelCoordinatesFromDepthPixel'

Aquí es un método de extensión para la clase en tiempo de ejecución. Devuelve un objeto WriteableBitmap. Este WriteableBitmap se actualiza automáticamente como nuevos marcos vienen en el uso de la misma es muy sencilla:.

kinect = new Runtime(); 
    kinect.Initialize(RuntimeOptions.UseColor | RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseDepthAndPlayerIndex); 
    kinect.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex); 
    kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color); 
    myImageControl.Source = kinect.CreateLivePlayerRenderer(); 

y aquí está el código en sí mismo:

public static class RuntimeExtensions 
{ 
    public static WriteableBitmap CreateLivePlayerRenderer(this Runtime runtime) 
    { 
     if (runtime.DepthStream.Width == 0) 
     throw new InvalidOperationException("Either open the depth stream before calling this method or use the overload which takes in the resolution that the depth stream will later be opened with."); 
     return runtime.CreateLivePlayerRenderer(runtime.DepthStream.Width, runtime.DepthStream.Height); 
    } 
    public static WriteableBitmap CreateLivePlayerRenderer(this Runtime runtime, int depthWidth, int depthHeight) 
    { 
     PlanarImage depthImage = new PlanarImage(); 
     WriteableBitmap target = new WriteableBitmap(depthWidth, depthHeight, 96, 96, PixelFormats.Bgra32, null); 
     var depthRect = new System.Windows.Int32Rect(0, 0, depthWidth, depthHeight); 

     runtime.DepthFrameReady += (s, e) => 
      { 
       depthImage = e.ImageFrame.Image; 
       Debug.Assert(depthImage.Height == depthHeight && depthImage.Width == depthWidth); 
      }; 

     runtime.VideoFrameReady += (s, e) => 
      { 
       // don't do anything if we don't yet have a depth image 
       if (depthImage.Bits == null) return; 

       byte[] color = e.ImageFrame.Image.Bits; 

       byte[] output = new byte[depthWidth * depthHeight * 4]; 

       // loop over each pixel in the depth image 
       int outputIndex = 0; 
       for (int depthY = 0, depthIndex = 0; depthY < depthHeight; depthY++) 
       { 
        for (int depthX = 0; depthX < depthWidth; depthX++, depthIndex += 2) 
        { 
         // combine the 2 bytes of depth data representing this pixel 
         short depthValue = (short)(depthImage.Bits[depthIndex] | (depthImage.Bits[depthIndex + 1] << 8)); 

         // extract the id of a tracked player from the first bit of depth data for this pixel 
         int player = depthImage.Bits[depthIndex] & 7; 

         // find a pixel in the color image which matches this coordinate from the depth image 
         int colorX, colorY; 
         runtime.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(
          e.ImageFrame.Resolution, 
          e.ImageFrame.ViewArea, 
          depthX, depthY, // depth coordinate 
          depthValue, // depth value 
          out colorX, out colorY); // color coordinate 

         // ensure that the calculated color location is within the bounds of the image 
         colorX = Math.Max(0, Math.Min(colorX, e.ImageFrame.Image.Width - 1)); 
         colorY = Math.Max(0, Math.Min(colorY, e.ImageFrame.Image.Height - 1)); 

         output[outputIndex++] = color[(4 * (colorX + (colorY * e.ImageFrame.Image.Width))) + 0]; 
         output[outputIndex++] = color[(4 * (colorX + (colorY * e.ImageFrame.Image.Width))) + 1]; 
         output[outputIndex++] = color[(4 * (colorX + (colorY * e.ImageFrame.Image.Width))) + 2]; 
         output[outputIndex++] = player > 0 ? (byte)255 : (byte)0; 
        } 
       } 
       target.WritePixels(depthRect, output, depthWidth * PixelFormats.Bgra32.BitsPerPixel/8, 0); 
      }; 
      return target; 
     } 
    } 
+0

desgracia que enlazan su lanzando una pantalla amarilla de la muerte mi camino en este momento. Pero estoy buscando el método que mencionaste –

+0

@ Mr-Bell - He actualizado esta publicación con el código actual en lugar de un enlace –

+0

Parece que funciona. Parece que llamar a GetColorPixelCoordinatesFromDepthPixel está matando mi framerate. –

2

Una forma de hacerlo es asumir que la las imágenes de color y profundidad tienen variaciones similares en ellas, y correlacionan de forma cruzada las dos imágenes (o versiones más pequeñas de ellas).

  • Pre-whiten the image s para obtener las variaciones subyacentes.
  • Cross-correlate las imágenes pre-blanqueadas o versiones más pequeñas de ellas.
  • La posición del pico de la correlación cruzada le dirá el desplazamiento en x y y
+0

Peter, esos son artículos interesantes. Sin embargo, creo que esta solución podría ser significativamente más empírica. Creo que podría ser un desplazamiento o algo así –

+0

:-) OK. Probablemente estoy pensando demasiado. [Acabo de leer este tipo de cosas ...] (http://liu.diva-portal.org/smash/record.jsf?pid=diva2:420400) –

+1

en la fábrica, cada dispositivo kinect está calibrado y las compensaciones entre las cámaras se graban en la memoria del dispositivo. el truco está en encontrar la API correcta para hacer uso de esa información. en este momento, el kinect sdk oficial solo proporciona una de estas API, pero se están considerando otras para lanzamientos futuros –

Cuestiones relacionadas