web-dev-qa-db-fra.com

Stocker la motion v2.0 de Kinect dans un fichier BVH

Je souhaite stocker les données de capture de mouvement de Kinect 2 dans un fichier BVH. J'ai trouvé le code qui le fait pour Kinect 1 qui peut être trouvé ici . J'ai parcouru le code et découvert plusieurs choses que je ne comprenais pas. Par exemple, dans le code mentionné, j'ai essayé de comprendre ce qu'est exactement l'objet squelette skel, trouvé à plusieurs endroits dans le code , est en fait. Si non, existe-t-il une application connue disponible pour accomplir le but recherché?

EDIT: J'ai essayé de changer Skelon Skel en Body Skel, ce qui, à mon avis, est l’objet correspondant de Kinect SDK 2.0. Cependant, j'ai une erreur quand j'essaie d'obtenir la position du corps:

tempMotionVektor[0] = -Math.Round( skel.Position.X * 100,2);
tempMotionVektor[1] = Math.Round( skel.Position.Y * 100,2) + 120;
tempMotionVektor[2] = 300 - Math.Round( skel.Position.Z * 100,2);

J'ai eu des erreurs en appelant la fonction Position pour le corps. Comment puis-je récupérer le X, Y, Z du squelette dans SDK 2.0 ?? J'ai essayé de changer les trois lignes ci-dessus pour:

tempMotionVektor[0] = -Math.Round(skel.Joints[0].Position.X * 100, 2);
tempMotionVektor[1] = Math.Round(skel.Joints[0].Position.Y * 100, 2) + 120;
tempMotionVektor[2] = 300 - Math.Round(skel.Joints[0].Position.Z * 100, 2);

EDIT: En gros, j’ai réussi à stocker le fichier bvh après avoir combiné bodyBasicsWPF et kinect2bvh. Cependant, il semble que le squelette que je stocke ne soit pas efficace. Il y a des mouvements étranges dans les coudes. J'essaie de comprendre si je dois changer quelque chose dans le fichier kinectSkeletonBVH.cp . Plus précisément, quels sont les changements d’orientation de l’axe des articulations pour la version kinect 2? Comment puis-je changer la ligne suivante: skel.BoneOrientations[JointType.ShoulderCenter].AbsoluteRotation.Quaternion; J'ai essayé de changer cette ligne avec skel.JointOrientations[JointType.ShoulderCenter].Orientation. Ai-je raison? J'utilise le code suivant pour ajouter le joint aux objets BVHBone:

BVHBone hipCenter = new BVHBone(null, JointType.SpineBase.ToString(), 6, TransAxis.None, true);
BVHBone hipCenter2 = new BVHBone(hipCenter, "HipCenter2", 3, TransAxis.Y, false);
BVHBone spine = new BVHBone(hipCenter2, JointType.SpineMid.ToString(), 3, TransAxis.Y, true);
BVHBone shoulderCenter = new BVHBone(spine, JointType.SpineShoulder.ToString(), 3, TransAxis.Y, true);

BVHBone collarLeft = new BVHBone(shoulderCenter, "CollarLeft", 3, TransAxis.X, false);
BVHBone shoulderLeft = new BVHBone(collarLeft, JointType.ShoulderLeft.ToString(), 3, TransAxis.X, true);
BVHBone elbowLeft = new BVHBone(shoulderLeft, JointType.ElbowLeft.ToString(), 3, TransAxis.X, true);
BVHBone wristLeft = new BVHBone(elbowLeft, JointType.WristLeft.ToString(), 3, TransAxis.X, true);
BVHBone handLeft = new BVHBone(wristLeft, JointType.HandLeft.ToString(), 0, TransAxis.X, true);

BVHBone neck = new BVHBone(shoulderCenter, "Neck", 3, TransAxis.Y, false);
BVHBone head = new BVHBone(neck, JointType.Head.ToString(), 3, TransAxis.Y, true);
BVHBone headtop = new BVHBone(head, "Headtop", 0, TransAxis.None, false);

Je ne comprends pas où se trouve le code the axis for every Joint est calculé.

296
Jose Ramon

