Saturday, January 2, 2016

Working with Kinect Camera

App Type     : WPF
Language     : C#
Kinect SDK : v1.8

In this post we are going to create a simple cam application.
Within this cam application we are going to develop the following feature:
1. Start and Stop the Kinect sensor
2. Screen to display the current view of the Kinect Camera.
3. Capture the current view of the Kinect Camera

We are going to create this application which has the bellow design (You can change the design according to your imagination)


XAML design:

<Window x:Class="KinectInfoBox.KinectCam.CamWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Kinect Cam" Height="500" Width="800" Closed="Window_Closed_1">
    <Grid>
        <Image Name="CamControl" Stretch="Fill" HorizontalAlignment="Left" Height="213" Margin="200,60,0,0" VerticalAlignment="Top" Width="400" />
        <Button Content="Start" HorizontalAlignment="Left" Margin="200,300,0,0" VerticalAlignment="Top" Width="100" Click="Button_Click_2" />
        <Button Content="Stop" HorizontalAlignment="Left" Margin="350,300,0,0" VerticalAlignment="Top" Width="100" Click="Button_Click_1"/>
        <Button Content="Capture" HorizontalAlignment="Left" Margin="500,300,0,0" VerticalAlignment="Top" Width="100" Click="Capture_Clicked"/>
        <TextBox Name="txtCamAngle" HorizontalAlignment="Left" Height="23" Margin="350,350,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="100" />
        <Button Name="btnSetAngle" Content="Ok" HorizontalAlignment="Left" Margin="500,350,0,0" VerticalAlignment="Top" Width="100" Click="btnSetAngle_Click"/>
    </Grid>
</Window>

.cs file:

namespace KinectInfoBox.KinectCam
{
    public partial class CamWindow : Window
    {
        private KinectSensor Sensor;

        public CamWindow()
        {
            InitializeComponent();
        }

        private void StartKinectCam()
        {
            if (KinectSensor.KinectSensors.Count > 0)
            {
                Sensor = KinectSensor.KinectSensors.FirstOrDefault(sensorItem => sensorItem.Status == KinectStatus.Connected);
                if (Sensor != null && !Sensor.IsRunning)
                {
                    Sensor.Start();
                }
                Sensor.ColorStream.Enable();
                Sensor.ColorFrameReady += Sensor_ColorFrameReady;
            }
            else
            {
                MessageBox.Show("Kinect is not ready!", "Message");
            }
        }

        void Sensor_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            byte[] pixeldata;

            using (ColorImageFrame imageFrame = e.OpenColorImageFrame())
            {
                //check if the incomming frame is not null
                if (imageFrame == null)
                {
                    return;
                }
                else
                {
                    //Get the pixel data in the byte array
                    pixeldata = new byte[imageFrame.PixelDataLength];

                    //Copy the pixel data
                    imageFrame.CopyPixelDataTo(pixeldata);

                    //calculate the stride
                    int stride = imageFrame.Width * imageFrame.BytesPerPixel;

                    //assign the bitmap image source into image control
                    CamControl.Source = BitmapSource.Create(imageFrame.Width, imageFrame.Height, 96, 96, PixelFormats.Bgr32, null, pixeldata, stride);
                }
            }
        }

        private void Window_Closed_1(object sender, EventArgs e)
        {
            if (Sensor != null && Sensor.IsRunning)
            {
                Sensor.Stop();
            }
        }

        //Save image in the projects' bin -> debug
        private void SaveImage()
        {
            using (FileStream fileStream = new FileStream(string.Format("{0}.jpg", Guid.NewGuid().ToString()), System.IO.FileMode.Create))
            {
                BitmapSource imageSource = (BitmapSource)CamControl.Source;
                JpegBitmapEncoder jpeegEncoder = new JpegBitmapEncoder();
                jpeegEncoder.Frames.Add(BitmapFrame.Create(imageSource));
                jpeegEncoder.Save(fileStream);
                fileStream.Close();
            }
        }

        private void Capture_Clicked(object sender, RoutedEventArgs e)
        {
            if (Sensor.IsRunning && Sensor.ColorStream.IsEnabled)
            {
                SaveImage();
            }
        }

        private void btnSetAngle_Click(object sender, RoutedEventArgs e)
        {
            int angle = int.Parse(txtCamAngle.Text);
            if (angle > Sensor.MinElevationAngle && angle < Sensor.MaxElevationAngle)
            {
                Sensor.ElevationAngle = angle;
            }
            else
            {
                MessageBox.Show("Invalid value. Enter value between -27 and 27", "Error");
            }

        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            if (Sensor.IsRunning)
            {
                Sensor.Stop();
                CamControl.Source = null;
            }
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            StartKinectCam();
        }
    }
}