2014-02-15 46 views
3

我是kinect sdk v1.7的新手。如何捕捉Kinect SDK V1.7(Avateering XNA)中的運動數據?

我想知道如何從樣本採集運動數據。(http://msdn.microsoft.com/en-us/library/jj131041.aspx

所以,我怎麼能做出可以捕捉骨架數據轉換成文件的程序? (記錄)

然後,將文件讀回示例程序並對其進行建模(播放)?

我的想法是將骨架數據記錄到文件中,然後從文件中獲取骨架數據並讓頭像播放。

我可以做我想要的另一個示例程序。 (http://msdn.microsoft.com/en-us/library/hh855381),導致示例程序只繪製直線和骨架點。

例如,

00001 00:00:[email protected],349,354,332,358,249,353,202,310,278,286,349,269,407,266,430,401,279,425,349,445,408,453,433,332,369,301,460,276,539,269,565,372,370,379,466,387,548,389,575, 

00002 00:00:[email protected],349,353,332,356,249,352,202,309,278,284,349,266,406,263,430,398,279,424,349,445,408,453,433,331,369,301,461,277,541,271,566,371,371,379,466,387,548,390,575, 

[幀號] [時間戳] @ [骨架位置座標]

在這個例子中

,我假定骨架位置是聯合ID順序。

謝謝(原諒我可憐的英語)。

回答

2

您可以使用StreamWriter,在選定的路徑上初始化它,然後爲每個幀增加幀計數器,將其寫入文件,將時間戳寫入文件,然後遍歷關節並將它們寫入文件。我會做如下:

using System.IO; 

StreamWriter writer = new StreamWriter(@path); 
int frames = 0; 

... 

void AllFramesReady(object sender, AllFramesReadyEventArgs e) 
{ 
    frames++; 
    using (SkeletonFrame sFrame = e.OpenSkeletonFrameData()) 
    { 
     if (sFrame == null) 
      return; 

     skeletonFrame.CopySkeletonDataTo(skeletons); 

     Skeleton skeleton = (from s in skeletons 
           where s.TrackingState == SkeletonTrackingState.Tracked 
           select s); 
     if (skeleton == null) 
      return; 

     if (skeleton.TrackingState == SkeletonTrackingState.Tracked) 
     { 
      writer.Write("{0} {1}@", frames, timestamp);//I dont know how you want to do this 
      foreach (Joint joint in skeleton.Joints) 
      { 
       writer.Write(joint.Position.X + "," + joint.Position.Y + "," joint.Position.Z + ","); 
      } 
      writer.Write(Environment.NewLine); 
     } 
    } 
} 

然後從文件中讀取:

StreamReader reader = new StreamReader(@path); 
int frame = -1; 
JointCollection joints; 

... 

string[] lines = reader.ReadAllLines(); 

... 

void AllFramesReady(object sender, AllFramesReadyEventArgs e) 
{ 
    canvas.Children.Clear(); 
    string[] coords = lines[frame].Split('@')[1].Split(','); 
    int jointIndex = 0; 
    for (int i = 0; i < coords.Length; i += 3) 
    { 
     joints[jointIndex].Position.X = int.Parse(coords[i]); 
     joints[jointIndex].Position.Y = int.Parse(coords[i + 1]); 
     joints[jointIndex].Position.X = int.Parse(coords[i + 2]); 
     jointIndex++; 
    } 

    DepthImageFrame depthFrame = e.OpenDepthImageFrame(); 
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.HipCenter, JointType.Spine, JointType.ShoulderCenter, JointType.Head }, depthFrame, canvas)); 
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.ShoulderCenter, JointType.ShoulderLeft, JointType.ElbowLeft, JointType.WristLeft, JointType.HandLeft }, depthFrame, canvas)); 
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.ShoulderCenter, JointType.ShoulderRight, JointType.ElbowRight, JointType.WristRight, JointType.HandRight }, depthFrame, canvas)); 
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.HipCenter, JointType.HipLeft, JointType.KneeLeft, JointType.AnkleLeft, JointType.FootLeft }, depthFrame, canvas)); 
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.HipCenter, JointType.HipRight, JointType.KneeRight, JointType.AnkleRight, JointType.FootRight }, depthFrame, canvas)); 
    depthFrame.Dispose(); 

    frame++; 
} 

