如何跟踪头部位置

我想做类似于Johhny Lee在他的Wii头部跟踪中所做的事情http://www.youtube.com/watch?v=Jd3-eiid-Uw&feature=player_embedded

但我想使用Kinect。 由于微软的sdk暴露了骨骼关节,我曾希望我能够用它来获得头部位置。 问题是我想用我的台式电脑及其显示器来做这件事。 如果我将Kinect传感器放在我的显示器旁边并坐在桌子旁边。 几乎只有我的头部和颈部对于传感器是可见的,因此骨骼跟踪不会在我的头部位置上拾取。

是否有人熟悉使用Kinect的头部跟踪项目? 最好是在C#

我认为对于这个应用程序,您无法使用任何框架(如Microsoft的SDK或OpenNI)提供的骨架跟踪。

我建议通过对原始深度数据应用深度阈值来对用户的头部进行分段。 这应该导致背景减少。 我认为已有的方法可以做到这一点。

作为第二步,你想在分段用户中拥有类似轴的东西。 最简单的方法是使用opencv fitEllipse 。 返回椭圆的长轴与深度信息相结合,为您提供此轴。

此方法仅在大多数分段点属于用户头时才有效。 如果你离得更远,你必须考虑一种只分割头部的方法。 椭圆拟合应始终有效。

Windows SDK的官方Kinect有一些限制,它与XBox和XDK提供的指导一致,因为您需要距离传感器1.2米到3.5米才能使用Kinect传感器。 实际上,在OpenNI / NITE库等备用SDK中可以减少此限制,从而可以检测更接近传感器的骨架/对象。

你将在skeltal输入中遇到的问题是它只会检测头部与骨骼成比例的位置,但如果你将头部左右旋转则不会。 为了达到这个目的,你不会使用原始深度流和一些关于物体识别的智能,这有点复杂。

在过去,我使用过这个商业.NET API,它使用网络摄像头来跟踪头部动作,并实现您的目标: http : //luxand.com/facesdk/index2.php

您不需要kinect来跟踪您的头部位置。 你可以使用普通相机和openCV通过脸部追踪来做同样的事情。

这里有一个简单的例子: http : //vimeo.com/19464641

在video中我使用openCV来跟踪我的脸(你几乎看不到角落,但红点表示我的脸部位置)。

查看关于此类主题的Channel 9s 教程 。 你会去参加Skeletal Fundamentals Video。 但是如果你想节省时间,这里有一些代码。
XAML

      

内部代码

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Microsoft.Kinect; using Coding4Fun.Kinect.Wpf; namespace SkeletalTracking { ///  /// Interaction logic for MainWindow.xaml ///  public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } bool closing = false; const int skeletonCount = 6; Skeleton[] allSkeletons = new Skeleton[skeletonCount]; private void Window_Loaded(object sender, RoutedEventArgs e) { kinectSensorChooser1.KinectSensorChanged += new DependencyPropertyChangedEventHandler(kinectSensorChooser1_KinectSensorChanged); } void kinectSensorChooser1_KinectSensorChanged(object sender, DependencyPropertyChangedEventArgs e) { KinectSensor old = (KinectSensor)e.OldValue; StopKinect(old); KinectSensor sensor = (KinectSensor)e.NewValue; if (sensor == null) { return; } var parameters = new TransformSmoothParameters { Smoothing = 0.3f, Correction = 0.0f, Prediction = 0.0f, JitterRadius = 1.0f, MaxDeviationRadius = 0.5f }; //sensor.SkeletonStream.Enable(parameters); sensor.SkeletonStream.Enable(); sensor.AllFramesReady += new EventHandler(sensor_AllFramesReady); sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30); sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30); try { sensor.Start(); } catch (System.IO.IOException) { kinectSensorChooser1.AppConflictOccurred(); } } void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e) { if (closing) { return; } //Get a skeleton Skeleton first = GetFirstSkeleton(e); if (first == null) { return; } //set scaled position ScalePosition(headImage, first.Joints[JointType.Head]); //ScalePosition(leftEllipse, first.Joints[JointType.HandLeft]); //ScalePosition(rightEllipse, first.Joints[JointType.HandRight]); GetCameraPoint(first, e); } void GetCameraPoint(Skeleton first, AllFramesReadyEventArgs e) { using (DepthImageFrame depth = e.OpenDepthImageFrame()) { if (depth == null || kinectSensorChooser1.Kinect == null) { return; } //Map a joint location to a point on the depth map //head DepthImagePoint headDepthPoint = depth.MapFromSkeletonPoint(first.Joints[JointType.Head].Position); //left hand DepthImagePoint leftDepthPoint = depth.MapFromSkeletonPoint(first.Joints[JointType.HandLeft].Position); //right hand DepthImagePoint rightDepthPoint = depth.MapFromSkeletonPoint(first.Joints[JointType.HandRight].Position); //Map a depth point to a point on the color image //head ColorImagePoint headColorPoint = depth.MapToColorImagePoint(headDepthPoint.X, headDepthPoint.Y, ColorImageFormat.RgbResolution640x480Fps30); //left hand ColorImagePoint leftColorPoint = depth.MapToColorImagePoint(leftDepthPoint.X, leftDepthPoint.Y, ColorImageFormat.RgbResolution640x480Fps30); //right hand ColorImagePoint rightColorPoint = depth.MapToColorImagePoint(rightDepthPoint.X, rightDepthPoint.Y, ColorImageFormat.RgbResolution640x480Fps30); //Set location CameraPosition(headImage, headColorPoint); //CameraPosition(leftEllipse, leftColorPoint); //CameraPosition(rightEllipse, rightColorPoint); } } Skeleton GetFirstSkeleton(AllFramesReadyEventArgs e) { using (SkeletonFrame skeletonFrameData = e.OpenSkeletonFrame()) { if (skeletonFrameData == null) { return null; } skeletonFrameData.CopySkeletonDataTo(allSkeletons); //get the first tracked skeleton Skeleton first = (from s in allSkeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).FirstOrDefault(); return first; } } private void StopKinect(KinectSensor sensor) { if (sensor != null) { if (sensor.IsRunning) { //stop sensor sensor.Stop(); //stop audio if not null if (sensor.AudioSource != null) { sensor.AudioSource.Stop(); } } } } private void CameraPosition(FrameworkElement element, ColorImagePoint point) { //Divide by 2 for width and height so point is right in the middle // instead of in top/left corner Canvas.SetLeft(element, point.X - element.Width / 2); Canvas.SetTop(element, point.Y - element.Height / 2); } private void ScalePosition(FrameworkElement element, Joint joint) { //convert the value to X/Y //Joint scaledJoint = joint.ScaleTo(1280, 720); //convert & scale (.3 = means 1/3 of joint distance) //Joint scaledJoint = joint.ScaleTo(1280, 720, .3f, .3f); Canvas.SetLeft(element, scaledJoint.Position.X); Canvas.SetTop(element, scaledJoint.Position.Y); } private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { closing = true; StopKinect(kinectSensorChooser1.Kinect); } } } 

我个人会建议观看video,因为他们解释了一切。 祝你的项目好运!

我建议使用: Aforge.net以及Microsoft XNA Framework或仅Aforge.net。 你需要自己做一些开发。 我也在使用C#进行类似的事情。 我想你将无法找到一个完整的开箱即用的例子。 还没有人做过这件事。 (如果我错了,请纠正我)。