Windows Metro App for Kinect

by Daksha Lad 30. April 2012 11:48

While working gesture recognition through Kinect on a Windows computer, one of the most common problems faced is invoking a “click” similar to a tile selection on default Xbox dashboard.

There are many ways of doing this. One of the best ways out is doing this by “Timer” same as the XBox Kinect concept. All you have to do is move the cursor over the Button, hold on for a predefined time at the same place and the tile is clicked. This enables the user to fire the click event by pointing the hand icon on a tile for a predefined time duration (say 5 seconds).

This example includes selecting a tile out of 5 tiles, thereby navigating to the page linked to that tile and navigating back to the start dashboard by clicking on the back button.

To achieve this we need to create two controls the “HoverButton” and second a “HandCursor”.

Creating HoverButton:

1) Create a WPF user control library and add a user control HoverButton then add reference to Microft.Kinect and Coding4Fun.Kinect.Wpf.

2) Define the dependency property in HoverButton.xaml.cs for that button to customize it in application, like:-

public int HoverTime

        {
            set { hoverDuration = new Duration(new TimeSpan(0, 0, value)); }
        }

public Brush BackgroundColor
        {
            get { return (Brush)this.GetValue(BackgroundColorProperty); }
            set { this.SetValue(BackgroundColorProperty, value); }
        }
public static readonly DependencyProperty BackgroundColorProperty = DependencyProperty.Register(
            "BackgroundColor", typeof(Brush), typeof(HoverButton), new PropertyMetadata(Brushes.Red));



public Brush HoverColor
        {
            get { return (Brush)this.GetValue(HoverColorProperty); }
            set { this.SetValue(HoverColorProperty, value); }
        }

public static readonly DependencyProperty HoverColorProperty = DependencyProperty.Register(
            "HoverColor", typeof(Brush), typeof(HoverButton), new PropertyMetadata(Brushes.White));

public string Image
        {
            get { return (string)this.GetValue(ImageProperty); }
            set { this.SetValue(ImageProperty, value); }
        }
public static readonly DependencyProperty ImageProperty = DependencyProperty.Register(
            "Image", typeof(string), typeof(HoverButton), new PropertyMetadata(""));

 

 

You can define other properties as per need of application.

3) In HoverButton.xaml for button:

<Grid Background="{Binding BackgroundColor}">
        <Image Source="{Binding Image}" Stretch="Fill"/>
        <TextBlock Text="{Binding Text}" FontSize="{Binding TextSize}" Foreground="{Binding TextColor}" FontFamily="Segoe UI" HorizontalAlignment="Center" VerticalAlignment="Center">          
        </TextBlock>
        <Rectangle Name="Mask" Fill="{Binding HoverColor}" Width="{Binding Width}" Opacity="0.3" RenderTransformOrigin="0,0" Height="0" HorizontalAlignment="Left" VerticalAlignment="Top"/>        
    </Grid>

 

4) Now to data bind the button with properties add below in constructor:

this.DataContext = this;

 

5) Add below for hover and animation:

//animation related
private Duration hoverDuration = new Duration(new TimeSpan(0, 0, 2));
private Duration reverseDuration = new Duration(new TimeSpan(0, 0, 1));
private DoubleAnimation maskAnimation;
private bool isHovering = false;

 

6) To start and stop Hover add these two methods:

private void StartHovering()
        {
            double maxFillHeight = this.ActualHeight;

            if (!isHovering)
            {
                isHovering = true;
                maskAnimation = new DoubleAnimation(Mask.ActualHeight, maxFillHeight, hoverDuration);
                maskAnimation.Completed += new EventHandler(maskAnimation_Completed);
                Mask.BeginAnimation(Canvas.HeightProperty, maskAnimation);
            }
        }

        private void StopHovering()
        {
            if (isHovering)
            {
                isHovering = false;
                maskAnimation.Completed -= maskAnimation_Completed;
                maskAnimation = new DoubleAnimation(Mask.ActualHeight, 0, reverseDuration);
                Mask.BeginAnimation(Canvas.HeightProperty, maskAnimation);
            }
        }

 

7) Another important step is adding click event and its handler:

public delegate void ClickHandler(object sender, EventArgs e);
public event ClickHandler Click;

void maskAnimation_Completed(object sender, EventArgs e)
        {
            isHovering = false;
            if (Click != null)
                Click(this, e);
            Mask.BeginAnimation(Canvas.HeightProperty, null);
        }

 

Implementation:- Check if the cursor is over the button or not

public bool Check(FrameworkElement cursor)
        {
            if (IsCursorInButton(cursor))
            {
                this.StartHovering();
                return true;
            }
            else
            {
                this.StopHovering();
                return false;
            }
        }

