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.

Seated sideways measurement with skeleton tracking

Seated sideways measurement without skeleton tracking

Sideways measurement with skeleton tracking

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:

Sitting on a block 1

Sitting on a block 2

42
demandé sur Yi Jiang 2012-04-17 17:43:52

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

13
répondu Liam McInroy 2017-05-23 11:54:24

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.

0
répondu user2299275 2013-04-19 12:59:32

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

0
répondu user2823510 2013-11-22 23:28:58