Time Required: ~10 minutes
到目前为止您已经掌握了 Astra SDK 的一些基本概念,下一步我们利用 Astra SDK 的另外一个功能来从Astra读取深度数据。
看完这个指引,你将熟悉这些方面:
FrameListener
类的目的
- 如何定义
FrameListener
- 用
FrameListener
来处理深度流
准备工作
- 下载并解压最新的 Astra SDK,之前做过则忽略。
- 使用你喜欢的IDE,新建一个命令行程序工程并且新建一个叫“main.cpp”的源文件。
- 拷贝下面的代码到你的main.cpp文件:
#include <astra/astra.hpp>
#include <cstdio>
int main(int argc, char** argv)
{
return 0;
}
A Depth Stream
Definition: Depth.hpp:147
Stream Reader class
Definition: StreamReader.hpp:39
Stream Set Class
Definition: StreamSet.hpp:36
astra_status_t terminate()
Terminate the library, destroying all its streams.
Definition: astra_core.hpp:45
astra_status_t initialize()
Initializes the library.
Definition: astra_core.hpp:35
- Line 7 - 初始化 Astra SDK
- Line 9 - 构造一个
StreamSet
- Line 10 - 创建一个
StreamReader
- Line 12 - 启动一个深度流
- Line 16 - 关闭 Astra SDK
侦听深度流
在Hello World 教程,我们通过循环调用 StreamReader
的 get_latest_frame
函数处理了多个数据帧构成的流。这种调用方法非常适合Hello World这种简单应用。但是,如果我们想要访问多个数据流,想要处理多个 StreamSet
,或者在每个 StreamSet
里有多个 StreamReader
,怎么办? 在这几种情况下,采用循环的方式会让问题变得非常复杂。
为了让这种问题变得简单, Astra SDK 提供了一种事件机制。该机制定义并创建了 FrameListener
。 FrameListener
有个成员函数 on_frame_ready
会在特定类型的一帧新数据到来的时候自动被调用。所以,相比于使用 StreamReader
的 get_latest_frame
函数,侦听器(listener)自动并且及时地得到了最新的数据。
下面是 FrameListener
的使用示例...
- 我们需要定义一个listener 类来实现接口
FrameListener
。这个类使我们能够访问从Astra摄像头输出的实际数据。 我们将通过 on_frame_ready
函数来得到这些帧。首先将下面的代码拷贝到你的 #include
和 main
函数之间:
{
public:
DepthFrameListener(int maxFramesToProcess)
: maxFramesToProcess_(maxFramesToProcess)
{}
bool is_finished() const { return isFinished_; }
private:
{
{
print_depth_frame(depthFrame);
++framesProcessed_;
}
isFinished_ = framesProcessed_ >= maxFramesToProcess_;
}
{
const short middleValue = get_middle_value(depthFrame);
std::printf("Depth frameIndex: %d value: %d \n", frameIndex, middleValue);
}
{
const int width = depthFrame.
width();
const int height = depthFrame.
height();
const size_t middleIndex = ((width * (height / 2.f)) + (width / 2.f));
const short* frameData = depthFrame.
data();
const short middleValue = frameData[middleIndex];
return middleValue;
}
bool isFinished_{false};
int framesProcessed_{0};
int maxFramesToProcess_{0};
};
int main(int argc, char** argv)
{
A Depth Frame
Definition: Depth.hpp:287
Frame class
Definition: Frame.hpp:32
Frame Listener class
Definition: FrameListener.hpp:31
const int height() const
get height
Definition: Image.hpp:444
const astra_frame_index_t frame_index() const
get frame index
Definition: Image.hpp:465
const int width() const
get width
Definition: Image.hpp:437
const bool is_valid() const
get is vaild
Definition: Image.hpp:430
const TDataType * data() const
get data pointer
Definition: Image.hpp:486
- Line 10 - 构造函数,其变量表示程序退出之前总共要处理的帧数。
- Line 14 -
is_finished
用于判断是否我们已经处理了足够的帧数,该变量后面会用到。
- Line 20 - 读取深度数据帧
- Line 22 - 检查是否获取到有效的帧。
- Line 24 - 打印深度帧信息到命令行窗口
- Line 44 - 计算深度帧中心像素的索引
- Line 47 - 获取中心像素的值
- 注意
- 本例中唯一必须的函数是
on_frame_ready
函数。其它函数都是为了配合而存在的。
- 定义好了
DepthFrameListener
,接下来我们在 main
函数中构造一个listener并将其添加到上一步创建的 StreamReader
里。
int main(int argc, char** argv)
{
int maxFramesToProcess = 100;
DepthFrameListener listener(maxFramesToProcess);
return 0;
}
void add_listener(FrameListener &listener)
add listener
Definition: StreamReader.hpp:87
void remove_listener(FrameListener &listener)
remove listener
Definition: StreamReader.hpp:101
- Line 73 - 构造一个会循环100次的
DepthFrameListener
- Line 75 - 将listener添加到reader
- Line 79 - 将listener从reader移除
更新我们的listener
我们已经将 Astra SDK 和 StreamSet
运行起来了,而且我们还通过 StreamSet
的 StreamReader
来侦听了数据帧。但我们不知道数据帧什么时候会从Astra里面输出,所以我们需要在一个循环里反复调用 astra_update
去持续更新这些listener。
int main(int argc, char** argv)
{
const int maxFramesToProcess = 100;
DepthFrameListener listener(maxFramesToProcess);
do {
astra_update();
} while (!listener.is_finished());
return 0;
}
- Line 77-79 - The Astra SDK 更新循环。
我们现在编译并运行工程。当你观察完命令行窗口打印的一些深度帧信息后,你会发现你已经掌握了 Astra SDK 的事件机制使用方法。现在,让我们更进一步,发挥你的想象,用 Astra SDK 去实现你的各种创意吧!