VisionWorks Toolkit Reference

December 18, 2015 | 1.2 Release

 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
1. Processing Callback Function

This section illustrates the implementation of the kernel processing callback function.

The processing callback associated to a kernel is automatically called each time a node instantiated from this kernel is executed. The processing callback takes as parameter the reference to the node object as well as the set of references to data objects that correspond to the node parameters.

1.1. Comparison functions for the qsort algorithm

These functions are utility functions needed by the processing callback to implement the 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. Processing callback prototype

All kernel processing callbacks have the same prototype:

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

Usually, the first thing to do in the kernel processing function is to retrieve the reference to node parameters (input and outputs data objects). Since the prototype of the callback is generic, these parameters are given as generic references with type vx_reference. They must be cast explicitly to the right data object reference type. From this point, node parameter objects can be queried and manipulated.

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

The qsort algorithm operates in-place and then, since the input array must not be modified, it must initially be copied to the destination array.

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. Sort the output array

The output array object can be sorted due to the comparison utility functions seen previously.

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);

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;
}