VisionWorks之用户自定义结点


VisionWorks使用图模型进行pipeline处理,主要包含Nodes(结点)和edge(边),我们可以定义自己的结点。下面介绍一个如何创建一个结点。
内核对象API(Object:Kernel)允许您创建自定义的vision函数,这些函数可以集成在VisionWorks框架中,然后可以作为节点在graph中调用。节点是具有一组参数数据对象的内核实例。

本教程通过实现对keypoints数组进行排序的一个自定义内核,并将其实例化为graph中的用户自定义节点。这个内核的目的是在两种可能的模式下对一个键点输入数组进行排序:

  • 按关键点坐标(从左上角到右下角)

  • 按关键点强度(从最高强度到最低强度)

为了注册自定义用户内核,应用程序必须提供一组回调函数:

  • Processing function:在图形执行时处理节点参数的函数。

  • Parameter validation function:必须为输入和输出提供验证函数,以便验证参数属性和参数之间的一致性。此回调函数在图形(重新)验证时调用。

  • 初始化/取消初始化函数:这些回调是可选的,被视为节点的构造函数/析构函数。本教程中不使用这些函数。

有了回调函数,应用程序可以通过提供附加信息(如内核名称、唯一标识符和参数属性)来注册自定义内核。

为了像创建标准节点一样的创建用户自定义节点,一个好的实践是创建一个自定义节点工厂函数。

1. Processing Callback Function

本节说明内核处理回调函数的实现。

每次执行从该内核实例化的节点时,都会自动调用与内核关联的回调函数,将对节点对象的引用以及对与节点参数相对应的数据对象的引用集作为参数。

1.1 比较函数

这些函数是处理回调所需的实用函数,用于实现qsort算法。

int compare_keypoints_coord_only(const void* ptr1, const void* ptr2)
{
    const vx_keypoint_t *kp1 = (const vx_keypoint_t *)ptr1;
    const vx_keypoint_t *kp2 = (const vx_keypoint_t *)ptr2;
    if (kp1->y != kp2->y)
        return (kp1->y < kp2->y);
    return (kp1->x < kp2->x);
}
int compare_keypoints_with_strength(const void* ptr1, const void* ptr2)
{
    const vx_keypoint_t *kp1 = (const vx_keypoint_t *)ptr1;
    const vx_keypoint_t *kp2 = (const vx_keypoint_t *)ptr2;
    if (kp1->strength != kp2->strength)
        return (kp1->strength > kp2->strength);
    // if strengths are equal, sort keypoints by coordinates
    return compare_keypoints_coord_only(ptr1, ptr2);
}

1.2 处理回调原型

所有内核处理回调都具有相同的原型:

vx_status keypointArraySort_kernel(vx_node node, const vx_reference *parameters, vx_uint32 num)

通常,在内核处理函数中要做的第一件事是检索对节点参数(输入和输出数据对象)的引用由于回调的原型是泛型的,因此这些参数以vx_reference类型的泛型引用给出。它们必须显式转换为正确的数据对象引用类型从这一点上,可以查询和操作节点参数对象。

    if (num != 3)
        return VX_FAILURE;
    vx_array src = (vx_array)parameters[0];
    vx_array dst = (vx_array)parameters[1];
    vx_scalar use_strength_scalar = (vx_scalar)parameters[2];
    vx_bool use_strength = vx_false_e;
    vxCopyScalar(use_strength_scalar, &use_strength, VX_READ_ONLY, VX_MEMORY_TYPE_HOST);
    vx_size num_items = 0;
    vxQueryArray(src, VX_ARRAY_ATTRIBUTE_NUMITEMS, &num_items, sizeof(num_items));
    vx_size dst_capacity = 0;
    vxQueryArray(dst, VX_ARRAY_ATTRIBUTE_CAPACITY, &dst_capacity, sizeof(dst_capacity));
    if (dst_capacity < num_items)
    {
        vxAddLogEntry((vx_reference)node, VX_FAILURE,
            "[keypoint_array_sort] Destination Array is too small (required capacity = " VX_FMT_SIZE ", actual = " VX_FMT_SIZE ")",
            num_items, dst_capacity);
        return VX_FAILURE;
    }

1.3 将数据从源数组复制到目标数组

qsort算法在适当的位置运行,然后,由于输入数组不能被修改,它必须首先复制到目标数组。

   vx_size src_stride;
    void *src_ptr;
    vx_map_id src_map_id;
    vxMapArrayRange(src, 0, num_items, &src_map_id, &src_stride, &src_ptr, VX_READ_ONLY, VX_MEMORY_TYPE_HOST, 0);
    vxTruncateArray(dst, 0);
    vxAddArrayItems(dst, num_items, src_ptr, src_stride);
    vxUnmapArrayRange(src, src_map_id);

1.4条对输出数组排序

由于前面看到的比较实用程序函数,可以对输出数组对象进行排序。

   vx_size dst_stride;
    void *dst_ptr;
    vx_map_id dst_map_id;
    vxMapArrayRange(dst, 0, num_items, &dst_map_id, &dst_stride, &dst_ptr, VX_READ_AND_WRITE, VX_MEMORY_TYPE_HOST, 0);
    if (use_strength == vx_true_e)
        qsort(dst_ptr, num_items, dst_stride, &compare_keypoints_with_strength);
    else
        qsort(dst_ptr, num_items, dst_stride, &compare_keypoints_coord_only);
    vxUnmapArrayRange(dst, dst_map_id);

2. Validation Callback Function

This section illustrates the implementation of the validation callback function.

3. Kernel Registration

This section illustrates the user custom kernel registration.

4. User Custom Node Factory

This section illustrates the implementation of the user custom node factory.

5. Usage

This section illustrates the usage of user custom nodes.

6. CUDA Nodes

This section describes the implementation of user custom nodes based on CUDA.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值