本文采用多台Azure kinect实现了对人体的动态捕捉


前言

  • 如果你是刚接触kinect的小白,建议认真阅读Microsoft给出的官方文档
  • 如果你打算自己开发azure kinect的程序,请参考官方的SDK手册
  • 如果你想在win下配置azure kinect的开发环境,请参考我的上一篇文章
  • 在linux下配置azure kinect会复杂一些,k4a暂时不支持ubuntu 21.04.建议选择20.04LTS或18.04LTS。官方手册中提供了安装指南,在网上也能搜到一些资料,如点击此处
  • 在本文中,录制视频与生成点云是分开的。 这样做的好处有两点。一是在具体操作时发现如果二者并行,采集速度将会是龟速。二是这里的kinect即使替换为任意的RGB-D相机,该程序仍然可以运行。
  • 本文大部分代码与思想基于此文,大感谢!

提示:以下是本篇文章正文内容,下面案例可供参考

一、多台Azure kinect的配准

1、硬件配准

配准硬件相当简单,具体参见此处。如果使用Daisy-chain configuration,你仅需3.5mm的音频线,一端插入sync out,一端连接sync in。如此反复,将多台kinect连接起来。第一台机器会被自动识别为主设备(master device)。你可以使用SDK中自带的viewer进行查看。打开多个viewer窗口来打开多台设备,依次打开从属设备(subordinate device),最后打开主设备。如果你的配置正确,它们会同时开启。

kinect可以用一根usb-c线同时完成供电与传输信号。如果你打算这么做,且线的长度会超过1.5m,推荐使用有源usb-c线

The Azure Kinect can be powered in two ways:

  1. The sensor comes with its own USB-C to USB-A cable with power adapter that can used to power the sensor via wall power outlet.
  2. For capturing on location, you can power the device with a USB-C to USB-C cable verified to supply both the power as well as the data transfer.

2、利用k4arecorder录制

如果你想要体验一下自己写代码的乐趣,强烈推荐这个专栏
但由于笔者照葫芦画瓢写完之后一不小心删除了整个工程文件,并且心灰意冷直接摆烂…
同时sdk自带的工具k4arecorder也可以实现这个功能。具体的介绍也可以在官方文档中找到。

请注意!

  • 使用管理员权限打开终端,不然可能没有权限写入视频文件。
  • 如果找不到k4arecorder.exe的命令,将其替换为k4arecorde试试。
  • 如果你也像笔者一样,需要一个外部触发来实现设备间的同步,可以将所有设备都设置为从属模式,将头一个设备的sync in连接至你的触发源。

二、点云采集

k4arecorder得到的是一个mkv视频文件,其中包括了RGB图,深度图,以及每个时刻的时间戳信息。我们要做的就是读取各个信息,并将其转换到点云文件中。

    for (int i = 0; i < count; i += coord_stride) {
        Eigen::Vector3d q(frame.PointCloudData.data()[3 * i + 0] / 1000.0f, frame.PointCloudData.data()[3 * i + 1] / 1000.0f, frame.PointCloudData.data()[3 * i + 2] / 1000.0f);
        if (q.z() == 0)
        {
            continue;
        }
        // BGR -> RGB
        Eigen::Vector3d color{};
        color.z() = (double)frame.ColorImage.data()[4 * i + 0] / 255.0;
        color.y() = (double)frame.ColorImage.data()[4 * i + 1] / 255.0;
        color.x() = (double)frame.ColorImage.data()[4 * i + 2] / 255.0;

        if (color.x() == 0 && color.y() == 0 && color.z() == 0)
        {
            continue;
        }
        full_cloud[idx]->points_.push_back(q);
        full_cloud[idx]->colors_.push_back(color);
    }

三、点云配准

关于点云配准的文章在CSDN就能查到很多,在这里就不赘述了。一句话概括:点云配准就是一个用各种方法寻找相机间的旋转矩阵的过程。 需要注意如果直接使用ICP配准,很可能陷入局部最优解中。因此我们引入一个编码标志点(fiducial marker)来判断相机的相对位置,再调用ICP来细化相机的位置。

1.基于AprilTag的粗配准[1]

部分代码如下(示例):

            apriltag_detection_info_t info;
            info.det = det;
            info.cx = calibration.Color.cx; // pixels
            info.cy = calibration.Color.cy;
            info.fx = calibration.Color.fx; // mm
            info.fy = calibration.Color.fy;
            info.tagsize = 0.22f; // in meters 按照你的maker大小修改  

其中tagsize取决于你的图片尺寸,计算标准如下:

Apriltag还有其他的参数,如果你想要达到更好的效果,不妨花些时间研究一下。

2.基于彩色ICP的细配准[2]

官网提供的函数示例:

RegistrationResult open3d::pipelines::registration::RegistrationGeneralizedICP	(	const geometry::PointCloud & 	source,
const geometry::PointCloud & 	target,
double 	max_correspondence_distance,
const Eigen::Matrix4d & 	init = Eigen::Matrix4d::Identity(),
const TransformationEstimationForGeneralizedICP & 	estimation = TransformationEstimationForGeneralizedICP(),
const ICPConvergenceCriteria & 	criteria = ICPConvergenceCriteria() 
)	

Parameters:
source: 源点云.
target: 目标点云.
max_distance:最大对应点对距离
init 初始变换估计. 默认值: array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.]]). (本项目中使用apriltag配准后得到的矩阵)
criteria: 收敛标准.

四、点云相加

两个维度相同的点云相加非常简单,在open3d中,你仅仅需要创建两个指向点云的指针(std::shared_ptr<open3d::geometry::PointCloud>),然后*cloud_A+=*cloud_B即可。要注意指针必须指向某个位置,不然会出现segment fault的问题。比如:full_cloud = std::make_shared<open3d::geometry::PointCloud>();这样指针full_cloud就指向了一个空的点云。


五、开源项目推荐

https://github.com/stytim/k4a-calibration
推荐!实用且好用!不过配置环境较为麻烦,其实如果只是想输出点云文件,可以只安装open3d和sdk,但要修改相应的cmake文件和头文件。
https://github.com/catid/xrcap/tree/master/codecs
此项目实现了windows上的实时人体捕捉,一度让笔者心动不已,但实在没法解决K4a dir not found的问题,最终放弃了。
https://vcl3d.github.io/VolumetricCapture/docs/synchronization/
不多说,看起来就非常炫酷。

总结

其实整个过程还是非常简单的,每个环节都能找到很多前人留下的笔记。笔者从一个两眼一抹黑的c++小白到终于拼拼凑凑做出来,实在是走了很多弯路。Anyway,希望大家都能顺顺利利完成。

参考文献

[1]https://april.eecs.umich.edu/software/apriltag
[2]Jaesik Park, Qian-Yi Zhou, Vladlen Koltun; Proceedings of the IEEE International Conference on Computer Vision (ICCV), 2017, pp. 143-152

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