OpenCV  4.10.0
开源计算机视觉
载入中...
搜索中...
无匹配项
高层设计概述

G-API 高层设计概述

G-API 是一个异构框架,提供统一的 API 来以多个支持的后端对图像处理管道进行编程。

关键设计思想是将管道代码本身保持为与平台无关,同时使用额外的参数在图形编译(配置)时指定要使用哪些内核以及要利用哪些设备。此要求已导致以下体系结构

G-API 框架体系结构

此体系结构中有三层

  • API 层 – 这是顶层,它实现了 G-API 公共接口及其构建块和语义。当用户使用 G-API 构建管道时,他会直接与此层交互,而用户操作的实体(如 cv::GMatcv::GComputation)由该层提供。
  • 图形编译器层 – 这是中间层,它将用户计算展开成一个图形,然后对其应用一系列变换(例如优化)。此层建立在 ADE 框架之上。
  • 后端层 – 这是最低层,它列出了许多后端。与上述两层相反,后端与低级平台细节紧密耦合,每个后端代表每个平台。后端对已处理的图形(来自图形编译器)进行操作,并针对特定平台或设备以最佳方式执行此图形。

API 层

API 层是用户在定义和使用管道时与之交互的部分(在 G-API 中称为计算)。API 层定义了一组 G-API 动态对象,这些对象可以用作图形中的输入、输出和中间数据对象

API 层指定了针对这些数据对象定义的操作列表,即内核。有关 G-API 提供哪些默认操作,请参阅 G-API coreimgproc 命名空间的详细信息。

G-API 不仅限于这些操作 - 用户可以使用一个特殊宏 G_TYPED_KERNEL()轻松定义自己的内核。

API 层还负责在创建管道时编组并存储操作参数。除上述 G-API 动态对象外,操作还可能接受任意参数(更多信息请参见此处),因此,API 层会对其值进行捕获并在执行时进行内部存储。

最后,cv::GComputationcv::GCompiled 是 API 层中剩余的重要组件。前者将一系列 G-API 表达式包装到一个对象(图)中,后者是图编译的产物(有关详细信息,请参见本章节)。

图编译器层

在执行每个 G-API 计算之前,均会对其进行编译。编译过程以两种方式触发

当输入数据格式事先未知时,推荐使用第一种方式,例如当它来自任意输入文件。第二种方式推荐用于通常在其中预定义输入数据特征的部署(生产)场景。

在 ADE 框架的顶部构建图编译过程。最初,从 API 层捕获的表达中生成一个二部图。此图包含两种类型的节点:数据操作。图始终以一个或多个数据节点开始和结束,操作节点位于两者之间。每个操作节点都具有输入和输出,两者都是数据节点。

生成初始图后,实际上会通过许多图转换(称为pass)对其进行处理。ADE 框架充当编译器 pass 管理引擎,而 pass 是专门为 G-API 编写的。

有不同的 pass 可以检查图的有效性、优化操作和数据的详细信息、根据关联性或用户指定的区域化将节点组织到集群(“Island”)中,等等。后端还可以将特定于后端的 pass 注入到编译过程中,有关更多信息,请参阅 专门的章节

图编译的结果是一个已编译对象,由类 cv::GCompiled 所表示。始终会创建一个新的 cv::GCompiled 对象,无论是否有明确或隐式的编译请求(请参见上文)。实际的图执行发生在 cv::GCompiled 中,并由参与图编译的后端决定。

另请参见
cv::GComputation::apply()cv::GComputation::compile()cv::GCompiled

后端层

上图列出了两个后端:OpenCVFluidOpenCV 是所谓的“参考后端”,它使用普通的旧 OpenCV 函数来实现 G-API 操作。此后端对于在熟悉的开发系统上制作原型非常有用。Fluid 是一个插件,用于在 CPU 上执行高效缓存操作 - 它实现了一个不同的执行策略并使用其自己的特殊内核来运行。Fluid 后端允许在 CPU 上运行时实现更少的内存占用和更好的内存局部性。

可能有多个后端可用,例如 Halide、OpenCL 等 - G-API 提供了一个统一的内部 API 来开发后端,因此任何爱好者或公司都可以自由地在新的平台或加速器上扩展 G-API。就 OpenCV 基础架构而言,每个新的后端都是一个新的独立 OpenCV 模块,当作为 OpenCV 的一部分构建时,它会扩展 G-API。

图执行

图执行的方式由针对编译选择的后端定义。实际上,每个后端都会在可执行(已编译)对象生成时构建自己的执行脚本,作为图编译过程的最后阶段。例如,在 OpenCV 后端中,此脚本只是一系列按拓扑排序的 OpenCV 函数调用;对于 Fluid 后端,类似 - 一个按拓扑排序的 代理 列表,处理每次迭代的输入行。

图执行通过两种方式触发:

这两种方法都是多态的,采用可变参数,其有效性检查在运行时执行。如果传递的数据对象的数字、形状和格式与预期不一致,将引发运行时异常。G-API 还提供了类型化封装器,可在编译时执行这些检查 – 请参见cv::GComputationT<>

G-API 图形执行已声明为无状态 – 这意味着编译的函数对象 (cv::GCompiled) 就像一个纯 C++ 函数,针对同一组输入参数提供相同的结果。

执行方法采用 \(N+M\) 参数,其中 \(N\) 个输入,\(M\) 是针对已定义 cv::GComputation 的输出。请注意,虽然在定义中使用了 G-API 类型 (cv::GMat 等),但执行方法采用包含实际数据的传统 OpenCV 数据类型(如 cv::Mat) – 请参见 参数封送 中的表格。

另请参见
实现详情内核 API