With the inclusion of the InteractionStream and the ability to detect a Grip gesture in the Kinect for Windows SDK Update 1.7 it’s now possible to grab UI elements on a screen and move them around. This blog post shows a possible implementation in a WPF application. Please notice that I’m using the following nuGet packages
- FluentKinect to initialize the Kinect sensor
- Rx-Main to have the LINQ operators available on events
- Rx-PlatformServices includes ObserveOnDispatcher()
- Kinect.Reactive to subscribe to the InteractionStream
Code-Behind: MainWindow.cs
// this code can be called after initialization of the MainWindow // Get a kinect instance with started SkeletonStream and DepthStream var kinect = await KinectConnector.GetKinect(); kinect.KickStart(); // instantiate an object that implements IInteractionClient var interactionClient = new InteractionClient(); // GetUserInfoObservable() method is available through Kinect.Reactive kinect.GetUserInfoObservable(interactionClient) .SelectMany(_ => _.Select(__ => __.HandPointers.Where(___ => ___.IsActive))) .Where(_ => _.FirstOrDefault() != null) .Select(_ => _.First()) .ObserveOnDispatcher() .Subscribe(_ => { var region = this.kinectRegion; var p = new Point(_.X * region.ActualWidth, _.Y * region.ActualHeight); if (_.HandEventType == InteractionHandEventType.Grip) { var elem = this.kinectRegion.InputHitTest(p) as TextBlock)); if (elem != null) { this.lastTouched = elem; } } else if(_.HandEventType == InteractionHandEventType.GripRelease) { this.lastTouched = null; } else { if (this.lastTouched == null) return; Canvas.SetLeft(this.lastTouched, p.X - this.lastTouched.ActualWidth / 2); Canvas.SetTop(this.lastTouched, p.Y - this.lastTouched.ActualHeight / 2); } });
XAML: MainWindow.xaml
<Window x:Class="DragAndDrop.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:dd="clr-namespace:DragAndDrop" xmlns:k="clr-namespace:Microsoft.Kinect.Toolkit.Controls;assembly=Microsoft.Kinect.Toolkit.Controls" Title="MainWindow" WindowState="Maximized"> <Window.Resources> <Style TargetType="TextBlock"> <Setter Property="Height" Value="200" /> <Setter Property="Width" Value="200" /> <Setter Property="Foreground" Value="White" /> <Setter Property="FontWeight" Value="ExtraBold" /> <Setter Property="FontSize" Value="35" /> <Setter Property="Text" Value="Drag Me" /> <Setter Property="TextAlignment" Value="Center" /> <Setter Property="Background" Value="Black" /> </Style> </Window.Resources> <k:KinectRegion x:Name="kinectRegion" KinectSensor="{Binding Kinect}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="100" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid Grid.Row="0"> <k:KinectUserViewer x:Name="userViewer" /> </Grid> <Canvas Grid.Row="1"> <TextBlock Canvas.Left="50" Canvas.Top="50" /> <TextBlock Canvas.Left="260" Canvas.Top="50" /> <TextBlock Canvas.Left="470" Canvas.Top="50" /> <TextBlock Canvas.Left="680" Canvas.Top="50" /> <TextBlock Canvas.Left="890" Canvas.Top="50" /> </Canvas> </Grid> </k:KinectRegion> </Window>
Hi,
I have tried tour code with the three packages I have installed with package manager console.
I have two properties unavailable.
First one HandPointers in the skeleton and lastTouched in the MainWindow.
Any idea? My version of the toolkit is 1.8.
Thank you!
JSB
Hi,
please make sure that you’ve added all necessary using statement in MainWindow.cs
using FluentKinect;
using Kinect.Reactive;
using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit.Interaction;
using System;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
The missing lastTouched object is just a private field of type TextBlock in MainWindow.cs
See this gist for further reference: https://gist.github.com/MarcusKohnert/51dc6e457f24db19771f
Hi,
thanks a lot for the feedback.
Sorry to bother you again.
Now, I’ve got an error with ObserveOnDispatcher.
It’s seem the property is not available. I’ve looking on the web , they said I can find out in System.Reactive.Windows.Threading but Reactive.windows doesn’t exists in my version.
I’m lost, I really need to use the drag and drop with Kinect.
Thanks a lot for your help.
Regards,
JSB
I’m sorry, you are right. I’ve missed to add the package http://www.nuget.org/packages/Rx-PlatformServices/ as a dependency.
This package should have System.Reactive.Windows.Threading.dll
In this dll you’ll find the namespace System.Reactive.Linq which has a static class DispatcherObservable.
This class brings all the extension methods for WPF, like ObserveOnDispatcher.
Hope it works out now. 😉
HI,
I already have the Rx-PlatformServices. But can’t find out System.Reactive.Windows.Threading.dll
I have System.Reactive.Linq in Rx-Linq.2.2.5, I have installed this one. When I comment “ObserveOnDispatcher()” and run the program, I’ve got a assembly conflict with System.Reactive.Linq. I think there is another reference in Kinect.reactive, but not sure.
It’s really hard to setup everything, I don’t thing it could take so long. 🙂
Thanks a lot for your time.
JSB
mmmhhh… really strange…
There is another implementation here: https://github.com/MarcusKohnert/BASTA2013/tree/master/Basta.DragAndDrop
Hi Marcus,
I just have somethings to say…It’s aliveee! It’s aliveeee! hehe!
Thanks a lot, your “Basta 2013” code works.
Best Regards,
JSB
Perfect! I’m glad it worked out for you…
Hey Marcus. Do those libraries work with kinect v1?
Those mentioned in this blog post surely do.
Do they have the relationship between “Drag & Drop” and “Hoverbutton”?
I’m thinking that if the function of Hoverbutton including Drag & Drop, can it works?
Hello Marcus.
I’m sorry for that I didn’t say hello for you first.
May I ask that do they have the relationship between “Drag & Drop” and “Hover Button”?
I’m thinking that if the function of Hover Button including Drag & Drop, can it works?
Thank you very much.
I’m a student. My name is Joyce.
Hi there,
I’m really sorry but I don’t understand the question.
Thanks a lot, your “Basta 2013” code works.
but ı want ask a question how can ı enable or disable hands. for example only active right hant or left hand
You should be able to filter events by hand type. Probably in MainWindows.cs line number 12. Don’t have the source at hat but something similar to this:
__.HandPointers.Where(___ => ___.IsActive && __.IsLeft)
Thanks a lot, your “Basta 2013” code works.
ı change some where. but I want ask q question. can we detect finger grip.
As far as I know that’s not possible with the Kinect for Windows SDK. But there are community projects out there in the web.