VisionWorks - kernel of custom node

Hi all,

I am implementing user customized node. For the node’s kernel function, I need to pass in some un-openVX variables (like cv::Descriptor). I am trying to cast the address of cv::someObject to vx_uint64 and wrap which into a vx_array, then pass the reference of this vx_array to the kernel. Then inside the kernel, cast this vx_uint64 back to a pointer pointing to cv::someObject. But this is messy and I am encountering some pointer issue which causes segmentation fault.

May I ask is VX kernel designed for accepting vx_reference only? Or there are some “correct” way to pass in cv reference?

Thank you so much!
Byin

========
PS.
I do can construct(create) that cv::someObject inside the kernel, but the create is expensive and the graph(<-node<-kernel) is supposed to run in a loop.

BTW, why VisionWorks or OpenVX do not provide DescriptorExtractor node or vx_object, which is widely used in opencv applications?

Hi,

Thanks for your question.

For user-defined structure, you can wrap it with vx_array.
I wrote a sample to show how to wrap custom data structure into vx_array, hope this will help.

(I use cv::Mat as example since I’m not familiar cv::Descriptor, but it should be easy to substitute)

#include <VX/vx.h>
#include <NVX/nvx_opencv_interop.hpp>
#include <opencv2/opencv.hpp>
#include <stdio.h>//printf()
#include <stdlib.h>//exit() 

typedef struct mystruct {
    cv::Mat src;
} mystruct;

enum {
    USER_LIBRARY = 0x1,
    USER_KERNEL_SIMPLE = VX_KERNEL_BASE(VX_ID_DEFAULT, USER_LIBRARY) + 0x0,
};

vx_status simple_kernel(vx_node node, const vx_reference *parameters, vx_uint32 num)
{
    vx_array input = (vx_array)parameters[0];

    vx_status status;
    vx_size nItem;
    status |= vxQueryArray(input, VX_ARRAY_ATTRIBUTE_NUMITEMS, &nItem, sizeof(nItem));

    if (nItem > 0)
    {
        vx_map_id map_id;
        vx_size stride;
        void* ptr;
        status |= vxMapArrayRange(input, 0, nItem, &map_id, &stride, &ptr, VX_READ_ONLY, VX_MEMORY_TYPE_HOST, 0);

        for (vx_size i = 0; i < nItem; i++)
        {
            mystruct m = vxArrayItem(mystruct, ptr, i, stride);
            printf("Item %d: size=%d\n", i, m.src.total());
        }

        status |= vxUnmapArrayRange(input, map_id);
    }

    return VX_SUCCESS;
}

vx_status simple_validate(vx_node node, const vx_reference parameters[], vx_uint32 num, vx_meta_format metas[])
{
    return VX_SUCCESS;
}

vx_status registerSimpleKernel(vx_context context)
{
    vx_status status = VX_SUCCESS;
    vx_kernel kernel = vxAddUserKernel(context, "simple_kernel", USER_KERNEL_SIMPLE, simple_kernel, 1, simple_validate, NULL, NULL);
    status = vxGetStatus((vx_reference)kernel);
    if (status != VX_SUCCESS)
    {
        vxAddLogEntry((vx_reference)context, status, "Failed to create Simple Kernel");
        return status;
    }
    status |= vxAddParameterToKernel(kernel, 0, VX_INPUT , VX_TYPE_ARRAY , VX_PARAMETER_STATE_REQUIRED);
    if (status != VX_SUCCESS)
    {
        vxReleaseKernel(&kernel);
        vxAddLogEntry((vx_reference)context, status, "Failed to initialize Simple Kernel parameters");
        return VX_FAILURE;
    }
    status = vxFinalizeKernel(kernel);
    if (status != VX_SUCCESS)
    {
        vxReleaseKernel(&kernel);
        vxAddLogEntry((vx_reference)context, status, "Failed to finalize Simple Kernel");
        return VX_FAILURE;
    }
    return status;
}

vx_node SimpleNode(vx_graph graph, vx_array input)
{
    vx_node node = NULL;
    vx_context context = vxGetContext((vx_reference)graph);
    vx_kernel kernel = vxGetKernelByEnum(context, USER_KERNEL_SIMPLE);
    if (vxGetStatus((vx_reference)kernel) == VX_SUCCESS)
    {
        node = vxCreateGenericNode(graph, kernel);
        vxReleaseKernel(&kernel);
        if (vxGetStatus((vx_reference)node) == VX_SUCCESS)
        {
            vxSetParameterByIndex(node, 0, (vx_reference)input);
        }
    }
    return node;
}

int main() {
    vx_context context = vxCreateContext();

    vx_enum mytype = vxRegisterUserStruct(context, sizeof(mystruct));
    vx_array array = vxCreateArray(context, mytype, 100);
    registerSimpleKernel(context);

    vx_graph graph = vxCreateGraph(context);
    vx_node simple_node = SimpleNode(graph, array);
    vxVerifyGraph(graph);

    mystruct features;
    features.src = cv::Mat(9,1,CV_32FC1);
    vxAddArrayItems(array, 1, &features, sizeof(mystruct));

    vxProcessGraph(graph);

    return 0;
}
nvcc topic_1001961.cpp -lvisionworks -lopencv_core -o test && ./test