2011-11-12 9 views
-1

私は、このリンクでロバート・レビーによって提供されたコードを追っ:http://channel9.msdn.com/coding4fun/kinect/Display-Kinect-color-image-containing-only-players-aka-background-removalのKinect背景除去

私は私の既存のコードにそれを実装しようとした、と矛盾した結果がありました。プログラムの起動時にユーザがkinectの視界にいる場合、時間の一部をバックグラウンドで削除します。ユーザが視界に入ると、それを拾いません。

namespace KinectUserRecognition 
    { 
     public partial class MainWindow : Window 
     { 
      public MainWindow() 
      { 
       InitializeComponent(); 
      } 

      //Kinect Runtime 
      Runtime kinect = Runtime.Kinects[0]; 

      PlanarImage colorImage; 
      PlanarImage depthImage; 
      bool isDepthImage; 
      WriteableBitmap player1; 


      private void Window_Loaded(object sender, RoutedEventArgs e) 
      { 
       isDepthImage = false; 
       //UseDepthAndPlayerIndex and UseSkeletalTracking 
       kinect.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseColor);// | RuntimeOptions.UseSkeletalTracking); 

       //register for event 
       kinect.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_VideoFrameReady); 
       kinect.DepthFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_DepthFrameReady); 

       //Video image type 
       kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, 
        ImageType.Color); 

       //DepthAndPlayerIndex ImageType 
       kinect.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, 
        ImageType.DepthAndPlayerIndex); 

      } 

      void nui_VideoFrameReady(object sender, ImageFrameReadyEventArgs e) 
      { 
       colorImage = e.ImageFrame.Image; 
       image1.Source = BitmapSource.Create(colorImage.Width, colorImage.Height, 96, 96, 
        PixelFormats.Bgr32, null, colorImage.Bits, colorImage.Width * colorImage.BytesPerPixel); 

       if (isDepthImage) 
       { 
        player1 = GeneratePlayerImage(e.ImageFrame, 1); 
        image3.Source = player1; 
       } 
      } 

      void nui_DepthFrameReady(object sender, ImageFrameReadyEventArgs e) 
      { 
       //Convert depth information for a pixel into color information 
       byte[] ColoredBytes = GenerateColoredBytes(e.ImageFrame); 

       depthImage = e.ImageFrame.Image; 
       image2.Source = BitmapSource.Create(depthImage.Width, depthImage.Height, 96, 96, PixelFormats.Bgr32, null, 
        ColoredBytes, depthImage.Width * PixelFormats.Bgr32.BitsPerPixel/8); 

       isDepthImage = true; 
      } 

      private WriteableBitmap GeneratePlayerImage(ImageFrame imageFrame, int playerIndex) 
      { 
       int depthWidth = kinect.DepthStream.Width; 
       int depthHeight = kinect.DepthStream.Height; 

       WriteableBitmap target = new WriteableBitmap(depthWidth, depthHeight, 96, 96, PixelFormats.Bgra32, null); 
       var depthRect = new System.Windows.Int32Rect(0, 0, depthWidth, depthHeight); 

       byte[] color = 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) 
        { 

         short depthValue = (short)(depthImage.Bits[depthIndex] | (depthImage.Bits[depthIndex + 1] << 8)); 

         int colorX, colorY; 
         kinect.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(
          imageFrame.Resolution, 
          imageFrame.ViewArea, 
          depthX, depthY, //depth coordinate 
          depthValue,  //depth value 
          out colorX, out colorY); //color coordinate 

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

         output[outputIndex++] = color[(4 * (colorX + (colorY * imageFrame.Image.Width))) + 0]; 
         output[outputIndex++] = color[(4 * (colorX + (colorY * imageFrame.Image.Width))) + 1]; 
         output[outputIndex++] = color[(4 * (colorX + (colorY * imageFrame.Image.Width))) + 2]; 
         output[outputIndex++] = GetPlayerIndex(depthImage.Bits[depthIndex]) == playerIndex ? (byte)255 : (byte)0; 
        } 
       } 
       target.WritePixels(depthRect, output, depthWidth * PixelFormats.Bgra32.BitsPerPixel/8, 0); 
       return target; 
       //return output; 
      } 

      private static int GetPlayerIndex(byte firstFrame) 
      { 
       //returns 0 = no player, 1 = 1st player, 2 = 2nd player... 
       //bitwise & on firstFrame 
       return (int)firstFrame & 7; 
      } 
     } 
} 

-EDITの1-

私は、問題を絞り込んたと思うが、私はそれを解決する方法のか分かりません。私はkinectの視野に1人しかいないと、私の "GetPlayerIndex"メソッドから1の値を返すと仮定しました。これはそうではありません。背景を取り除いた人物ごとに別々のイメージを作りたいと思っていました。どのようなタイプの値のIから受け取ることを前提とすべきである:私のテストから

-EDIT 2 -

私はプレーヤーのインデックスのための6の最大値ことができますが、私はISNを取得する指標ことに気付きました一貫性がない。どのプレイヤーのインデックスがスケルトンに割り当てられるのか知る方法があれば?たとえば、私が唯一の邦人だったら、自分の選手インデックスが常に1であることを知る方法がありますか?

+2

「改善の余地が十分にある」という原作者のコードは適切ではないと言っていますか?それとも、それはあなたの側で作者の元のコードとは異なった振る舞いをしていますか? – Bart

+0

より具体的で狭いスコープの質問をここで定義できますか?それが立てば、私はあなたが "このコードを修正してください"と言っていると思います。これは実際には問題ではなく、潜在的にも非常に広いです。 – Flexo

+1

このリンクを参照できます。http://stackoverflow.com/questions/6844697/how-to-align-kinects-depth-image-with-color-image – ravithejag

答えて

2

プレーヤーのインデックスは何も保証されません。一度スケルトンをキャッチすると、そのスケルトンの視界が失われるまでインデックスは同じままになりますが、最初のプレーヤーが1、2番目の2などと仮定することはできません。

player1 = GeneratePlayerImage(e.ImageFrame, 1);コールの前に有効なスケルトンインデックスを決定するか、またはGeneratePlayerImage関数を変更してインデックスを見つける必要があります。あなたが背景を削除し、そのままフレーム内のすべての人々のためのピクセルを残すのみで興味を持っている場合は、単にこれを変更:ただのプレーヤーのためにチェックしますこれに

output[outputIndex++] = GetPlayerIndex(depthImage.Bits[depthIndex]) == playerIndex ? (byte)255 : (byte)0; 

を、代わりに特定のプレイヤーの:

output[outputIndex++] = GetPlayerIndex(depthImage.Bits[depthIndex]) != 0 ? (byte)255 : (byte)0; 

特定の代わりに、すべてのプレーヤーのプレーヤーのためにこれを行うには、私は考えることができる他の二つの方法:それは与える骨格の配列によって

  1. オープンのKinectのスケルトンフィード、およびループあなたは有効なインデックスを見つけることができます。このインデックスを保持するグローバル整数を作成し、このグローバル整数でGeneratePlayerImageメソッドを呼び出します。
  2. GeneratePlayerImageメソッドを変更して、各ピクセルのプレーヤーインデックスを確認し、見つかった場合は、そのインデックスを使用して画像全体の背景を削除します(見つかった他のインデックスは無視します)。
関連する問題