Kinect侧身骨架跟踪
目前我正在使用Microsoft Kinect测量关节之间的angular度。 大多数测量工作正常。 当一个人坐在椅子上时,Kinect将不会准确地跟踪骨架。 为了说明我的问题,我添加了3张Kinect深度图。
正如你所看到的,3个测量中的2个“正确地”工作。 每当我抬起我的腿,Kinect正确地停止骨骼跟踪。 有没有人有解决这个问题,或者这只是Kinect的限制?
谢谢。
更新1:在屏幕截图2上显示的这些跟踪关节上的JointTrackingState-Enumeration
被标记为Inferred
,但深度视图正在跟踪我的全身。
更新2:在截图2我试图跟踪我的前腿,突出显示为绿色。 我知道另一条腿没有被跟踪,但这没关系,我猜。
更新3:以下代码select一个框架:
private Skeleton StickySkeleton(Skeleton[] skeletons) { if (skeletons.Count<Skeleton>(skeleton => skeleton.TrackingId == _trackedSkeletonId) <= 0) { _trackedSkeletonId = -1; _skeleton = null; } if (_trackedSkeletonId == -1) { Skeleton foundSkeleton = skeletons.FirstOrDefault<Skeleton>(skeleton => skeleton.TrackingState == SkeletonTrackingState.Tracked); if (foundSkeleton != null) { _trackedSkeletonId = foundSkeleton.TrackingId; return foundSkeleton; } } return _skeleton; }
每当跟踪骨架时,将使用数据绘制关节点并计算关节之间的angular度。
更新4:我testing过坐在一个“块”上,比椅子简单得多。 不幸的是,Kinect仍然是一样的。
以下2个截图:
正如Renaud Dumont所说,我会用JointTrackingState
做些事情。 自从你使用膝盖以来,我使用了leftknee
和rightknee
的variables来完成。 这里的代码,你可以使用JointType.FootRight
和JointType.FootLeft
和Hip
types,但是我会留给你的。
static Skeleton first = new Skeleton(); Joint leftknee = first.Joints[JointType.KneeLeft]; Joint rightknee = first.Joints[JointType.KneeRight]; if ((leftknee.TrackingState == JointTrackingState.Inferred || leftknee.TrackingState == JointTrackingState.Tracked) && (rightknee.TrackingState == JointTrackingState.Tracked || rightknee.TrackingState == JointTrackingState.Inferred)) { }
或者,如果你只是想一次跟踪一个膝盖,或者两者兼而有之,你可以这样做:
if ((leftknee.TrackingState == JointTrackingState.Inferred || leftknee.TrackingState == JointTrackingState.Tracked) && (rightknee.TrackingState == JointTrackingState.Tracked || rightknee.TrackingState == JointTrackingState.Inferred)) { } else if (leftknee.TrackingState == JointTrackingState.Inferred || leftknee.TrackingState == JointTrackingState.Tracked) { } else if (rightknee.TrackingState == JointTrackingState.Inferred || rightknee.TrackingState == JointTrackingState.Tracked) { }
仅供参考Skeleton
first
是static
的原因是因为它可以用于制作关节
static Skeleton first;
反对
Skeleton first;
编辑1
我已经得出结论,这是非常困难的,我认为上述方法可行,但我只是想包括我正在工作的情况下,以便可以find某种方式使其工作。 反正这是我正在处理的代码是另一个class
,这只是另一个SkeletalTrackingState
我试图在其中Inferred
enum
。 但不幸的是, enum
是不可能 inherit
。 如果你发现这种效果有效,我会永远尊重你作为一个优秀的程序员;)。 没有更多的勇气:我试图做的.dll
:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Kinect; namespace IsInferred { public abstract class SkeletonInferred : Skeleton { public bool inferred; static Skeleton first1 = new Skeleton(); Joint handright; Joint handleft; Joint footright; Joint footleft; Joint ankleleft; Joint ankleright; Joint elbowleft; Joint elbowright; Joint head; Joint hipcenter; Joint hipleft; Joint hipright; Joint shouldercenter; Joint shoulderleft; Joint shoulderright; Joint kneeleft; Joint kneeright; Joint spine; Joint wristleft; Joint wristright; public SkeletonInferred(bool inferred) { } public enum Inferred { NotTracked = SkeletonTrackingState.NotTracked, PositionOnly = SkeletonTrackingState.PositionOnly, Tracked = SkeletonTrackingState.Tracked, Inferred = 3, } private void IsInferred(object sender, AllFramesReadyEventArgs e) { handright = first1.Joints[JointType.HandRight]; handleft = first1.Joints[JointType.HandLeft]; footright = first1.Joints[JointType.FootRight]; footleft = first1.Joints[JointType.FootLeft]; ankleleft = first1.Joints[JointType.AnkleLeft]; ankleright = first1.Joints[JointType.AnkleRight]; elbowleft = first1.Joints[JointType.ElbowLeft]; elbowright = first1.Joints[JointType.ElbowRight]; head = first1.Joints[JointType.Head]; hipcenter = first1.Joints[JointType.HipCenter]; hipleft = first1.Joints[JointType.HipLeft]; hipright = first1.Joints[JointType.HipRight]; shouldercenter = first1.Joints[JointType.ShoulderCenter]; shoulderleft = first1.Joints[JointType.ShoulderLeft]; shoulderright = first1.Joints[JointType.ShoulderRight]; kneeleft = first1.Joints[JointType.KneeLeft]; kneeright = first1.Joints[JointType.KneeRight]; spine = first1.Joints[JointType.Spine]; wristleft = first1.Joints[JointType.WristLeft]; wristright = first1.Joints[JointType.WristRight]; if (handleft.TrackingState == JointTrackingState.Inferred & handright.TrackingState == JointTrackingState.Inferred & head.TrackingState == JointTrackingState.Inferred & footleft.TrackingState == JointTrackingState.Inferred & footright.TrackingState == JointTrackingState.Inferred & ankleleft.TrackingState == JointTrackingState.Inferred & ankleright.TrackingState == JointTrackingState.Inferred & elbowleft.TrackingState == JointTrackingState.Inferred & elbowright.TrackingState == JointTrackingState.Inferred & hipcenter.TrackingState == JointTrackingState.Inferred & hipleft.TrackingState == JointTrackingState.Inferred & hipright.TrackingState == JointTrackingState.Inferred & shouldercenter.TrackingState == JointTrackingState.Inferred & shoulderleft.TrackingState == JointTrackingState.Inferred & shoulderright.TrackingState == JointTrackingState.Inferred & kneeleft.TrackingState == JointTrackingState.Inferred & kneeright.TrackingState == JointTrackingState.Inferred & spine.TrackingState == JointTrackingState.Inferred & wristleft.TrackingState == JointTrackingState.Inferred & wristright.TrackingState == JointTrackingState.Inferred) { inferred = true; } } } }
你的项目中的代码(编译器错误)
using IsInferred; static bool Inferred = false; SkeletonInferred inferred = new SkeletonInferred(Inferred); static Skeleton first1 = new Skeleton(); Skeleton foundSkeleton = skeletons.FirstOrDefault<Skeleton>(skeleton => skeleton.TrackingState == SkeletonTrackingState.Inferred);
祝你好运,我希望这可以帮助你走向正确的方向或帮助你!
我的代码
这是我要求的代码。 是的,它来自骨架跟踪基础 ,但是这个代码在这里,我不想用大部分相同的东西开始一个新的项目。 请享用!
码
// (c) Copyright Microsoft Corporation. // This source is subject to the Microsoft Public License (Ms-PL). // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // All other rights reserved. 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]); ScalePosition(leftknee, first.Joints[JointType.KneeLeft]); ScalePosition(rightknee, first.Joints[JointType.KneeRight]); 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); DepthImagePoint rightKnee = depth.MapFromSkeletonPoint(first.Joints[JointType.KneeRight].Position); DepthImagePoint leftKnee = depth.MapFromSkeletonPoint(first.Joints[JointType.KneeLeft].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); ColorImagePoint leftKneeColorPoint = depth.MapToColorImagePoint(leftKnee.X, leftKnee.Y, ColorImageFormat.RgbResolution640x480Fps30); ColorImagePoint rightKneeColorPoint = depth.MapToColorImagePoint(rightKnee.X, rightKnee.Y, ColorImageFormat.RgbResolution640x480Fps30); //Set location CameraPosition(headImage, headColorPoint); CameraPosition(leftEllipse, leftColorPoint); CameraPosition(rightEllipse, rightColorPoint); Joint LEFTKNEE = first.Joints[JointType.KneeLeft]; Joint RIGHTKNEE = first.Joints[JointType.KneeRight]; if ((LEFTKNEE.TrackingState == JointTrackingState.Inferred || LEFTKNEE.TrackingState == JointTrackingState.Tracked) && (RIGHTKNEE.TrackingState == JointTrackingState.Tracked || RIGHTKNEE.TrackingState == JointTrackingState.Inferred)) { CameraPosition(rightknee, rightKneeColorPoint); CameraPosition(leftknee, leftKneeColorPoint); } else if (LEFTKNEE.TrackingState == JointTrackingState.Inferred || LEFTKNEE.TrackingState == JointTrackingState.Tracked) { CameraPosition(leftknee, leftKneeColorPoint); } else if (RIGHTKNEE.TrackingState == JointTrackingState.Inferred || RIGHTKNEE.TrackingState == JointTrackingState.Tracked) { CameraPosition(rightknee, rightKneeColorPoint); } } } 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); } private void kinectDepthViewer1_Loaded(object sender, RoutedEventArgs e) { } } }
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}" /> <Ellipse Canvas.Left="0" Canvas.Top="0" Height="50" Name="leftEllipse" Width="50" Fill="#FF4D298D" Opacity="1" Stroke="White" /> <Ellipse Canvas.Left="100" Canvas.Top="0" Fill="#FF2CACE3" Height="50" Name="rightEllipse" Width="50" Opacity="1" Stroke="White" /> <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" /> <Ellipse Canvas.Left="283" Canvas.Top="233" Height="23" Name="leftknee" Stroke="Black" Width="29" /> <Ellipse Canvas.Left="232" Canvas.Top="233" Height="23" Name="rightknee" Stroke="Black" Width="30" /> </Canvas>
下面是一张照片,仅仅是为了展示Kinect有时可以如何:
提示:注意只有我的arm被检测到,并且是背景的一部分
由于SDK本身的限制,kinect无法准确地跟踪骨架。 Essentiall每当设备尝试拾取一个骨架时,总是假设它是正面的。 如果您保存关节,请从上到下查看并绘制x和z坐标,这很容易看出来。
我也在使用Kinect,你可以得到膝关节angular度的关节angular度值,但是你似乎面临的问题是由于Kinect本身,因为它的推断值没有显示出来。 它更好地使用整个骷髅身体跟踪你的膝盖,希望你会得到你的每个关节的运动的所有价值