为Kinects深度场创建3D面部网格

时间:2013-02-01 14:01:29

标签: c# kinect kinect-sdk

Kinect SDK附带了一个在颜色流上创建面部网格的示例。看起来像是:

http://imgur.com/TV6dHBC

我想为深度流创建一个3D网格

我的代码目前看起来如下:

private EnumIndexableCollection<FeaturePoint, PointF> facePoints;
private EnumIndexableCollection<FeaturePoint, Vector3DF> depthPoints;

public void DrawFaceModel(DrawingContext drawingContext)
{
    if (!this.lastFaceTrackSucceeded || this.skeletonTrackingState != SkeletonTrackingState.Tracked)
        return;

    var faceModelPts = new List<Point>();
    var faceModelPts3D = new List<Point3D>();
    var faceModel = new List<FaceModelTriangle>();
    var faceModel3D = new List<FaceModelTriangle3D>();

    for (int i = 0; i < this.facePoints.Count; i++)
    {
        faceModelPts3D.Add(new Point3D(this.depthPoints[i].X + 0.5f, this.depthPoints[i].Y + 0.5f, this.depthPoints[i].Z + 0.5f));
    }

    FaceDataPoints.Number_of_Points = this.facePoints.Count;

    foreach (var t in ImageData.faceTriangles)
    {
        var triangle = new FaceModelTriangle3D();
        triangle.Point1_3D = faceModelPts3D[t.First];
        triangle.Point2_3D = faceModelPts3D[t.Second];
        triangle.Point3_3D = faceModelPts3D[t.Third];
        faceModel3D.Add(triangle);
    }

    var faceModelGroup = new GeometryGroup();
    for (int i = 0; i < faceModel.Count; i++)
    {
        var faceTriangle = new GeometryGroup();  
        faceTriangle.Children.Add(new LineGeometry(faceModel3D[i].Point1_3D, faceModel3D[i].Point2_3D)); 
        faceTriangle.Children.Add(new LineGeometry(faceModel3D[i].Point2_3D, faceModel3D[i].Point3_3D));
        faceTriangle.Children.Add(new LineGeometry(faceModel3D[i].Point3_3D, faceModel3D[i].Point1_3D));
        faceModelGroup.Children.Add(faceTriangle); //Add lines to image
    }

    drawingContext.DrawGeometry(Brushes.LightYellow, new Pen(Brushes.LightYellow, 1.0), faceModelGroup);
}

private struct FaceModelTriangle3D
{
     public Point3D Point1_3D;
     public Point3D Point2_3D;
     public Point3D Point3_3D;
}

我目前收到错误 “错误2参数1:无法从'System.Windows.Media.Media3D.Point3D'转换为'System.Windows.Point'F:\ Work \ Uni \ 4th Year \ Final Year Project \ Project \ Project 3.0 \ Project 3.0 \ FaceTrackingViewer.xaml.cs 275 68项目3.0 “

由以下原因引起:

(new LineGeometry(faceModel3D[i].Point2_3D, faceModel3D[i].Point3_3D));

我需要使用什么代替LineGeometry来实现这项工作,还是有更有效的方法来实现这一目标?

此外,一旦我创建了面部网格,我还希望能够存储此信息,以便能够计算面部点之间的距离。那么我将如何存储三角形信息呢?

3 个答案:

答案 0 :(得分:0)

面部跟踪基础知识WPF示例使用Point2D,但您使用的是Point3D。

这意味着您将3D坐标传递给LineGeometry构造函数,该构造函数用于2D绘图。您需要将3D世界坐标转换为2D屏幕坐标;一个称为投影的过程。

WPF包含一个透视摄像机类,应该可以胜任工作

System.Windows.Media.Media3D.PerspectiveCamera

了解在WPF中创建3D场景 - MSDN

答案 1 :(得分:0)

确实需要从3D投影到2D。但是,您应该使用Kinect框架的校准投影方法,而不是滚动自己的投影:

Microsoft.Kinect.CoordinateMapper.MapSkeletonPointToDepthPoint()

请参阅http://msdn.microsoft.com/en-us/library/jj883696.aspx

答案 2 :(得分:0)

  

How to get mesh from kinect fracetrack?

对于第二个问题:
三角形信息为您提供面部,因此如果您想将其存储在例如a .obj,然后

  1. 顶点:v x y z
    (x,y,z应该用代表坐标的相应数字代替,而v代表你列出顶点)

  2. 三角形的面孔:f i j k
    (x,y,z应该用代表坐标的相应数字代替,而f则表示你列出了面部)

  3. 你有你的.obj

    如果你将它存储在程序中,那么我会建议两个容器(可能是数组或链表,具体取决于你想要的),一个用于顶点,一个用于面或者有一个类来存储所有容器。