Le code que vous avez utilisé pour Kinect 1.0 pour obtenir un [~ # ~] bvh [~ # ~] fichier utilise les informations sur les articulations pour construire des vecteurs osseux en lisant le squelette .

public static double[] getBoneVectorOutofJointPosition(BVHBone bvhBone, Skeleton skel)
{
    double[] boneVector = new double[3] { 0, 0, 0 };
    double[] boneVectorParent = new double[3] { 0, 0, 0 };
    string boneName = bvhBone.Name;

    JointType Joint;
    if (bvhBone.Root == true)
    {
        boneVector = new double[3] { 0, 0, 0 };
    }
    else
    {
        if (bvhBone.IsKinectJoint == true)
        {
            Joint = KinectSkeletonBVH.String2JointType(boneName);

            boneVector[0] = skel.Joints[Joint].Position.X;
            boneVector[1] = skel.Joints[Joint].Position.Y;
            boneVector[2] = skel.Joints[Joint].Position.Z;
..

Source: Nguyên Lê Đặng - Kinect2BVH.V2

Sauf dans Kinect 2.0 , la classe Skeleton a été remplacée par la classe Body , vous devez donc le changer pour traiter avec un Body à la place, et obtenez les joints en suivant les étapes citées ci-dessous.

// Kinect namespace
using Microsoft.Kinect;

// ...

// Kinect sensor and Kinect stream reader objects
KinectSensor _sensor;
MultiSourceFrameReader _reader;
IList<Body> _bodies;

// Kinect sensor initialization
_sensor = KinectSensor.GetDefault();

if (_sensor != null)
{
    _sensor.Open();
}

Nous avons également ajouté une liste de corps dans laquelle toutes les données relatives au corps/squelette seront sauvegardées. Si vous avez développé pour Kinect version 1, vous remarquerez que la classe Skeleton a été remplacée par la classe Body. Rappelez-vous le MultiSourceFrameReader? Cette classe nous donne accès à tous les flux, y compris le flux de corps! Nous devons simplement faire savoir au capteur que nous avons besoin de la fonctionnalité de suivi du corps en ajoutant un paramètre supplémentaire lors de l'initialisation du lecteur:

_reader = _sensor.OpenMultiSourceFrameReader(FrameSourceTypes.Color |
                                             FrameSourceTypes.Depth |
                                             FrameSourceTypes.Infrared |
                                             FrameSourceTypes.Body);

_reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;

La méthode Reader_MultiSourceFrameArrived sera appelée chaque fois qu'un nouveau cadre est disponible. Précisons ce qui se passera en termes de données corporelles:

  1. Obtenez une référence au cadre du corps
  2. Vérifiez si le cadre du corps est nul - c'est crucial
  3. Initialiser la liste _bodies
  4. Appelez la méthode GetAndRefreshBodyData afin de copier les données de corps dans la liste.
  5. Parcourez la liste des corps et faites des choses géniales!

Rappelez-vous toujours de vérifier les valeurs nulles. Kinect vous fournit environ 30 images par seconde - tout peut être nul ou manquant! Voici le code jusqu'à présent:

void Reader_MultiSourceFrameArrived(object sender,
            MultiSourceFrameArrivedEventArgs e)
{
    var reference = e.FrameReference.AcquireFrame();

    // Color
    // ...

    // Depth
    // ...

    // Infrared
    // ...

    // Body
    using (var frame = reference.BodyFrameReference.AcquireFrame())
    {
        if (frame != null)
        {
            _bodies = new Body[frame.BodyFrameSource.BodyCount];

            frame.GetAndRefreshBodyData(_bodies);

            foreach (var body in _bodies)
            {
                if (body != null)
                {
                    // Do something with the body...
                }
            }
        }
    }
}

Ça y est ...! Nous avons maintenant accès aux corps identifiés par Kinect. L'étape suivante consiste à afficher les informations du squelette à l'écran. Chaque corps est composé de 25 articulations. Le capteur nous fournit la position (X, Y, Z) et les informations de rotation pour chacune d’elles. De plus, Kinect nous permet de savoir si les articulations sont suivies, supposées ou non. Il est recommandé de vérifier si un corps est suivi avant d’exécuter des tâches critiques.

Le code suivant illustre comment nous pouvons accéder aux différentes articulations du corps:

if (body != null)
{
    if (body.IsTracked)
    {
        Joint head = body.Joints[JointType.Head];

        float x = head.Position.X;
        float y = head.Position.Y;
        float z = head.Position.Z;

        // Draw the joints...
    }
}

Source: Blog de Vangos Pterneas - Version 2 de KINECT FOR WINDOWS: SUIVI DU CORPS

2
Khaled.K