专栏算法工具链HOBOTCV框架之应用程序实例

HOBOTCV框架之应用程序实例

TROS.Assist2024-01-04
93
0

应用程序示例

HobotCV 提供的通过名字去设置对象属性的能力,使得应用程序和底层设备之间不需要共享一个 CV 操作的定义代码,从而做到前后端完全代码解耦。

下面将介绍一个典型的 HobotCV 应用程序的几个步骤。从代码可以看到,应用程序只需要设置 CVOP 的需要的参数即可,而不用关心具体哪个硬件去执行。

  • 创建 ICVOP,并设置相应的参数,指令如下:

  • 创建 IContext, 建立执行 ICVOP 的系统环境,指令如下:

  • 创建 ISession, 建立执行环境,指令如下:

  • 创建输入输出图像,并分配内存,指令如下:

  • 获取输入图像,指令如下:

  • 调用同步或者异步执行接口

  • 调用结果处理函数,指令如下:

  • 释放资源,指令如下:

1. 插件开发

每个 HobotCV 插件仅需 export如下6个C函数,其中,前面四个函数是必须存在,并且框架仅会调用一次。如果这四个函数有一个不存在,则框架认为不是HobotCV的插件,将拒绝加载,后两个函数是可选实现:

插件可以创建三种类型的组件对象,分别由三个类工厂来完成:

  • IDeviceFactory: 用于创建设备对象。

  • ICVOPFactory: 用于创建CVOP对象,定义OP完成的操作。

  • IDevSchedFactory: 用于创建设备调度算法对象。

这些工厂实例又由根工厂IPluginFactory来创建。

Description

所有的工厂类都提供这样三种方法:

  • GetList()

    • IPluginFactory通过GetList()方法,告知框架可以创建的类工厂类型。

    • IDeviceFactory/ICVOPFactory/IDevSchedFactory 通过GetList()方法返回可以创建的对象的类名称的列表。

  • CreateComponent()
    创建组件对象。
  • DestroyComponent()
    释放组件对象。

相应的接口类定义如下所示:

2. 设备开发

如前方章节所述,开发一个HobotCV设备最主要的工作就是实现设备接入层的接口类。

2.1IDevBackend

该类提供了设备抽象,通过Start()/Stop()来实现设备级别的初始化和释放。

还需要实现GetCVOPList()来向框架报告支持的CVOP列表。
IDevBackend实现了RegisterDevOP()以及GetCVOPList()来简化设备的实现代码。

设备层最重要的工作就是创建DevOP和DevSession, 用于执行OP。IDevBackend包含了一个默认的CreateDevOP实现,以降低设备实现的代码量。

2.2 IDevSession

IDevSession重要的接口包括PrepareRun()和PostRun(),用于初始化和释放Session级别,为了执行OP需要在设备上执行的资源分配和释放动作。

此外,还提供设备内存分配和释放函数。之所以放在IDevSession而非IDevBackend,是因为不同的OP可能有不同的内存分配策略。这些接口的实现需要多线程安全。

IDevSession创建和执行任务的接口实现也需要多线程安全。

2.3 IDevOP

设备真正实现OP计算的类,并通过IDevBackend::RegisterDevOP()注册到设备中。

IDevOP的接口分为OP参数相关和计算相关两类接口。

参数相关接口包括获取OP参数和校验参数的有效性。

计算相关相关的接口如下:

2.4 IDevTask

用于记录task(一次OP运行)的状态。设备可以将运行一次OP时,设备的临时状态记录在该类的派生类中。
该类重要的成员包括app_sync、dev_sync,分别表示应用程序请求的执行方式(同步/异步)和实际设备的选择执行方式。

2.5 ICVBuffer

在实现设备分配图像内存时,从该类派生出设备自己定义的Buffer类,用于保存设备内存相关的数据。

在IDevSession::AllocateInputMem()/AllocateOutputMem() 中,自定义的Buffer对象设置完成以后,需要调用CVImage::SetDevBuffer()填到相应的Image中。

在IDevSession::FreeMem() 中,可以通过CVImage::GetDevBuffer()拿到Buffer对象的指针并释放。

3. 自定义CVOP

在HobotCV中, OP代表特定的计算逻辑和相应的参数。 通过CVOP提供的接口,定义一个新的CVOP非常简单,需要关注的是如何规划好新OP的参数。

OP参数定义一般选择与硬件无关,而依据OP的计算逻辑需要的参数。与特定硬件相关的参数,一般不应放在OP的定义设计中,可以通过:

  • Context进行传递,

  • 运行接口的options参数

  • 或者通过设备参数设置接口(IDevice::SetParamXXX)进行传递。

自定义OP从CVOP派生,并调用以下接口来添加参数:

此外,还需要实现:

  • CheckParamValid()来检查设置的参数是否有效。

  • GetDescription()来返回对该OP的描述,可设置的参数以及取值范围。

  • CheckShapeValid() 来检查输入输出图像的尺寸,与设置的参数是否匹配。

算法工具链
征程5杂谈
评论0
0/1000