Point GetDisplayPosition(Joint joint, DepthImageFrame depthFrame, Canvas skeleton) 
{ 
    float depthX, depthY; 
    KinectSensor sensor = KinectSensor.KinectSensors[0]; 
    DepthImageFormat depthImageFormat = sensor.DepthStream.Format; 
    DepthImagePoint depthPoint = sensor.CoordinateMapper.MapSkeletonPointToDepthPoint(joint.Position, depthImageFormat); 

    depthX = depthPoint.X; 
    depthY = depthPoint.Y; 

    depthX = Math.Max(0, Math.Min(depthX * 320, 320)); 
    depthY = Math.Max(0, Math.Min(depthY * 240, 240)); 

    int colorX, colorY; 
    ColorImagePoint colorPoint = sensor.CoordinateMapper.MapDepthPointToColorPoint(depthImageFormat, depthPoint, ColorImageFormat.RgbResolution640x480Fps30); 
    colorX = colorPoint.X; 
    colorY = colorPoint.Y; 

    return new System.Windows.Point((int)(skeleton.Width * colorX/640.0), (int)(skeleton.Height * colorY/480)); 
} 

Polyline GetBodySegment(Joint[] joints, Brush brush, JointType[] ids, DepthImageFrame depthFrame, Canvas canvas) 
{ 
    PointCollection points = new PointCollection(ids.Length); 
    for (int i = 0; i < ids.Length; ++i) 
    { 
     points.Add(GetDisplayPosition(joints[i], depthFrame, canvas)); 
    } 
    Polyline polyline = new Polyline(); 
    polyline.Points = points; 
    polyline.Stroke = brush; 
    polyline.StrokeThickness = 5; 
    return polyline; 
} 

當然,在WPF這僅適用。你只需要使用更改代碼:

DepthImageFrame depthFrame = e.OpenDepthImageFrame(); 
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.HipCenter, JointType.Spine, JointType.ShoulderCenter, JointType.Head }, depthFrame, canvas)); 
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.ShoulderCenter, JointType.ShoulderLeft, JointType.ElbowLeft, JointType.WristLeft, JointType.HandLeft }, depthFrame, canvas)); 
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.ShoulderCenter, JointType.ShoulderRight, JointType.ElbowRight, JointType.WristRight, JointType.HandRight }, depthFrame, canvas)); 
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.HipCenter, JointType.HipLeft, JointType.KneeLeft, JointType.AnkleLeft, JointType.FootLeft }, depthFrame, canvas)); 
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.HipCenter, JointType.HipRight, JointType.KneeRight, JointType.AnkleRight, JointType.FootRight }, depthFrame, canvas)); 
    depthFrame.Dispose(); 

到avateering樣本如何動畫模型,你甚至可以創建一個新的Skeleton和複製jointsSkeleton.Joints,那麼就傳遞骨架的「檢測」骨架。請注意,您需要更改此示例中使用的函數所需的任何其他必需變量。我對樣本不熟悉,因此我不能提供具體的方法名稱,但是您可以用開頭創建的全局替換全局Skeleton並更新每一幀。因此,我建議這樣的:

//in the game class (AvateeringXNA.cs) 
StreamReader reader = new StreamReader(@path); 
int frame = -1; 
JointCollection joints; 
Skeleton recorded = new Skeleton(); 

... 

string[] lines = reader.ReadAllLines(); 

... 

