Kinect suivi latéral des squelettes
actuellement, J'utilise le Microsoft Kinect pour mesurer les angles entre les articulations. La plupart des mesures fonctionnent correctement. Chaque fois qu'une personne est assise de côté (sur une chaise) le Kinect ne suit pas le squelette avec précision. Pour illustrer mon problème, j'ai ajouté 3 photos du depthview Kinect.
As vous pouvez voir que 2 mesures sur 3 fonctionnent "correctement". Chaque fois que je lève la jambe, le Kinect arrête le traçage du squelette correctement. Est-ce que quelqu'un a une solution à ce problème, ou est-ce juste une limitation du Kinect?
Merci.
mise à Jour 1:
Le JointTrackingState-Enumeration
sur ces joints tracés montré à screenshot 2 sont marqués comme Inferred
, cependant la vue de profondeur suit mon corps entier.
Maj 2: À screenshot 2, j'essaie de suivre ma jambe avant, surlignée en vert. Je sais que l'autre jambe n'est pas tracée, mais ça n'a pas d'importance.
mise à Jour 3: Le code suivant sélectionne un squelette:
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;
}
chaque fois qu'un squelette est traqué que des données seront utilisées pour dessiner les points communs et calculer l'angle entre les joints.
mise à jour 4: J'ai testé Assis sur un "bloc", bien plus simple qu'une chaise. Malheureusement, le Kinect agit toujours de la même manière.
en dessous de 2 screenshots:
3 réponses
comme Renaud Dumont l'a déclaré, Je ferais quelque chose avec JointTrackingState
. Depuis que vous utilisez les genoux, j'ai utilisé les variables leftknee
et rightknee
qui sont Joints
pour le faire. Voici le code, vous pouvez utiliser JointType.FootRight
et JointType.FootLeft
et les types Hip
, mais je vous laisse le choix.
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))
{
}
ou alternativement, si vous vouliez qu'un genou soit suivi à la fois, ou les deux, vous pourriez faire ceci:
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)
{
}
FYI la raison pour laquelle le Skeleton
est first
est static
est parce qu'alors il peut être utilisé dans la fabrication des joints
static Skeleton first;
opposé à
Skeleton first;
Edition 1
Je suis arrivé à la conclusion que c'est extrêmement difficile à faire, je pense que la méthode ci-dessus va fonctionner, mais je voulais juste inclure ce que je travaille sur le cas vous pourriez trouver un moyen de le faire marcher. De toute façon, voici le code sur lequel je travaillais qui est un autre
class
qui est juste un autre SkeletalTrackingState
j'essayais de faire un Inferred
enum
dans lui. Mais malheureusement enum
sont impossible à inherit
. Si vous trouvez quelque chose à cet effet qui fonctionne, je vous respecterai comme un programmeur supérieur à moi pour toujours ;). Sans plus attendre: le .dll
que j'essayais de faire:
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;
}
}
}
}
le code dans votre projet (erreur de compilateur)
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);
Bonne chance, j'espère que cela vous aide à aller dans la bonne direction ou vous aide à tous!
Mon Code
Voici mon code que vous avez demandé. Oui, il est du Skeletal Tracking Fundamentals , mais ce code était ici et je ne voulais pas commencer un nouveau projet avec la plupart des mêmes choses. Profitez-en!
Code
// (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>
Voici une image juste pour montrer comment hors Kinect peut être parfois:
Conseil: notez comment seul mon bras est détecté et une partie de l'arrière-plan
le kinect ne suit pas le squelette avec précision en raison des limites de son propre SDK. Essentiall chaque fois que l'appareil tente de ramasser un squelette, on suppose toujours qu'il est orienté vers l'avant. Si vous sauvegardez les articulations, prenez une vue du haut vers le bas et tracez les coordonnées x et z cela est assez facile à voir.
je travaille aussi avec Kinect , vous pouvez obtenir la valeur pour les angles articulaires pour les angles articulaires de votre genou mais le problème que vous semblez faire face est due à Kinect lui-même car il valeurs inférées ne sont pas indiquées . Il est préférable que vous utilisiez tout le corps squelettique pour suivre votre genou et j'espère que vous obtiendrez toutes les valeurs pour votre mouvement de chaque articulation