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

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

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

編集: Skeleton skel を、Kinect SDK 2.0 に対応するオブジェクトであると思われる Body skel に変更しようとしました。ただし、ボディの位置を取得しようとするとエラーが発生しました。

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 ファイルを保存することができました。ただし、保存しているスケルトンは効率的ではないようです。肘の動きがおかしいです。ファイル内の何かを変更する必要があるかどうか理解しようとしています。kinectスケルトンBVH.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計算されるのか理解できません。

ベストアンサー1

Kinect 1.0でBVHファイルを取得するために使用したコードは、ジョイント情報を使用して、スケルトンを読み取ってボーン ベクトルを構築します。

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ên Lê Đặ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 用に開発したことがある場合は、Skeleton クラスが Body クラスに置き換えられていることに気付くでしょう。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 フレームを提供します。null または欠落しているものが存在する可能性があります。これまでのコードは次のとおりです。

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 バージョン 2: ボディ トラッキング

おすすめ記事