private bool IsCursorInButton(FrameworkElement cursor)
        {
            try
            {
                //Cursor midpoint location
                Point cursorTopLeft = cursor.PointToScreen(new Point());
                double cursorCenterX = cursorTopLeft.X + (cursor.ActualWidth / 2);
                double cursorCenterY = cursorTopLeft.Y + (cursor.ActualHeight / 2);

                //Button location
                Point buttonTopLeft = this.PointToScreen(new Point());
                double buttonLeft = buttonTopLeft.X;
                double buttonRight = buttonLeft + this.ActualWidth;
                double buttonTop = buttonTopLeft.Y;
                double buttonBottom = buttonTop + this.ActualHeight;

                if (cursorCenterX < buttonLeft || cursorCenterX > buttonRight)
                    return false;

                if (cursorCenterY < buttonTop || cursorCenterY > buttonBottom)
                    return false;

                return true;
            }
            catch
            {
                return false;
            }
        }

 

Create HandCursor:

1) Add another user control for cursor

In xaml:

<Ellipse Height="40" Width="40" Name="hand">
        <Ellipse.Fill>
            <ImageBrush ImageSource="/HoverAppWPF;component/Images/Hand.png" />
        </Ellipse.Fill>
    </Ellipse>

 

In xaml.cs:

public void SetPosition(Joint joint)
        {
            Joint scaledJoint = joint.ScaleTo(1300, 600, 0.4f, 0.4f);
            Canvas.SetLeft(this, scaledJoint.Position.X);
            Canvas.SetTop(this, scaledJoint.Position.Y);
        }

 

Use the Controls

1) Add the above user control library reference to your application:

Add below to xaml page

<Page x:Class="HoverAppWPF.Main"      
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="600" d:DesignWidth="1000"
       xmlns:ctrl="clr-namespace:KinectControls;assembly=KinectControls"
	Title="Main" Loaded="Page_Loaded" Unloaded="Page_Unloaded">

<Canvas Background="#146c3a">
        <ctrl:HoverButton x:Name="btnVideoChat"  BackgroundColor="Blue" HoverColor="White" Height="100" Width="200" Click="btnVideoChat_Click" Canvas.Top="300" Canvas.Left="100" Image="Images/VideoChat-icon.jpg"/>
        <ctrl:HoverButton x:Name="btnPicture" BackgroundColor="Blue" HoverColor="White" Height="100" Width="200" Click="btnPicture_Click" Canvas.Top="300" Canvas.Left="350" Image="Images/Pictures-icon.jpg"/>
        <ctrl:HoverButton x:Name="btnMenu" BackgroundColor="Blue" HoverColor="White" Height="100" Width="200" Click="btnMenu_Click" Canvas.Top="300" Canvas.Left="600" Image="Images/Menu-icon.jpg" />
        <ctrl:HoverButton x:Name="btnWeather" BackgroundColor="Blue" HoverColor="White" Height="100" Width="200" Click="btnWeather_Click" Canvas.Top="300" Canvas.Left="850" Image="Images/Weather-icon.jpg"/>
        <ctrl:HoverButton x:Name="btnDoctor" BackgroundColor="Blue" HoverColor="White" Height="100" Width="200" Click="btnDoctor_Click" Canvas.Top="300" Canvas.Left="1100" Image="Images/Doctor-icon.jpg"/>
        <ctrl:HandCursor x:Name="hand" Canvas.Top="0" Canvas.Left="0"/>
    </Canvas>

 

2) Add below to xaml.cs to initialize the sensor and for skeleton tracking:

KinectSensor kinect = null;
bool _isInit;
private void Page_Loaded(object sender, RoutedEventArgs e)
        {         
            SetupKinect();
            this.Cursor = Cursors.None;
        }

private void SetupKinect()
        {
            if (_isInit)
                StopKinect();

            if (KinectSensor.KinectSensors.Count > 0)
            {
                //pull the first Kinect
                kinect = KinectSensor.KinectSensors[0];
            }
            if (kinect.Status != KinectStatus.Connected || KinectSensor.KinectSensors.Count == 0)
            {
                MessageBox.Show("No Kinect connected");
                return;
            }

            kinect.SkeletonStream.Enable();

            //to experiment, toggle TransformSmooth between true & false        
            // parameters used to smooth the skeleton data        

            TransformSmoothParameters parameters = new TransformSmoothParameters();
            parameters.Smoothing = 0.1f;
            parameters.Correction = 0.9f;
            parameters.Prediction = 0.3f;
            parameters.JitterRadius = 0.5f;
            parameters.MaxDeviationRadius = 0.1f;
            kinect.SkeletonStream.Enable(parameters);

            kinect.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(kinect_SkeletonFrameReady);

            kinect.Start();
            _isInit = true;

        }

        public void StopKinect()
        {
            if (kinect != null)
            {
                kinect.Stop();
            }
            _isInit = false;
        }

        private void Page_Unloaded(object sender, RoutedEventArgs e)
        {
            kinect.SkeletonFrameReady -= new EventHandler<SkeletonFrameReadyEventArgs>(kinect_SkeletonFrameReady);

            if (kinect != null)
                kinect.Stop();

            kinect = null;

        }

