4 获取流数据

流的类型

Astra SDK 支持各种类型的流类型。底层的流类型由摄像头生成并且通过SDK传输给应用程序。上层的流类型则是通过SDK的插件从底层的流类型高效地运算得到的。一般来说,我们应该首选可用的上层流。

底层

流类型 描述
ColorStream 来自摄像头的RGB像素数据。每个 ColorFrame 中的数组 data 包含 0-255之间的数值,这些数值代表每个像素每个色彩通道的值
DepthStream 来自摄像头的深度数据。每个 DepthFrame 中的数组 data 包含了摄像头 视场范围内每个像素的值,单位是毫米

上层

流类型 描述
PointStream 从深度数据计算的世界坐标点云(XYZ)。 每个 PointFramedata 数组元素是 astra:Vector3f 类型的, 通过访问其 x, yz 值可以方便地访问每个像素
HandStream 从深度数据计算出来的手点。 对每一个 HandFrame, 在任一给定时间点从 HandFrame::handpoint_count 函数可以得到点的数量, 通过 HandFrame::handpoints 函数还可以得到 astra::HandFrame::HandPointList

获取数据

Astra SDK 提供了两个方法来获取流数据。根据您应用的特定需求和其复杂度, 两个方法中总有一个更为适用的方法。

轮询

通过轮询的方法来获取流数据是一种比较直接的方法。在Hello World教程里我们采用的就是这种方法。使用这种方法很简单,你只需要调用 StreamReaderget_latest_frame 函数,然后用模板函数 get<T> 来返回得到特定类型的帧。在这里 “T” 必须是一个有效的帧类型。函数 get_latest_frame 是阻塞式的,在下一帧数据到来之前,程序将被挂起。如果你想限制阻塞时间,可以给 get_latest_frame 函数传递一个 timeout 变量。

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();
  • 通过轮询的方法读取一帧深度帧

侦听

通过侦听的方法来获取数据需要事先做一些设置,这种方法允许开发者将帧的处理委托给一个或多个不同的类。 Astra SDK 提供了一个叫 FrameListener 的抽象类,该类只实现了一个叫 FrameListener::on_frame_ready 的函数。当数据帧到来的时候, 该类会立即调用 FrameListener::on_frame_ready 并且将帧的引用作为参数传入。

class DepthFrameListener : public astra::FrameListener
{
   virtual void on_frame_ready(astra::StreamReader& reader,
                               astra::Frame& frame) override
   {
      const astra::DepthFrame depthFrame = frame.get<astra::DepthFrame>();

      if (depthFrame.is_valid())
      {
         // do all the things
      }
   }
};
  • frame_listener 继承的listener类示例

定义了 listener 类,您还必须在您的应用程序里将这个listener实例化并且用 StreamReader::add_listener 函数将其添加到 StreamReader 之后才能使用它。

astra::initialize();

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

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

DepthFrameListener listener;
reader.add_listener(listener);

while(true)
{
   astra_update();
}
  • listener使用示例。实际使用的时候,对 astra_update 的循环调用必须持续到程序要关闭的时候,或者别的特定事件发生的时候。

添加了listener之后,我们需要通过循环调用 astra_update 函数来触发事件。通过这种调用,SDK可以检查是否有新的一帧数据到来,如果是,比如在本例子里,将调用 DepthFrameListener::on_frame_ready 函数,并且传入当前帧的引用。

如果想要了解更实际的listener使用,可以查看 Simple Depth Reader Tutorial.