Microsoft Kinect V2 + Unity 3D 深度 = 翘曲
Microsoft Kinect V2 + Unity 3D Depth = Warping
我一直在 Unity3D 中处理一个场景,其中我有 512 x 424 的 KinectV2 深度信息,我正在将其实时转换为同样为 512 x 424 的网格。所以有一个1:1 像素数据(深度)与顶点(网格)的比率。
我的最终目标是使在 'Microsoft Kinect Studio v2.0' 中找到的 'Monitor 3D View' 场景具有深度。
我在点云方面已经基本可以使用它了。但是,我的 Unity 场景中存在大量变形。我虽然这可能取决于我的数学等
但是我注意到在他们的开发工具包中提供的 Unity Demo kinect 也是一样的。
我只是想知道我是否遗漏了一些明显的东西?我的每个像素(或本例中的顶点)都以 1 乘 1 的方式映射出来。
我不确定是不是因为我需要在将 DepthFrame 渲染到场景之前处理来自 DepthFrame 的数据?或者如果我错过了一些额外的步骤来获得我房间的真实表现?因为看起来现在添加了轻微的 'spherical' 效果。
这两张图片是我房间的俯视图。绿线代表我的墙。
左图为Unity场景中的Kinect,右图为Microsoft Kinect Studio中。忽略色差,你可以看到左边(Unity)是扭曲的,而右边是线性和完美的。
我知道这很难分辨,尤其是你不知道我所在房间的布局:/侧视图。你能看到左边的翘曲吗?使用绿线作为参考 - 这些在实际房间中是笔直的,如右图所示。
观看我的视频以获得更好的想法:
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
非常感谢任何建议,谢谢!
感谢 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;
}
}
}
我一直在 Unity3D 中处理一个场景,其中我有 512 x 424 的 KinectV2 深度信息,我正在将其实时转换为同样为 512 x 424 的网格。所以有一个1:1 像素数据(深度)与顶点(网格)的比率。
我的最终目标是使在 'Microsoft Kinect Studio v2.0' 中找到的 'Monitor 3D View' 场景具有深度。
我在点云方面已经基本可以使用它了。但是,我的 Unity 场景中存在大量变形。我虽然这可能取决于我的数学等
但是我注意到在他们的开发工具包中提供的 Unity Demo kinect 也是一样的。
我只是想知道我是否遗漏了一些明显的东西?我的每个像素(或本例中的顶点)都以 1 乘 1 的方式映射出来。
我不确定是不是因为我需要在将 DepthFrame 渲染到场景之前处理来自 DepthFrame 的数据?或者如果我错过了一些额外的步骤来获得我房间的真实表现?因为看起来现在添加了轻微的 'spherical' 效果。
这两张图片是我房间的俯视图。绿线代表我的墙。
左图为Unity场景中的Kinect,右图为Microsoft Kinect Studio中。忽略色差,你可以看到左边(Unity)是扭曲的,而右边是线性和完美的。
我知道这很难分辨,尤其是你不知道我所在房间的布局:/侧视图。你能看到左边的翘曲吗?使用绿线作为参考 - 这些在实际房间中是笔直的,如右图所示。
观看我的视频以获得更好的想法: 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
非常感谢任何建议,谢谢!
感谢 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;
}
}
}