Search code examples
c#opencvkinectemgucvkinect-sdk

Kinect Depth Image only partly visible


I am new to Kinect and C#. I am trying to get the Depth Image from the Kinect, convert it to a bitmap to perform some OpenCV operations and then display it. The problem is, I am getting only a third of the depth image and the rest is completely black(as seen in the picture). This is not the raw depth image but the image that I receive after painting.

enter image description here

Here is the code-

image and image1 are the two image canvas i have for display.

void DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
    {

        DepthImageFrame Image;
        Bitmap bm;
        using (Image = e.OpenDepthImageFrame())
        {


           if (Image != null)
            {
            this.shortpixeldata = new short[Image.PixelDataLength];
            this.depthFrame32 = new byte[Image.Width * Image.Height * Bgr32BytesPerPixel];


            bmp = new Bitmap(Image.Width, Image.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
            Image.CopyPixelDataTo(this.shortpixeldata);

            byte[] convertedDepthBits = this.ConvertDepthFrame(this.shortpixeldata, ((KinectSensor)sender).DepthStream);


            BitmapData bmapdata = bmp.LockBits(
                                new System.Drawing.Rectangle(0, 0, Image.Width, Image.Height),
                                ImageLockMode.WriteOnly,
                                bmp.PixelFormat);


            IntPtr ptr = bmapdata.Scan0;
            Marshal.Copy(convertedDepthBits, 0, ptr, Image.PixelDataLength);
            bmp.UnlockBits(bmapdata);

            MemoryStream ms1 = new MemoryStream(); 
            bmp.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg);
            System.Windows.Media.Imaging.BitmapImage bImg = new System.Windows.Media.Imaging.BitmapImage();
            bImg.BeginInit();
            bImg.StreamSource = new MemoryStream(ms1.ToArray());
            bImg.EndInit();

            image.Source = bImg;

                if (bmp != null)
            {

                Image<Bgr, Byte> currentFrame = new Image<Bgr, Byte>(bmp); 

                Image<Gray, Byte> grayImage = currentFrame.Convert<Gray, Byte>().PyrDown().PyrUp();
                Image<Gray, Byte> Dest = new Image<Gray, Byte>(grayImage.Size);
                CvInvoke.cvCanny(grayImage, Dest, 10, 60, 3);


                image1.Source = ToBitmapSource(Dest);

                CalculateFps();
            }



            }



            else
            {
                System.Diagnostics.Debug.WriteLine("depth bitmap empty :/");
            }
        }
    }


        private byte[] ConvertDepthFrame(short[] depthFrame, DepthImageStream depthStream)
        {
            System.Diagnostics.Debug.WriteLine("depthframe len :{0}", depthFrame.Length);

        for (int i16 = 0, i32 = 0; i16 < depthFrame.Length && i32 < this.depthFrame32.Length; i16++, i32 += 4)
        {

        int realDepth = depthFrame[i16] >> DepthImageFrame.PlayerIndexBitmaskWidth;


        byte Distance = 0;


        int MinimumDistance = 800;
        int MaximumDistance = 4096;


        if (realDepth > MinimumDistance)
        {


        //White = Close
        //Black = Far
        Distance = (byte)(255-((realDepth-MinimumDistance)*255/(MaximumDistance-MinimumDistance)));


        this.depthFrame32[i32 + RedIndex] = (byte)(Distance);
        this.depthFrame32[i32 + GreenIndex] = (byte)(Distance);
        this.depthFrame32[i32 + BlueIndex] = (byte)(Distance);
        }

        else
        {
        this.depthFrame32[i32 + RedIndex] = 0;
        this.depthFrame32[i32 + GreenIndex] = 150;
        this.depthFrame32[i32 + BlueIndex] = 0;
        }
        }

        return this.depthFrame32;
        }

I tried different PixelFormats to no avail. I can't figure out the problem. Does someone have any idea what I'm doing wrong? Thanks


Solution

  • Okay, I figured it out on my own. It was hiding in plain sight all along.

    The function ConvertDepthFrame returns the byte array to convertedDepthBits in a different size (its 4 separate channels so 4x the original size), I need to use the length of data to be copied as 4*Image.PixelDataLength in the method call: Marshal.Copy(...)

    Working fine now. Phew! :)