Speichern Sie Kinects v2.0 Motion in einer BVH-Datei

298

Ich möchte die Bewegungserfassungsdaten von Kinect 2 als BVH-Datei speichern. Ich habe Code für Kinect 1 gefunden, der hier zu finden ist . Ich ging den Code durch und fand einige Dinge, die ich nicht verstehen konnte. Zum Beispiel habe ich im erwähnten Code versucht zu verstehen, was genau das Skeleton- skelObjekt ist, das sich an mehreren Stellen im Code befindet. Wenn nicht, gibt es eine bekannte Anwendung, um das beabsichtigte Ziel zu erreichen?

BEARBEITEN: Ich habe versucht, das Skeleton-Skel in Body-Skel zu ändern, was meiner Meinung nach das entsprechende Objekt für Kinect SDK 2.0 ist. Ich habe jedoch einen Fehler, wenn ich versuche, die Position des Körpers zu ermitteln:

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);

Beim Aufrufen der Funktion Position für das Körperskelett sind Fehler aufgetreten. Wie kann ich das X, Y, Z des Skeletts in SDK 2.0 abrufen? Ich habe versucht, die obigen drei Zeilen zu ändern:

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: Grundsätzlich habe ich es geschafft, die a bvh-Datei nach dem Kombinieren von bodyBasicsWPF und kinect2bvh zu speichern. Es scheint jedoch, dass das Skelett, das ich speichere, nicht effizient ist. Es gibt seltsame Bewegungen in den Ellbogen. Ich versuche zu verstehen, ob ich etwas in der Datei kinectSkeletonBVH.cp ändern muss . Genauer gesagt, was sind die Änderungen in der Ausrichtung der Gelenkachse für die Kinect 2-Version? Wie kann ich die folgende Zeile ändern: skel.BoneOrientations[JointType.ShoulderCenter].AbsoluteRotation.Quaternion; Ich habe versucht, diese Zeile mit zu ändern skel.JointOrientations[JointType.ShoulderCenter].Orientation. Habe ich recht? Ich verwende den folgenden Code, um die Verbindung zu BVHBone-Objekten hinzuzufügen:

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);

Ich kann nicht verstehen, wo im Code the axis for every Jointberechnet wird.

Jose Ramon
quelle
9
Ich habe dieses Problem jedoch übersprungen. Wenn Sie eine Lösung haben, ist es gut, sie hier nicht nur für mich zu veröffentlichen, da ich viele Leute bemerkt habe, die nach dem Speichern von Bewegungen in bvh-Dateien suchen.
Jose Ramon
Ich kann die Kinect v1- und v2-Informationen für eine txt-Datei speichern. Diese BVH-Datei habe ich gerade gelesen und werde eine Funktion sein, die ich unserer Erfassungssoftware hinzufügen werde. Wenn Sie an den * .txt-Dateien interessiert sind, lassen Sie es mich einfach wissen. Ich habe noch keine richtige BVH-Lösung.
16per9
2
check: pterneas.com/2014/03/13/…
Khaled.K
1
Ich habe eine Möglichkeit, die Streams Kinect v1 und Kinect v2 ordnungsgemäß in txt zu schreiben. Wenn Sie es verwenden, können Sie möglicherweise die Dateien Ihres bvh für dasselbe Experiment überprüfen. Überprüfen Sie meine Biografie für weitere Informationen.
16per9
1
@ Khaled.K Wenn der Link, den Sie gepostet haben, dies beantwortet, würde es Ihnen etwas ausmachen, daraus eine Antwort auf diese Frage zu machen (gemäß dieser Meta-Frage )
Matt Thomas

Antworten:

2

Der Code, den Sie für Kinect 1.0 verwendet haben , um eine BVH- Datei zu erhalten, verwendet die Gelenkinformationen, um Knochenvektoren durch Lesen des Skeletts zu erstellen .

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;
..

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

Mit Ausnahme von Kinect 2.0 wurde die Skeleton- Klasse durch die Body- Klasse ersetzt. Sie müssen sie daher ändern, um stattdessen mit einem Body umzugehen , und die Gelenke erhalten, indem Sie die unten angegebenen Schritte ausführen.

// 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();
}

Wir haben auch eine Liste von Körpern hinzugefügt, in der alle körper- / skelettbezogenen Daten gespeichert werden. Wenn Sie für Kinect Version 1 entwickelt haben, stellen Sie fest, dass die Skeleton-Klasse durch die Body-Klasse ersetzt wurde. Erinnern Sie sich an den MultiSourceFrameReader? Diese Klasse gibt uns Zugriff auf jeden Stream, einschließlich des Body-Streams! Wir müssen dem Sensor lediglich mitteilen, dass wir Body-Tracking-Funktionen benötigen, indem wir beim Initialisieren des Lesegeräts einen zusätzlichen Parameter hinzufügen:

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

_reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;

Die Reader_MultiSourceFrameArrived-Methode wird aufgerufen, sobald ein neuer Frame verfügbar ist. Lassen Sie uns angeben, was in Bezug auf die Körperdaten passieren wird:

  1. Holen Sie sich einen Verweis auf den Körperrahmen
  2. Überprüfen Sie, ob der Körperrahmen null ist - dies ist entscheidend
  3. Initialisieren Sie die _bodies-Liste
  4. Rufen Sie die GetAndRefreshBodyData-Methode auf, um die Body-Daten in die Liste zu kopieren
  5. Durchlaufen Sie die Liste der Körper und machen Sie tolle Sachen!

Denken Sie immer daran, nach Nullwerten zu suchen. Kinect liefert Ihnen ungefähr 30 Bilder pro Sekunde - alles kann null sein oder fehlen! Hier ist der bisherige Code:

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...
                }
            }
        }
    }
}

Das ist es! Wir haben jetzt Zugang zu den Körpern, die Kinect identifiziert. Der nächste Schritt besteht darin, die Skelettinformationen auf dem Bildschirm anzuzeigen. Jeder Körper besteht aus 25 Gelenken. Der Sensor liefert uns die Position (X, Y, Z) und die Rotationsinformationen für jeden von ihnen. Darüber hinaus teilt Kinect uns mit, ob die Gelenke verfolgt, hypothetisiert oder nicht verfolgt werden. Es ist eine gute Praxis, zu überprüfen, ob ein Körper verfolgt wird, bevor kritische Funktionen ausgeführt werden.

Der folgende Code zeigt, wie wir auf die verschiedenen Körpergelenke zugreifen können:

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...
    }
}

Quelle: Vangos Pterneas Blog - KINECT FOR WINDOWS VERSION 2: KÖRPERVERFOLGUNG

Khaled.K
quelle