Данный пример кода как в этом предыдущем вопросе (проверка ошибок удалена для краткости):
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
Возможно, но документация очень непонятна) для этого?
Можно создать vx_image
который ссылается только на данные, хранящиеся в cv::Mat
, Что-то используя vx_image
для доступа к данным будет в конечном итоге доступ к данным, хранящимся в Mat
, Этот подход использует только документированные OpenCV и OpenVX функции. Из этого Документация Intel:
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
здесь означает 0-й параметр sobel
узел, исключая 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
изменения.