//Here the event gets called:-

        void kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            SkeletonFrame frame = e.OpenSkeletonFrame();
            if (frame != null)
            {
                Skeleton[] skeletons = new Skeleton[frame.SkeletonArrayLength];
                frame.CopySkeletonDataTo(skeletons);

                var skeleton = skeletons.Where(s => s.TrackingState == SkeletonTrackingState.Tracked).FirstOrDefault();

                if (skeleton != null)
                {
                    Joint handJoint = skeleton.Joints[JointType.HandRight];

//set cursor position
                    hand.SetPosition(handJoint);
                    
//check if the cursor is over the button or not
                    btnMenu.Check(hand);
                    btnPicture.Check(hand);
                    btnVideoChat.Check(hand);
                    btnWeather.Check(hand);
                    btnDoctor.Check(hand);
                }
            }
        }
3) For navigation to next page:

private void btnPicture_Click(object sender, EventArgs e)
        {
            ((Window)(this.Parent)).Content = new Picture();            
        }

 

4) Remember to remove the event handler on page unload otherwise when you navigate to next page it will also call the handler of old page with new one that will result in unexpected behavior of cursor.

5) The above code was for dashboard, add same logic to each individual page to reach the dashboard again.

This is all about how to call Click event through Kinect windows.

So let the gestures speak, till then keep learning and keep exploring.

 

 

Tags: ,

Kinect Development

Test Automation - Testing Performance of Web Applications

by Aayush Ojha 25. April 2012 09:37

Web testing is a stream of software testing which focuses on testing web application. Web performance test enables verification that a web application’s behavior is correct. It is usually used to test the performance of the web.

Creating a web test

Web test are created using internet explorer, which records a user clicking through a web application. Click on Test in the menu and select New Test.

 

 

As you select the following you get a screen asking for the type of test.

 

 

Select Web Performance Test and click Ok, Enter the project name you wish to follow and click Create.

 


When you add a new web test to your project, visual studio will open up Internet Explorer and you should see the web test recorder panel in the browser. You can now go to a web site and start using it just like you normally would, and you will see your action being recorded by the web test recorder. You can pause/stop/delete at any time you feel to.

 

 

When you finish performing the action that you wanted to record, click the stop on the web test recorder toolbar and you will be taken back to visual studio and you will see your actions in web test file. As we click the run option it will run the recorded script. As the script runs it detects every individual link and we can see it in the below frame.

 

RED indicates the test is failed and GREEN represents the test is pass.

 

Note: Java script files, CSS and Image files are not supported. They produce 404 errors while the web performance tests.

Skype Calling Through Kinect Gesture Recognition

by Daksha Lad 14. April 2012 02:48

Gone are the days when people preferred to tap the keys for sending commands to their computers. Today’s is the time of touch technology and future is gesture sensing technology. Gesture sensing technologies involve extensive combination of hardware and software application to come up with outstanding results. Gesture sensing is pacing up widely to be used for touchless computer operations.

This blog shows how this latest technology can be used to make Skype calls with ease using Kinect. This app can be used to make Skype calls to predefined users with just wave of hand.

Create a windows application. Connect the Kinect device to your system and use below code snippet to set up the Kinect with your application.

 

Add Microsoft.Kinect.dll and SKYPE4COMLib.dll to your application. 

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Linq;
using System.Drawing.Drawing2D;
using System.Collections.Generic;
using Microsoft.Kinect;
using SKYPE4COMLib;

public Form1()
        {
            InitializeComponent();
            SetupKinect();
        }

        private void SetupKinect()
        {
            if (_isInit)
                StopKinect();

            if (KinectSensor.KinectSensors.Count > 0)
            {
                //pull the first Kinect
                _sensor = KinectSensor.KinectSensors[0];
            }
            if (_sensor.Status != KinectStatus.Connected || KinectSensor.KinectSensors.Count == 0)
            {
                MessageBox.Show("No Kinect connected");
                return;
            }

            _sensor.SkeletonStream.Enable();
            _sensor.DepthStream.Enable(DepthImageFormat.Resolution320x240Fps30);
            _sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
            _sensor.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(_sensor_AllFramesReady);

            _sensor.Start();
            _isInit = true;
        }

 void _sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
        {
            RuntimeColorFrameReady(e); 
            Sensor_SkeletonFrameReady(e);
        }

        void RuntimeColorFrameReady(AllFramesReadyEventArgs e)
        {
            using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
            {
                if (colorFrame == null)
                {
                    return;
                }

                ColorImage.Image = colorFrame.ToBitmap();

                if (_saveColorFrame)
                {
                    _saveColorFrame = false;
                    colorFrame.ToBitmap().Save(DateTime.Now.ToString("yyyyMMddHHmmss") + "_color.jpg", ImageFormat.Jpeg);
                }
            }
        }

        public void StopKinect()
        {
            if (_sensor != null)
            {
                _sensor.Stop();
            }

            _isInit = false;
        }


        private void ReinitRuntime_Click(object sender, EventArgs e)
        {
            SetupKinect();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            StopKinect();
        }