void Update(...) 
{ 
    string[] coords = lines[frame].Split('@')[1].Split(','); 
    int jointIndex = 0; 
    for (int i = 0; i < coords.Length; i += 3) 
    { 
     joints[jointIndex].Position.X = int.Parse(coords[i]); 
     joints[jointIndex].Position.Y = int.Parse(coords[i + 1]); 
     joints[jointIndex].Position.X = int.Parse(coords[i + 2]); 
     jointIndex++; 
    } 

    recorded.Joints = joints; 

    ... 

    //preform necessary methods, except with recorded skeleton instead of detected, I think it is: 
    this.animator.CopySkeleton(recorded); 
    this.animator.FloorClipPlane = skeletonFrame.FloorClipPlane; 

    // Reset the filters if the skeleton was not seen before now 
    if (this.skeletonDetected == false) 
    { 
     this.animator.Reset(); 
    } 

    this.skeletonDetected = true; 
    this.animator.SkeletonVisible = true; 

    ... 

    frame++; 
} 

編輯

當你閱讀的起始樓面夾持平面(clipPlanes[0]),它會得到整個幀信息到第一個空間。見下面來看看它是如何將分裂,我將如何讀它:

var newFloorClipPlane = Tuple.Create(Single.Parse(clipPlanes[2]), Single.Parse(clipPlanes[3]), Single.Parse(clipPlanes[4]), Single.Parse(clipPlanes[5])); 

這裏是你如何佈局框架:

frame# [email protected],joint1posy,joint1posz,...jointNPosx,jointNposy,jointNposz floorX floorY floorZ floorW 

這裏是'產生的陣列。斯普利特(」「)

["frame#", "[email protected],joint1posy,joint1posz,...jointNPosx,jointNposy,jointNposz", "floorX", "floorY", "floorZ", "floorW"] 

因此,示例輸入:

00000002 [email protected],10,10... 11 12 13 14 

與您的代碼,你會得到:

[2, 10112101010..., 11, 12] 

從我的代碼修正指標:

[11, 12, 13, 14] 

把這一行放入控制檯權證申請的真快,看看它輸出:

Console.WriteLine(Convert.ToSingle("10,10")); 

輸出爲1010您正在試圖完成的任務,這造成了錯誤的地板上剪裁平面。你需要適當的索引來實現你想要達到的目標。

注:我改變Convert.ToSingleSingle.Parse,因爲它是更好的做法,並在堆棧跟蹤他們都瓶坯相同功能

+0

感謝您的回覆。 但我想用示例程序(Avatarring) 我在示例程序中找不到任何框架信息。 我想記錄骨架信息並將其放回到頭像中,然後播放。 但我只能找到關於skeleton的信息是skeleton []對象。如何以txt(字符串)格式記錄對象。並轉回到頭像模型? –

+0

我的意思是我想修改可以捕捉運動數據的示例程序。但我不知道該怎麼做。 –

+0

您可以使用我的相同代碼來捕捉運動,因爲它可以保存關節座標,並且您可以用相同的方式來讀取它,而不是寫入畫布將其轉換爲世界點並將頭像關節設置爲相對...我真的很快編輯@ user255 –

0

嘿你爲什麼不使用CSV方法寫入來講所有的關節數據excel文件。它會幫助你在稍後階段分析它們。我已經定製了我的代碼,用於將它們放入csv格式,這有助於我在數據的後期階段進行分析。你可以在你的項目中編寫一個單獨的文件,導出所有的骨架數據

public void CoordinatesExportToCSV(Skeleton data) 
    { 
     if (!TimeRecorded) 
     { 
      startTime = DateTime.Now; 
      TimeRecorded = true; 
     } 
     recordedSamples[1]++; 
     if (!titles) 
     { 
      sw1.Write("Counter,Time,Clipped Edges,"); 
      foreach (Joint joint in data.Joints) 
      { 
       sw1.Write(joint.JointType.ToString()+","); 
      } 
      titles = true; 
     } 
     else 
     { 
      double a = DateTime.Now.TimeOfDay.TotalSeconds - startTime.TimeOfDay.TotalSeconds; 
      sw1.Write(recordedSamples[1] + "," + a + "," + data.ClippedEdges); 

      foreach (Joint joint in data.Joints) 
      { 
       sw1.Write(joint.Position.X + "|" + joint.Position.Y + "|" + joint.Position.Z+","); 
      } 
     } 
     sw1.WriteLine(); 
    }