前言
最近有多台Azure Kinect DK摄像头同步保存RGB和Depth图片的需求,一开始我是直接调用编译好的recorder工具进行视频录制,然后从mkv视频中分别提取出RGB和Depth图片,发现提取出来的图片其实不太同步,看来光连接外部同步线还不够准确。于是就在网上找了一些博客看,还是没有太大的收获,最后发现在官方给的源码example中的green_screen找到了同步相关的代码,故进行了浅显地注释和学习。
一、如何同步
处理Azure Kinect DK摄像机还比较复杂:
(1)不能完全保证同一个摄像机中的深度相机和彩色相机拍摄图像的时间戳完全相等,或多个摄像机之间拍摄图像的时间戳完全相等
(2)如果两个最新的图像是同步的,那么还是不能保证在每个摄像机上只调用一次get_capture()后它们以后拍摄的图像仍然是同步的。
这是因为在摄像机内部,设备保留一个包含一些捕获图像的队列,并根据get_capture()的请求提供这些图像。然而,图像也可以随时丢弃,在给定时刻,一个设备可能比另一个设备准备更多的图像。此外,同步过程很复杂。当同步时,摄像机不能保证在所有时间戳上完全匹配(尽管它们应该非常接近)。所有延迟都与主摄像机的彩色摄像机有关。为了处理这些复杂性,在官方给出的同步代码中采用了一种相当简单的算法。从读取两个捕获开始,然后如果相机图像不是在大致相同的时间拍摄的,则从具有较旧捕获的设备读取一个新图像,直到时间戳大致匹配。每次循环运行时,只会更新旧的捕获,捕获存储在向量中,其中向量的第一个元素是主捕获,后续元素是从属捕获。
二、多摄像头同步
1.官方代码如下:
bool have_synced_images = false; //设置一个bool变量判断是否同步
std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
while (!have_synced_images)
{
// 如果这花费的时间太长,则超时
int64_t duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start).count();
if (duration_ms > WAIT_FOR_SYNCHRONIZED_CAPTURE_TIMEOUT)
{
cerr << "ERROR: Timedout waiting for synchronized captures\n";
exit(1);
}
k4a::image master_color_image = captures[0].get_color_image(); //捕获到主设备的color_image
std::chrono::microseconds master_color_image_time = master_color_image.get_device_timestamp(); //记录这个color_image的时间戳
//开始处理从属设备
for (size_t i = 0; i < subordinate_devices.size(); ++i)
{
k4a::image sub_image; // 要获取的捕获项
if (compare_sub_depth_instead_of_color) //是否同步的是depth_image
{
sub_image = captures[i + 1].get_depth_image(); // 偏移1是因为captures[0]是master占用
}
else
{
sub_image = captures[i + 1].get_color_image(