使用 VTK 进行可视化的 Kinect v2 点云






4.78/5 (14投票s)
本文的目标是使用 Microsoft Kinect v2 传感器提取点云,使用 VTK 工具包对其进行可视化,然后将其保存以用于打印或进一步处理(例如使用 Meshlab)。
简介,快速入门
- 必备组件
- Kinect v2 传感器
- 已安装 Microsoft Kinect V2 SDK 2.0 版本
- Visual Studio 2012 或更高版本
- 启动程序 KinectPointCloud.exe
- 选中“如果深度帧...”复选框
- 点击“捕获”——见下文
- 扫描时请在传感器前保持静止。
当图像质量很高时,捕获将停止——“Depth OK…”超过 45% ——见下文 - 点击“显示点云”以打开点云
- 以带或不带颜色信息的方式查看点云
- 在 MeshLab 等外部工具中打开点云进行进一步编辑(使用 .ply 文件 - 包含颜色信息 - 或 .xyz 文件)
其他使用的源代码
项目中使用了不同的开源代码
- Kinect SDK 中包含的 Microsoft 示例部分
- 通过 C# 包装器 Activiz 使用的 VTK 库
- Vangos Pternas 在其 Codeproject 文章中的部分代码
- 文章:链接
编码
使用 Kinect 获取数据
使用标准的 Microsoft 示例代码从 Kinect 中提取点云,结果相当不理想——例如,高达 30% 的深度帧点丢失了深度信息。要么深度为零,要么深度图像上出现伪影,这是由低深度精度引起的。
提高深度质量
用于提高深度质量的方法是帧插值。
捕获 10 帧,然后将“插值”图像作为深度的平均值。
为了检查抓取图像的质量,我还计算了一个“熵”图像,该图像由最大深度和最小深度之间的差值组成,也就是说,当像素差值为零时(所有测量值显示相同的深度),像素质量最好,熵越高,像素质量越差。例如,如果一个头部在 0.5 到 1 米的范围内被扫描,相机和扫描的目标是静止的,环境光线 OK(日光扫描),则对于大于 95% 的像素,深度精度应在 0 到 5 之间。这意味着扫描点的深度不确定性最多为 5 毫米。
计算深度直方图
X 轴显示深度精度从 0 到 32。所有高于 32 的深度精度都被忽略,因为它们仅占扫描点总数的不到 1%。
Y 轴绘制了点的数量。
以下示例显示,超过 50% 的点的精度为 1 毫米或更低,34% 的点的深度精度为 2 毫米,依此类推。
如果您扫描的图像如下例所示,只有大约 16% 的点具有良好精度,那么最好不要使用该结果。您将看到大量伪影,请参阅下面的熵图像。
代码示例
使用的主窗口是 MainWindow.xaml,负责所有 Kinect 操作的类是 KinectUC
。
开始捕获
private void buttonConnect_Click(object sender, RoutedEventArgs e)
{
KinectConnect();
}
保存点云
private void buttonSave_Click(object sender, RoutedEventArgs e)
{
SaveDepthPoints();
SaveDepthBitmap();
SaveDepthPointsInterpolated();
SaveImageInterpolated();
SaveColorBitmap();
SaveColorInfoForDepth_FileAndImage();
}
显示点云,通过
private void buttonShowPointCloud_Click(object sender, RoutedEventArgs e)
{
this.OpenSavedDepthData();
ShowDepthScreenshot();
FormVTK vtkForm = new FormVTK();
vtkForm.ShowPointCloud
(this.DepthMetaData.FrameData, DepthMetaData.XResDefault, DepthMetaData.YResDefault);
}
有用于 Kinect 数据处理的实用工具,例如
namespace KinectUtils
{
public class DepthMetaData : MetaDataBase
{
...
public WriteableBitmap DepthBitmap
{
get
{
if (depthBitmap == null)
{
this.pixels = ImageUtil.ConvertUshortToByte(this.FrameData);
depthBitmap = ImageUtil.ByteArrayToWriteableBitmap_Gray
(pixels, DepthMetaData.XResDefault, DepthMetaData.YResDefault);
}
return depthBitmap;
}
}
或者 VTK 处理,例如 public class ColorUtils
。
要最好地理解代码,您可以调试主要用例:捕获、保存数据并在 VTK 窗口中显示。
备注
只有当目标和扫描仪不移动时,深度统计信息才有效。
如果发生大的移动,百分比值可能无法加到 100%。原因是,如果传感器或扫描目标移动,从图像中切出的深度点是不同的。
结论
如果使用本文所述的程序(如图像插值,并且仅在深度精度很高时保存点云),则可以使用 Microsoft Kinect v2 相机扫描出质量可接受的点云。
代码使用
只要您在致谢中引用本文,代码和本文的所有信息都可以在任何应用程序中使用。
我乐于接受任何关于代码改进的评论或建议。
关注点
我对将从不同角度扫描的点云拼接在一起,然后将它们组合起来以获得更好的点云感兴趣,例如使用某种 ICP 算法。任何提示,甚至更好的 C# 代码,只要符合这里的架构,都将非常感激。
另请参阅
"使用 OpenGL 的 Kinect 点云" - 本文在 OpenGL 控件中展示了 UI。对于我以后使用 Kinect 的工作,我将使用 OpenGL 控件。但是,我保留了 VTK 的代码,供对此感兴趣的人以及以后使用其他 VTK 示例。
历史
- 代码版本 0.9.0.1,发布日期 2014 年 9 月 30 日
- 0.9.0.2,发布日期 2014 年 12 月 26 日
- 替换了 Kinect 2.0 版本
- 对打开点云的小代码修复