将新的 cv::mat 输入vx_graph

Feeding a new cv::Mat into a vx_graph

本文关键字:vx graph 输入 mat cv      更新时间:2023-10-16

给定上一个问题中的示例代码(为简洁起见,删除了错误检查):

vx_image inputImage = vxCreateImage( graph, width, height, VX_DF_IMAGE_S16 );
vx_image outputImage = vxCreateImage( graph, width, height, VX_DF_IMAGE_S16 );
vx_graph graph = vxCreateGraph( context );
vx_image intermediate1 = vxCreateVirtualImage( graph, width, height, VX_DF_IMAGE_S16 );
vx_image intermediate2 = vxCreateVirtualImage( graph, width, height, VX_DF_IMAGE_S16 );
vx_image intermediate3 = vxCreateVirtualImage( graph, width, height, VX_DF_IMAGE_S16 );
vxSobel3x3Node(graph,inputImage,intermediate1,intermediate2);
vxMagnitudeNode(graph,intermediate1,intermediate2,intermediate3);
vxConvertDepthNode(graph,intermediate3,outputImage,VX_CONVERT_POLICY_WRAP,0);    
vxVerifyGraph( graph );
vxProcessGraph( graph );

以及经典的OpenCV阅读视频循环:

cv::VideoCapture cap;
cap.open("/Testing/test.avi");
for(;;)
{
cv::Mat frame;
cap >> frame;
if( frame.empty() ) break;
// TODO: what goes here?
vxProcessGraph( graph );
}

如何将frame放入inputImage以便正确呼叫vxProcessGraph()?我知道那件事:

vx_image image = nvx_cv::createVXImageFromCVMat(frame);

是获得vx_image的帮手,但我似乎找不到下一步该怎么做的例子。我读过的一些NVidia文档建议:

vxAccessImagePatch(...);
// copy pixel-by-pixel??
vxCommitImagePatch(...);

但是,这似乎有点太像蛮力了,那么是否有更好的方法(也许是vxSetParameter,但文档非常不清楚)来做到这一点?

可以创建一个仅引用存储在cv::Mat中的数据的vx_image。 使用vx_image访问数据的东西最终会实际访问存储在Mat中的数据。 此方法仅使用记录的 OpenCV 和 OpenVX 函数。 从此英特尔文档中:

vx_image get_vx_image_from_Mat(vx_context graph, cv::Mat &mat) {
vx_imagepatch_addressing_t frame_format {};
frame_format.dim_x = mat.cols;
frame_format.dim_y = mat.rows;
return vxCreateImageFromHandle(graph, 
VX_DF_IMAGE_S16, 
&format, 
&((void*)mat.data),
VX_IMPORT_TYPE_HOST);
} 

据推测,cv:Mat至少需要与以这种方式创建的任何vx_image一样长的时间。

我设法制定了解决方案,因为让我对示例感到困惑的是使用了官方 API 中没有的辅助函数。

vx_status vxAddParameterToGraphByIndex(vx_graph g, vx_node n, vx_uint32 index)
{
vx_parameter p = vxGetParameterByIndex(n, index);
vx_status status = vxAddParameterToGraph(g, p);
vxReleaseParameter(&p);
return status;
}

现在,我上面的示例代码需要快速修改:

vx_node sobel = vxSobel3x3Node(graph,inputImage,intermediate1,intermediate2);

然后是魔术线:

vxAddParameterToGraphByIndex(graph, sobel, 0);

此处的0表示sobel节点的第 0 个参数,不包括graph本身。

接下来,我的循环变成:

if( frame.empty() ) break;
vx_image image = nvx_cv::createVXImageFromCVMat(frame);
vxSetGraphParameterByIndex(graph, 0, (vx_reference) image);
vxProcessGraph( graph );
vxReleaseImage(&image);

在这里,0 表示我们添加到图中的第 0 个参数。如果我可以访问上面的vx_parameter p,那么稍微不那么不友好:

vxSetParameterByIndex(p, (vx_reference) image);

这可能会单独工作,但我不知道是否有额外的工作要做才能通知vx_graph更改。