web-dev-qa-db-ja.com

Kinectのv2.0モーションをBVHファイルに保存する

Kinect 2からのモーションキャプチャデータをBVHファイルとして保存したいと思います。 here にあるKinect 1のコードを見つけました。コードを調べてみると、理解できないことがいくつか見つかりました。たとえば、前述のコードでは、コード内のいくつかの場所にあるスケルトンskelオブジェクトが実際に何であるかを正確に理解しようとしました。そうでない場合、目的を達成するために利用可能な既知のアプリケーションはありますか?

編集:Skeletonのスケルトンをkinect SDK 2.0の対応するオブジェクトだと思うBodyのスケルトンに変更しようとしました。しかし、体の位置を取得しようとするとエラーが発生しました:

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

Body骨格のPosition関数を呼び出すときにエラーが発生しました。 SDK 2.0でスケルトンのX、Y、Zを取得するにはどうすればよいですか?上記の3行を次のように変更しようとしました。

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

編集:基本的に、bodyBasicsWPFとkinect2bvhを組み合わせた後、bvhファイルを保存することができました。ただし、保存しているスケルトンは効率的ではないようです。肘に奇妙な動きがあります。ファイル内の何かを変更する必要があるかどうかを理解しようとしています kinectSkeletonBVH.cp 。具体的には、kinect 2バージョンの関節軸の向きの変更は何ですか。次の行を変更するにはどうすればよいですか:skel.BoneOrientations[JointType.ShoulderCenter].AbsoluteRotation.Quaternion;skel.JointOrientations[JointType.ShoulderCenter].Orientationでその行を変更しようとしました。私は正しいですか?次のコードを使用して、ジョイントを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);

コード内でthe axis for every Jointが計算される場所がわかりません。

296
Jose Ramon

Kinect 1.0BVHファイルを取得するために使用したコード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;
..

ソース: NguyênLêĐặng-Kinect2BVH.V2

Kinect 2.0を除き、SkeletonクラスはBodyクラスなので、代わりにBodyを処理するように変更する必要があります。そして、以下に引用した手順に従ってジョイントを取得します。

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

また、すべてのボディ/スケルトン関連データが保存されるボディのリストも追加しました。 Kinectバージョン1用に開発している場合、スケルトンクラスがボディクラスに置き換えられていることに気付くでしょう。 MultiSourceFrameReaderを覚えていますか?このクラスにより、ボディストリームを含むすべてのストリームにアクセスできます!リーダーを初期化するときに追加のパラメーターを追加することにより、ボディトラッキング機能が必要であることをセンサーに知らせる必要があります。

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

_reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;

Reader_MultiSourceFrameArrivedメソッドは、新しいフレームが利用可能になるたびに呼び出されます。身体データに関して何が起こるかを指定しましょう:

  1. 本体フレームへの参照を取得します
  2. ボディフレームがnullかどうかを確認します-これは重要です
  3. _bodiesリストを初期化する
  4. GetAndRefreshBodyDataメソッドを呼び出して、本文データをリストにコピーします
  5. 体のリストをループして、素晴らしいことをしてください!

Null値をチェックすることを常に忘れないでください。 Kinectは、1秒あたり約30フレームを提供します。何でもヌルまたは欠落する可能性があります。これまでのコードは次のとおりです。

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

これです! Kinectが特定するボディにアクセスできるようになりました。次のステップでは、スケルトン情報を画面に表示します。各ボディは25のジョイントで構成されています。センサーは、位置(X、Y、Z)とそれぞれの回転情報を提供します。さらに、Kinectは、ジョイントが追跡されているか、仮説化されているか、追跡されていないかを知らせます。重要な機能を実行する前に、身体が追跡されているかどうかを確認することをお勧めします。

次のコードは、さまざまな身体の関節にアクセスする方法を示しています。

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

出典: Vangos Pterneasブログ-KINECT FOR WINDOWS VERSION 2:BODY TRACKING

2
Khaled.K