Przechowuj Motion Kinect v2.0 Motion do pliku BVH


298

Chciałbym zapisać dane przechwytywania ruchu z Kinect 2 jako plik BVH. Znalazłem kod, który robi to dla Kinect 1, który można znaleźć tutaj . Przejrzałem kod i znalazłem kilka rzeczy, których nie byłem w stanie zrozumieć. Na przykład we wspomnianym kodzie próbowałem zrozumieć, czym dokładnie jest skelobiekt Skeleton , znaleziony w kilku miejscach w kodzie. Jeśli nie, to czy są dostępne jakieś znane aplikacje do osiągnięcia zamierzonego celu?

EDYCJA: Próbowałem zmienić szkielet szkieletu na szkielet ciała, który moim zdaniem jest odpowiednim obiektem dla kinect SDK 2.0. Mam jednak błąd, gdy próbuję uzyskać pozycję ciała:

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

Wystąpiły błędy podczas wywoływania funkcji Pozycja dla szkieletu ciała. Jak mogę pobrać X, Y, Z szkieletu w SDK 2.0? Próbowałem zmienić powyższe trzy linie na:

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

EDYCJA: Zasadniczo udało mi się zapisać plik bvh po połączeniu bodyBasicsWPF i kinect2bvh. Wydaje się jednak, że szkielet, który przechowuję, nie jest wydajny. Dziwne ruchy w łokciach. Próbuję zrozumieć, czy muszę coś zmienić w pliku kinectSkeletonBVH.cp . Mówiąc dokładniej, jakie są zmiany orientacji osi złącza dla wersji kinect 2. Jak mogę zmienić następujący wiersz: skel.BoneOrientations[JointType.ShoulderCenter].AbsoluteRotation.Quaternion; Próbowałem zmienić ten wiersz za pomocą skel.JointOrientations[JointType.ShoulderCenter].Orientation. Czy mam rację? Używam następującego kodu, aby dodać połączenie do obiektów 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);

Nie rozumiem, gdzie the axis for every Jointjest obliczany kod .


9
Pominąłem ten problem, ale jeśli masz jakieś rozwiązanie, dobrze jest opublikować je tutaj nie tylko dla mnie, ponieważ zauważyłem, że wiele osób szuka przechowywania ruchów w plikach bvh.
Jose Ramon,

Jestem w stanie przechowywać informacje Kinect v1 i v2 dla pliku txt. Ten plik BVH to coś, co właśnie przeczytałem i będzie to funkcja, którą dodam do naszego oprogramowania do pozyskiwania. Jeśli jesteś zainteresowany plikami * .txt, daj mi znać. Nie mam jeszcze odpowiedniego rozwiązania BVH.
16per9


1
Mam sposób, aby poprawnie zapisać strumienie Kinect v1 i Kinect v2 w txt. Może jeśli go użyjesz, możesz dwukrotnie sprawdzić pliki BVH dla tego samego eksperymentu. Sprawdź moją biografię, aby uzyskać więcej informacji.
9

1
@ Khaled.K Jeśli link, który podałeś, odpowiada na to pytanie, czy mógłbyś sformułować to w odpowiedzi na to pytanie (według tego meta pytania )
Matt Thomas

Odpowiedzi:


2

Kod użyty w Kinect 1.0 do uzyskania pliku BVH wykorzystuje informacje o stawach do budowy wektorów kości poprzez czytanie Szkieletu .

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

Źródło: Nguyên Lê Đặng - Kinect2BVH.V2

Z wyjątkiem Kinect 2.0 , klasa Szkieletów została zastąpiona klasą Ciało , więc musisz ją zmienić, aby zamiast tego poradzić sobie z Ciałem , i uzyskać stawy, wykonując poniższe kroki.

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

Dodaliśmy również listę ciał, w której zostaną zapisane wszystkie dane dotyczące ciała / szkieletu. Jeśli opracowałeś wersję Kinect 1, zauważysz, że klasa Szkielet została zastąpiona klasą Body. Pamiętasz MultiSourceFrameReader? Ta klasa daje nam dostęp do każdego strumienia, w tym strumienia treści! Po prostu musimy poinformować czujnik, że potrzebujemy funkcji śledzenia ciała, dodając dodatkowy parametr podczas inicjalizacji czytnika:

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

_reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;

Metoda Reader_MultiSourceFrameArrived będzie wywoływana, gdy dostępna będzie nowa ramka. Określmy, co stanie się z danymi ciała:

  1. Uzyskaj odniesienie do ramy nadwozia
  2. Sprawdź, czy rama nadwozia ma wartość zerową - jest to bardzo ważne
  3. Zainicjuj listę _bodies
  4. Wywołaj metodę GetAndRefreshBodyData, aby skopiować dane ciała na listę
  5. Przeglądaj listę ciał i rób niesamowite rzeczy!

Zawsze pamiętaj, aby sprawdzić wartości zerowe. Kinect zapewnia około 30 klatek na sekundę - wszystko może być zerowe lub może brakować! Oto kod do tej pory:

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

To jest to! Mamy teraz dostęp do ciał, które identyfikuje Kinect. Następnym krokiem jest wyświetlenie informacji szkieletu na ekranie. Każde ciało składa się z 25 stawów. Czujnik podaje nam położenie (X, Y, Z) i informacje o obrocie dla każdego z nich. Co więcej, Kinect informuje nas, czy stawy są śledzone, hipotezowane, czy nie. Dobrą praktyką jest sprawdzanie, czy ciało jest śledzone przed wykonaniem jakichkolwiek krytycznych funkcji.

Poniższy kod ilustruje, w jaki sposób możemy uzyskać dostęp do różnych stawów ciała:

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

Źródło: Blog Vangos Pterneas - KINECT FOR WINDOWS VERSION 2: BODY TRACKING

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.