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

本文关键字:3D 网格 创建 Kinects 深度 | 更新日期: 2023-09-27 17:57:17

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

https://i.stack.imgur.com/aPtJt.jpg

我想为深度流创建一个 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''Last 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 来使其工作,或者是否有更有效的方法可以做到这一点?

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

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

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

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

WPF 包含一个透视相机类,该类应该可以胜任作业

System.Windows.Media.Media3D.PerspectiveCamera

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

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

Microsoft.Kinect.CoordinateMapper.MapSkeletonPointToDepthPoint()

见 http://msdn.microsoft.com/en-us/library/jj883696.aspx

如何从 kinect 赛道上获取网格?

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

  1. 顶点:v x y z
    (x,y,z 应替换为表示坐标的相应数字,而 v 表示您正在列出顶点)

  2. 三角形面:f i j k
    (x,y,z 应替换为表示坐标的相应数字,而 f 表示您正在列出面)

AMD 你有你的 .obj

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