VisionWorks Toolkit Reference

September 29, 2015 | 1.0 Release

 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
1. Implementation

This section demonstrates functionality implementation of User Custom Node.

You must provide the actual implementation for the node.

1.1 Define comparison functions to use with standard qsort algorithm:

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 Define a kernel function with the following prototype:

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

In the kernel function we get all input and output parameters:

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;
vxReadScalarValue(use_strength_scalar, &use_strength);
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)
{
"[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 Copy the data from the source array to the destination array as qsort operates in-place:

vx_size src_stride = 0;
void *src_ptr = NULL;
vxAccessArrayRange(src, 0, num_items, &src_stride, &src_ptr, VX_READ_ONLY);
vxTruncateArray(dst, 0);
vxAddArrayItems(dst, num_items, src_ptr, src_stride);
vxCommitArrayRange(src, 0, num_items, src_ptr);

1.4 Perform a sort operation on the destination array:

vx_size dst_stride = 0;
void *dst_ptr = NULL;
vxAccessArrayRange(dst, 0, num_items, &dst_stride, &dst_ptr, VX_READ_AND_WRITE);
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);
vxCommitArrayRange(dst, 0, num_items, dst_ptr);

The Full Code for the Node Implementation

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);
}
vx_status keypointArraySort_kernel(vx_node node, const vx_reference *parameters, vx_uint32 num)
{
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;
vxReadScalarValue(use_strength_scalar, &use_strength);
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)
{
"[keypoint_array_sort] Destination Array is too small (required capacity = " VX_FMT_SIZE ", actual = " VX_FMT_SIZE ")",
num_items, dst_capacity);
return VX_FAILURE;
}
// Copy src array to dst
vx_size src_stride = 0;
void *src_ptr = NULL;
vxAccessArrayRange(src, 0, num_items, &src_stride, &src_ptr, VX_READ_ONLY);
vxTruncateArray(dst, 0);
vxAddArrayItems(dst, num_items, src_ptr, src_stride);
vxCommitArrayRange(src, 0, num_items, src_ptr);
// sort dst array in place
vx_size dst_stride = 0;
void *dst_ptr = NULL;
vxAccessArrayRange(dst, 0, num_items, &dst_stride, &dst_ptr, VX_READ_AND_WRITE);
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);
vxCommitArrayRange(dst, 0, num_items, dst_ptr);
return VX_SUCCESS;
}