2.2 Hello World

Time Required: ~10 minutes

想在深入细节之前简要了解下我们的SDK?那我们现在就动手写些代码吧!

看完这个指引,您将熟悉这些方面:

  • 正确的初始化和结束SDK

  • 从摄像头读取数据

  • 检查ASTRA的深度相机提供的深度信息

准备工作

如果您跳过了SDK的安装和例程编译环节,请确保至少将 Astra 下载并解压到一个方便访问的目录下。

现在开始吧!

我们的第一步是配置基本的应用程序,作为后面添加新功能的一个起点。

  1. 使用你喜欢的IDE,新建一个命令行程序工程并且新建一个叫”main.cpp”的源文件。

  2. 拷贝下面的代码到你的main.cpp文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <astra/astra.hpp>

#include <cstdio>
#include <iostream>

int main(int argc, char** argv)
{
   std::cout << "hit enter to exit program" << std::endl;
   std::cin.get();

   return 0;
}
  • Line 1 - astra.hpp 是所有基于本SDK的应用程序都必须包含的文件。这是 Astra 的核心,是所有基于 Astra 的C++程序都需要的。

  • Lines 9-10 - 我们将用 std::cin.get() 来确保程序关闭窗口之前看到打印信息。

初始化和结束 Astra

让 Astra 工作,我们首先要初始化 Astra , 毫无疑问,这通过调用 initialize 来实现。当我们不需要用SDK的时候,我们需要彻底关闭它,关闭的方法就是调用 terminate 函数,该函数会关闭设备和释放其它资源。

下面再添加两行代码:

 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
int main(int argc, char** argv)
{
   astra::initialize();

   // what will go here? you'll find out soon!

   astra::terminate();

   std::cout << "hit enter to exit program" << std::endl;
   std::cin.get();

   return 0;
}

确认效果

继续下一步之前,我们先花点时间来确认到目前为止一切正常。编译并运行程序。程序应该会被启动,并且打印一些诊断信息到命令行,然后开始等待用户按Enter键。按完Enter,程序就会退出。

注解

Astra 默认情况下会输出诊断信息到命令行窗口。如果使用过程中碰到问题,可以查看这些log来寻找答案。

下一步: 和Astra对话。

连接Astra

我们已经知道怎样初始化和关闭 Astra,现在开始做一些实际的操作。为此我们会用到 StreamSet 类,该类封装了各种数据源(比如:2D摄像头的视频和音频)。我们暂且可以把streamSet当成一个类似Astra的物理设备,而 StreamSet 类,则是访问这个设备的功能接口。

现在我们在初始化和关闭之间定义一个 StreamSet 变量。

 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
int main(int argc, char** argv)
{
   astra::initialize();

   astra::StreamSet streamSet;

   astra::terminate();

   std::cout << "hit enter to exit program" << std::endl;
   std::cin.get();

   return 0;
}

这里看起来只是简单添加了一行代码,但这行代码实际做的事情比表面上看到的多很多。只是简单声明和构造一个 StreamSet 对象, Astra 就会自动去查找并连接Astra设备。是不是很酷?

既然设备已经连接,我们就可以做些其它事情了 - 让我们通过Astra的眼睛来观察这个3D世界!

读取摄像头数据

现在是时候利用我们的 StreamSet 对象来获取一些数据了。我们来试试读取Astra提供的其中一个数据流。数据流包含的是摄像头输出的多帧(frames)数据的集合。 Astra 目前支持几种类型的数据流,包括深度,彩色,手点和点云。

为了从Astra的数据流里拿到一帧帧的数据,我们需要 StreamReader 去访问这些数据。在本例程里,我们只读取深度数流。深度流给我们提供的是摄像头每一帧每一个像素看到的场景距离信息。

  1. 首先,我们用 StreamSet 来创建一个 StreamReader

 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
int main(int argc, char** argv)
{
   astra::initialize();

   astra::StreamSet streamSet;
   astra::StreamReader reader = streamSet.create_reader();

   astra::terminate();

   std::cout << "hit enter to exit program" << std::endl;
   std::cin.get();

   return 0;
}
  • Line 11 - 创建一个 StreamReader

  1. 然后我们用 StreamReader 来启动深度流。 启动深度流实际上是告诉 Astra ,我们想从 StreamSet 里读数据。

 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
