Simpan Gerakan Kinect's v2.0 ke BVH File

298

Saya ingin menyimpan data motion capture dari Kinect 2 sebagai file BVH. Saya menemukan kode yang melakukannya untuk Kinect 1 yang dapat ditemukan di sini . Saya membaca kode dan menemukan beberapa hal yang tidak dapat saya mengerti. Misalnya, dalam kode yang disebutkan saya sudah mencoba memahami apa sebenarnya skelobjek Kerangka , yang ditemukan di beberapa tempat dalam kode, sebenarnya. Jika tidak, apakah ada aplikasi yang dikenal tersedia untuk mencapai yang dimaksud?

EDIT: Saya mencoba mengubah Skeleton skel menjadi Body skel yang menurut saya adalah objek koresponden untuk kinect SDK 2.0. Namun saya mendapat kesalahan saat mencoba mendapatkan posisi tubuh:

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

Saya mendapatkan kesalahan saat memanggil fungsi Position for the Body skel. Bagaimana saya bisa mengambil X, Y, Z dari kerangka di SDK 2.0 ?? Saya mencoba mengubah tiga baris di atas menjadi:

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: Pada dasarnya saya berhasil menyimpan file bvh setelah menggabungkan bodyBasicsWPF dan kinect2bvh. Namun, tampaknya kerangka yang saya simpan tidak efisien. Ada gerakan aneh di siku. Saya mencoba memahami jika saya harus mengubah sesuatu di file kinectSkeletonBVH.cp . Lebih khusus, apa saja perubahan dalam orientasi sumbu sendi untuk versi kinect 2. Bagaimana saya bisa mengubah baris berikut: skel.BoneOrientations[JointType.ShoulderCenter].AbsoluteRotation.Quaternion; Saya mencoba mengubah baris itu dengan skel.JointOrientations[JointType.ShoulderCenter].Orientation. Apakah saya benar? Saya menggunakan kode berikut untuk menambahkan sambungan ke objek 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);

Saya tidak bisa mengerti di mana di dalam kode the axis for every Jointdihitung.

Jose Ramon
sumber
9
Namun saya melewatkan masalah ini. Jika Anda memiliki solusi, ada baiknya mempostingnya di sini bukan hanya untuk saya, karena saya perhatikan banyak orang yang mencari penyimpanan gerakan dalam file bvh.
Jose Ramon
Saya dapat menyimpan informasi Kinect v1 dan v2 untuk file txt. File BVH ini adalah sesuatu yang baru saja saya baca dan itu akan menjadi fitur yang akan saya tambahkan ke perangkat lunak akuisisi kami. Jika Anda tertarik dengan file * .txt, beri tahu saya. Saya belum memiliki solusi BVH yang tepat.
16per9
2
periksa: pterneas.com/2014/03/13/…
Khaled.K
1
Saya punya cara untuk benar menulis aliran Kinect v1 dan Kinect v2 ke txt. Mungkin jika Anda menggunakannya, Anda dapat memeriksa ulang file bvh Anda untuk percobaan yang sama. Periksa bio saya untuk info lebih lanjut.
16per9
1
@ Khaled.K Jika tautan yang Anda poskan menjawab ini, maukah Anda membuatnya menjadi jawaban untuk pertanyaan ini (per pertanyaan meta ini )
Matt Thomas

Jawaban:

2

Kode yang Anda gunakan untuk Kinect 1.0 untuk mendapatkan file BVH menggunakan informasi sambungan untuk membuat vektor tulang dengan membaca Skeleton .

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

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

Kecuali di Kinect 2.0 , kelas Skeleton telah digantikan oleh kelas Body , jadi Anda perlu mengubahnya untuk berurusan dengan Body , dan dapatkan sambungan dengan mengikuti langkah-langkah yang dikutip di bawah ini.

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

Kami juga menambahkan daftar tubuh, di mana semua data terkait tubuh / kerangka akan disimpan. Jika Anda telah mengembangkan untuk Kinect versi 1, Anda perhatikan bahwa kelas Skeleton telah digantikan oleh kelas Body. Ingat MultiSourceFrameReader? Kelas ini memberi kita akses di setiap aliran, termasuk aliran tubuh! Kami hanya perlu memberi tahu sensor bahwa kami membutuhkan fungsionalitas pelacakan tubuh dengan menambahkan parameter tambahan saat menginisialisasi pembaca:

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

_reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;

Metode Reader_MultiSourceFrameArrived akan dipanggil setiap kali bingkai baru tersedia. Mari kita tentukan apa yang akan terjadi dalam hal data tubuh:

  1. Dapatkan referensi ke kerangka tubuh
  2. Periksa apakah kerangka tubuh adalah nol - ini sangat penting
  3. Inisialisasi daftar _bodies
  4. Panggil metode GetAndRefreshBodyData, untuk menyalin data tubuh ke dalam daftar
  5. Lingkari daftar tubuh dan lakukan hal-hal yang luar biasa!

Selalu ingat untuk memeriksa nilai null. Kinect memberi Anda sekitar 30 frame per detik - apa pun bisa menjadi nol atau hilang! Berikut ini kodenya:

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

Ini dia! Kami sekarang memiliki akses ke tubuh yang diidentifikasi Kinect. Langkah selanjutnya adalah menampilkan informasi kerangka di layar. Setiap tubuh terdiri dari 25 sendi. Sensor memberi kita posisi (X, Y, Z) dan informasi rotasi untuk masing-masing. Selain itu, Kinect memberi tahu kami apakah persendian dilacak, dihipotesiskan atau tidak dilacak. Merupakan praktik yang baik untuk memeriksa apakah tubuh dilacak sebelum melakukan fungsi kritis.

Kode berikut menggambarkan bagaimana kita dapat mengakses sendi tubuh yang berbeda:

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

Sumber: Vangos Pterneas Blog - KINECT FOR WINDOWS VERSION 2: PELACAKAN TUBUH

Khaled.K
sumber