2016-05-12 123 views
2

我一直在Unity3D的场景中工作,在那里我有512 x 424的KinectV2深度信息,我正在将它实时转换为也是512的网格x 424.因此,像素数据(深度)和顶点(网格)的比例为1:1。微软Kinect V2 + Unity 3D深度=翘曲

我的最终目标是在'Microsoft Kinect Studio v2.0'中找到深度为'Monitor 3D View'的场景。

我已经在点云方面做了很多工作。但是,我的Unity场景中有大量的翘曲。我虽然可能是我的数学等

但是,我注意到它的发展套件中提供的Unity Demo kinect的情况相同。

我只是想知道如果我在这里失去了明显的东西?我的每个像素(或本例中的顶点)都以1乘1的方式映射出来。

我不确定是否因为我需要在将DepthFrame渲染到场景之前处理数据?或者如果还有一些额外的步骤,我错过了我的房间的真实代表?因为它看起来像现在添加了一个轻微的“球形”效果。

enter image description here

这两个图像是我的房间的顶部向下射击。绿线代表我的墙壁。

左图为Unity场景中的Kinect,右图为Microsoft Kinect Studio。忽略色差,你可以看到左边(Unity)被扭曲,而右边是线性和完美的。

我知道这很难做出来,尤其是你不知道我坐在房间的布局:/侧视图。你能看到左边的翘曲吗?使用绿线作为参考 - 这些在实际房间内是笔直的,如右图所示。

enter image description here

看看我的影片,以获得更好的主意: https://www.youtube.com/watch?v=Zh2pAVQpkBM&feature=youtu.be

代码C#

很简单是诚实的。我只是从Kinect SDK中直接获取深度数据,并将其放置在Z轴上的点云网格中。

//called on application start 
void Start(){ 

    _Reader = _Sensor.DepthFrameSource.OpenReader(); 
    _Data = new ushort[_lengthInPixels]; 
    _Sensor.Open(); 
} 

//called once per frame 
void Update(){ 

    if(_Reader != null){ 

     var dep_frame = _Reader.AcquireLatestFrame(); 
     dep_frame.CopyFrameDataToArray(_Data); 
     dep_frame.Dispose(); 
     dep_frame = null; 

     UpdateScene(); 
    } 
} 

//update point cloud in scene 
void UpdateScene(){ 

    for(int y = 0; y < height; y++){ 

     for(int x = 0; x < width; x++){ 

      int index = (y * width) + x; 
      float depthAdjust = 0.1; 
      Vector3 new_pos = new Vector3(points[index].x, points[index].y, _Data[index] * depthAdjust; 
      points[index] = new_pos; 
     } 
    } 
} 

Kinect的API可以在这里找到: https://msdn.microsoft.com/en-us/library/windowspreview.kinect.depthframe.aspx

希望任何指教,谢谢!

+0

这将是有益的,看看有什么症状,你的眼看,也许它周围集中的代码。 您确实需要将帧数据处理成数组,并将其正确应用于所显示的位图/图像。 – Sean

+0

@谢恩谢谢,我给OP添加了一张照片。 –

回答

2

感谢Edward Zhang,我发现自己做错了什么。

这是对我来说没有正确投影我的深度点,在我需要使用CoordinateMapper将我的DepthFrame映射到CameraSpace的位置。

目前,我的代码假设正交深度,而不是使用透视深度相机。我只是需要实现这个:

https://msdn.microsoft.com/en-us/library/windowspreview.kinect.coordinatemapper.aspx

//called once per frame 
void Update(){ 

    if(_Reader != null){ 

     var dep_frame = _Reader.AcquireLatestFrame(); 
     dep_frame.CopyFrameDataToArray(_Data); 
     dep_frame.Dispose(); 
     dep_frame = null; 

     CameraSpacePoint[] _CameraSpace = new CameraSpacePoint[_Data.Length]; 
     _Mapper.MapDepthFrameToCameraSpace(_Data, _CameraSpace); 

     UpdateScene(); 
    } 
} 

//update point cloud in scene 
void UpdateScene(){ 

    for(int y = 0; y < height; y++){ 

     for(int x = 0; x < width; x++){ 

      int index = (y * width) + x; 

      Vector3 new_pos = new Vector3(_CameraSpace[index].X, _CameraSpace[index].Y, _CameraSpace[index].Z; 
      points[index] = new_pos; 
     } 
    } 
}