int main(int argc, char** argv)
{
   astra::initialize();

   astra::StreamSet streamSet;
   astra::StreamReader reader = streamSet.create_reader();

   reader.stream<astra::DepthStream>().start();

   astra::terminate();

   std::cout << "hit enter to exit program" << std::endl;
   std::cin.get();

   return 0;
}
  • Line 13 - 启动深度数据流

  1. 深度数据流启动之后,我们就可以从这个流获取到当前最新的一帧深度数据。首先,用 StreamReader 来获取最新的 Frame ,然后调用 get<T> 来读取该深度帧的数据。

 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main(int argc, char** argv)
{
   astra::initialize();

   astra::StreamSet streamSet;
   astra::StreamReader reader = streamSet.create_reader();

   reader.stream<astra::DepthStream>().start();

   astra::Frame frame = reader.get_latest_frame();
   const auto depthFrame = frame.get<astra::DepthFrame>();

   astra::terminate();

   std::cout << "hit enter to exit program" << std::endl;
   std::cin.get();

   return 0;
}
  • Line 15 - 读取最新的一帧

  • Line 16 - 从最新的一帧中获取深度信息

  1. 剩下的唯一工作就是将之前获取的一些深度信息打印出来了。

 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int main(int argc, char** argv)
{
   astra::initialize();

   astra::StreamSet streamSet;
   astra::StreamReader reader = streamSet.create_reader();

   reader.stream<astra::DepthStream>().start();

   astra::Frame frame = reader.get_latest_frame();
   const auto depthFrame = frame.get<astra::DepthFrame>();

   const int frameIndex = depthFrame.frame_index();
   const short pixelValue = depthFrame.data()[0];

   std::cout << std::endl
             << "Depth frameIndex: " << frameIndex
             << " pixelValue: " << pixelValue
             << std::endl
             << std::endl;

   astra::terminate();

   std::cout << "hit enter to exit program" << std::endl;
   std::cin.get();

   return 0;
}
  • Line 18 - 从深度帧中得到帧索引的一个拷贝

  • Line 19 - 得到该深度帧数据的第一个像素的值拷贝

  • Line 21-25 - 将上面读取的两个值打印到命令行窗口

  • Line 27-28 - 暂停程序以便查看打印结果

现在您可以运行下程序看看是否一切都正常了。跟之前一样,运行的时候一个命令行窗口会弹出并且显示一些打印信息。然后您会看到一行帧数据被打印出来,这个时候按Enter键就可以结束了。

您刚刚从 Astra 拿到了第一帧数据!接下来还有一些 Astra 任务需要完成,就是如何处理多帧数据。

读取 StreamSet 流

你已经知道怎么创建一个 StreamReader 并且从中读取一帧数据,接下来就可以开始读取多帧数据了。为此我们只需要做点小小的改动,我们在 StreamReaderget_latest_frame 函数外面添加一个循环即可。在这个例程里,我们将读取深度流的前面100帧并将每一帧的第一个像素值打印到命令行窗口。

下面的代码跟上面的例子非常相像,差别在于多了一个 do while 循环,一个保存循环次数的变量,以及待处理的最大帧数。

 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int main(int argc, char** argv)
{
   astra::initialize();

   astra::StreamSet streamSet;
   astra::StreamReader reader = streamSet.create_reader();

   reader.stream<astra::DepthStream>().start();

   const int maxFramesToProcess = 100;
   int count = 0;

   do {
      astra::Frame frame = reader.get_latest_frame();
      const auto depthFrame = frame.get<astra::DepthFrame>();

      const int frameIndex = depthFrame.frame_index();
      const short pixelValue = depthFrame.data()[0];

      std::cout << std::endl
                << "Depth frameIndex: " << frameIndex
                << " pixelValue: " << pixelValue
                << std::endl
                << std::endl;

      count++;
   } while (count < maxFramesToProcess);

   std::cout << "Press any key to continue...";
   std::cin.get();

   astra::terminate();

   std::cout << "hit enter to exit program" << std::endl;
   std::cin.get();

   return 0;
}
  • Line 15 - 保存待处理的最大帧数

  • Line 16 - 记录已经处理的帧数

  • Line 18-32 - 帧处理循环

编译并运行。当程序运行的时候,将Astra的摄像头对准自己,稍微动一下,即可看到打印的数字变化。

任务完成! 你刚刚做了一个 Astra 的应用程序! 如果还想学习更多 Astra 相关应用,请继续阅读我们的Simple Depth Viewer指引。