2011-07-13 32 views
6

tôi muốn làm một cái gì đó tương tự như những gì Johhny Lee đã làm trong đầu Wii mình để theo dõi http://www.youtube.com/watch?v=Jd3-eiid-Uw&feature=player_embeddedLàm thế nào để theo dõi vị trí đầu

Nhưng tôi muốn sử dụng Kinect. Kể từ khi sdk của Microsoft phơi bày các khớp xương, tôi đã hy vọng tôi có thể chỉ cần sử dụng để có được vị trí đầu. Vấn đề là tôi muốn làm điều này với máy tính để bàn và màn hình của nó. Nếu tôi đặt cảm biến Kinect ngay cạnh màn hình và ngồi vào bàn làm việc. khá nhiều chỉ là đầu và cổ của tôi có thể nhìn thấy cảm biến, do đó, theo dõi xương doesnt pickup trên vị trí đầu của tôi.

Có ai quen thuộc với dự án theo dõi đầu bằng Kinect không? Tốt nhất là trong C#

Trả lời

1

Có những giới hạn về Kinect chính thức cho Windows SDK, nằm trong dòng với hướng dẫn được cung cấp cho XBox và XDK ở chỗ bạn cần phải cách cảm biến từ 1,2m đến 3,5m để sử dụng cảm biến Kinect. Giới hạn này thực sự bị giảm trong các SDK thay thế như thư viện OpenNI/NITE cho phép bạn phát hiện bộ xương/đối tượng gần với cảm biến hơn.

Vấn đề bạn cũng sẽ có với đầu vào skeltal là nó sẽ chỉ phát hiện vị trí của đầu tỷ lệ với bộ xương, nhưng không phải nếu bạn xoay đầu của bạn sang bên. Để đạt được điều này, bạn sẽ không sử dụng các luồng độ sâu thô và một số thông minh xung quanh nhận dạng đối tượng mà phần nào phức tạp hơn.

Trong quá khứ tôi đã sử dụng API này NET thương mại trong đó sử dụng một webcam để theo dõi chuyển động đầu, và đạt được những gì bạn đang sau: http://luxand.com/facesdk/index2.php

2

Tôi nghĩ rằng đối với ứng dụng này, bạn không thể sử dụng theo dõi bộ xương được cung cấp bởi bất kỳ khung công tác nào như SDK của Microsoft hoặc OpenNI.

Tôi sẽ đề xuất phân đoạn người đứng đầu của người dùng bằng cách áp dụng ngưỡng độ sâu cho dữ liệu độ sâu thô. Điều này sẽ dẫn đến giảm nền. Tôi nghĩ rằng đã có các phương pháp hiện có mà làm điều này.

Bước thứ hai bạn muốn có thứ gì đó giống như trục bên trong người dùng được phân đoạn. Cách tiếp cận đơn giản nhất là sử dụng opencv fitEllipse. Trục chính của hình elip được trả về kết hợp với thông tin chiều sâu cung cấp cho bạn trục này.

Cách tiếp cận này chỉ hoạt động khi hầu hết các điểm được phân đoạn thuộc về người đứng đầu của người dùng. Nếu bạn đang đi xa hơn bạn phải suy nghĩ về một phương pháp để phân khúc chỉ đầu. Việc lắp hình elip phải luôn luôn hoạt động.

1

Bạn không cần kinect để theo dõi vị trí đầu của bạn. Bạn có thể làm điều tương tự với máy ảnh thông thường và openCV bằng cách sử dụng tính năng theo dõi khuôn mặt.

ví dụ đơn giản cho thấy ở đây: http://vimeo.com/19464641

Trong video Tôi đang sử dụng OpenCV để theo dõi khuôn mặt của tôi (mà bạn chỉ có thể nhìn thấy trong góc, nhưng chấm đỏ chỉ ra vị trí khuôn mặt của tôi).

+0

Ngoài ra, OpenCV có thể được truy cập thông qua C# với dự án emgu ([http://www.emgu.com/wiki/index.php/Main_Page]). Thậm chí còn có một phương pháp gọi KinectCapture bạn có thể sử dụng để có được một khung hình video và dễ dàng nhận diện khuôn mặt ([http://www.emgu.com/wiki/files/2.4.2/document/html/a8b9f573-4c88-fdc0- a3b1-189096e54caa.htm]) –

-1

Tôi đề nghị sử dụng: Aforge.net cùng với Microsoft XNA Framework hoặc chỉ riêng Aforge.net. Bạn sẽ cần phải làm một chút phát triển cho mình mặc dù. Tôi cũng đang làm việc trên điều tương tự bằng cách sử dụng C#. Tôi nghĩ bạn sẽ không thể tìm thấy một ví dụ hoàn chỉnh. Chưa có cơ thể nào làm được điều đó. (Đúng nếu tôi đã sai lầm).

1

Khám phá Kênh 9s tutorials về loại chủ đề này. Bạn sẽ đi đến Video cơ bản về xương. Nhưng đây là một số mã nếu bạn muốn tiết kiệm thời gian.
XAML

<Window x:Class="SkeletalTracking.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="600" Width="800" Loaded="Window_Loaded" 
    xmlns:my="clr-namespace:Microsoft.Samples.Kinect.WpfViewers;assembly=Microsoft.Samples.Kinect.WpfViewers" 
    Closing="Window_Closing" WindowState="Maximized">  
<Canvas Name="MainCanvas"> 
    <my:KinectColorViewer Canvas.Left="0" Canvas.Top="0" Width="640" Height="480" Name="kinectColorViewer1" 
          Kinect="{Binding ElementName=kinectSensorChooser1, Path=Kinect}" /> 
    <my:KinectSensorChooser Canvas.Left="250" Canvas.Top="380" Name="kinectSensorChooser1" Width="328" /> 
    <Image Canvas.Left="66" Canvas.Top="90" Height="87" Name="headImage" Stretch="Fill" Width="84" Source="/SkeletalTracking;component/c4f-color.png" /> 
</Canvas> 

Internal Mã

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 
{ 
/// <summary> 
/// Interaction logic for MainWindow.xaml 
/// </summary> 
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<AllFramesReadyEventArgs>(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); 
    } 



    } 
} 

Cá nhân tôi sẽ khuyên bạn nên xem các đoạn video vì họ giải thích tất cả mọi thứ. Chúc may mắn với dự án của bạn!

Các vấn đề liên quan