Now to track the hand gesture below event handler will be called each time the gesture is changed. First of all it creates the skeleton of the object(the human body) in front of the Kinect device.

void Sensor_SkeletonFrameReady(AllFramesReadyEventArgs e)
        {
            using (var frame = e.OpenSkeletonFrame())
            {
                if (frame != null)
                {
                    Skeleton[] skeletons = new Skeleton[frame.SkeletonArrayLength];

                    frame.CopySkeletonDataTo(skeletons);

                    var skeleton = skeletons.Where(s => s.TrackingState == SkeletonTrackingState.Tracked).FirstOrDefault();

                    if (skeleton != null)
                    {
                        //call the function to check the hand position                       
                        TrackHand(skeleton);
                    }
                }
            }
        }

 

The below function will now track the joints of the passed skeleton and then compares the coordinates of the right hand with respect to the head and shoulder. 

public bool TrackHand(Skeleton skeleton)
        {
            Joint rightHand = skeleton.Joints[JointType.HandRight];
            Joint leftHand = skeleton.Joints[JointType.HandLeft];
            Joint head = skeleton.Joints[JointType.Head];
            Joint rightShoulder = skeleton.Joints[JointType.ShoulderRight];

            string userName;

            if (rightHand.Position.Y > head.Position.Y) //if right hand is above head
            {
                userName = "david.skypeID";
                MessageBox.Show("Calling " + userName);
                CallSkype(userName);
                return true;
            }
            else
                if (leftHand.Position.Y > head.Position.Y) //if left hand is above head
                {
                    userName = "tom.skypeID";
                    MessageBox.Show("Calling " + userName);
                    CallSkype(userName);
                    return true;
                }
                else
                    if (rightHand.Position.X > rightShoulder.Position.X) //if right hand is in right direction to the shoulder
                    {
                        userName = "steve.skypeID";
                        MessageBox.Show("Calling " + userName);
                        CallSkype(userName);
                        return true;
                    }
                    else
                        if (rightHand.Position.X < rightShoulder.Position.X) //if right hand is in right direction to the shoulder
                        {
                            userName = "andy.skypeID";
                            MessageBox.Show("Calling " + userName);
                            CallSkype(userName);
                            return true;
                        }

            return false;
        }

Based on different gestures of hand as mentioned in above method the current user can call to different Skype users.

The CallSkype() function is actually used here to make the call based on the online status of users, and prompts accordingly. 

/**************************Skype***********************/

        public void CallSkype(string userNameToCall)
        {
            Call call = new Call();
            try
            {
                Start();

                // wait for the client to be connected and ready 
  skype.Attach(7, true); // 7 = protocol

                if (skype.CurrentUserStatus == TUserStatus.cusOnline) // check if calling user is online
                {
                    //check if user is online
                    User user = new User(skype.SearchForUsers(userNameToCall));
                    if (user.OnlineStatus == TOnlineStatus.olsOnline)
                    {
                        call = skype.PlaceCall(userNameToCall);
                        if (call.Status != TCallStatus.clsInProgress)
                        {
                            //some message
                            MessageBox.Show(call.Status.ToString());
                        }
                        MessageBox.Show(call.Status.ToString());
                    }
                    else
                    {
                        MessageBox.Show(userNameToCall + " is " + call.Status.ToString());
                    }
                }
                else
                {
                    MessageBox.Show("Please get online to Skype.");
                }
                Shutdown();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: " + ex.Message);
            }
        }

        public void Start()
        {
            if (!skype.Client.IsRunning)
            {
                skype.Client.Start(true, true);
            }
        }

        public void Shutdown()
        {
            if (skype.Client.IsRunning)
            {
                skype.Client.Shutdown();
            }
        }
        /*************************Skype Ends**********************************/

This is how we can make Skype calls by our gestures.

So let the gestures speak, till then keep learning and keep exploring.

Tags:

Blog | Kinect Development

About Ignatiuz

Ignatiuz Technologies is an IT company offering technology solutions for customers keeping partner centric approach with a mantra "Compelling IT Solutions". The company is passionate to latest technologies & innovation. Our consulting led approach make our customers become partners & partner's transformation to global corporations.

Ignatiuz QR Code

Month List

Tag cloud