您可以使用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
和複製joints
到Skeleton.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.ToSingle
到Single.Parse
,因爲它是更好的做法,並在堆棧跟蹤他們都瓶坯相同功能
感謝您的回覆。 但我想用示例程序(Avatarring) 我在示例程序中找不到任何框架信息。 我想記錄骨架信息並將其放回到頭像中,然後播放。 但我只能找到關於skeleton的信息是skeleton []對象。如何以txt(字符串)格式記錄對象。並轉回到頭像模型? –
我的意思是我想修改可以捕捉運動數據的示例程序。但我不知道該怎麼做。 –
您可以使用我的相同代碼來捕捉運動,因爲它可以保存關節座標,並且您可以用相同的方式來讀取它,而不是寫入畫布將其轉換爲世界點並將頭像關節設置爲相對...我真的很快編輯@ user255 –