OpenCL实现OpenCV时使用的语法/函数

时间:2017-05-30 07:25:54

标签: opencv opencl

我尝试了解在OpenCV中使用OpenCL但我得不到它:

这是来自orb.cpp的示例代码部分,其中ORB_HarrisResponses中创建了名为orb.cl的内核(可行):

ocl::Kernel hr_ker("ORB_HarrisResponses", ocl::features2d::orb_oclsrc,
            format("-D ORB_RESPONSES -D blockSize=%d -D scale_sq_sq=%.12ef -
            D HARRIS_K=%.12ff", blockSize, scale_sq_sq, harris_k));
return hr_ker.args(ocl::KernelArg::ReadOnlyNoSize(imgbuf),
            ocl::KernelArg::PtrReadOnly(layerinfo),
            ocl::KernelArg::PtrReadOnly(keypoints),
            ocl::KernelArg::PtrWriteOnly(responses),
            nkeypoints).run(1, globalSize, 0, true);

但这不是常规的OpenCL语法(像clCreateKernel这样的函数......)。有人知道我可以从哪里获得对OpenCV的OpenCL实现的基本了解,以回答以下问题:

  • “正常”OpenCL和OpenCV OpenCL之间的连接在哪里?
  • 程序是从内核源文件构建的吗?
  • 创建内核的函数在哪里解释?

我无法在网上找到文档或相关问题。 感谢

编辑:感谢您回答它有助于理解一些事情:

 ocl::Kernel hr_ker("ORB_HarrisResponses", ocl::features2d::orb_oclsrc,
            format("-D ORB_RESPONSES -D blockSize=%d -D scale_sq_sq=%.12ef -D HARRIS_K=%.12ff", blockSize, scale_sq_sq, harris_k));

在此部分中,位于字符串ORB_HarrisResponses内的orb.cl内部的内核代码ocl::features2d::orb_oclsrc创建为hr_ker(对吗?)。

  • 但格式(...)的作用是什么?

如果hr_ker.empty()返回false;

return hr_ker.args(ocl::KernelArg::ReadOnlyNoSize(imgbuf),
            ocl::KernelArg::PtrReadOnly(layerinfo),
            ocl::KernelArg::PtrReadOnly(keypoints),
            ocl::KernelArg::PtrWriteOnly(responses), 
            nkeypoints).run(1, globalSize, 0, true);

在内核参数imgbuf的这一部分中,layerinfokeypoints被设置,内核的输出存储在响应中。

  • nkeypoints发生了什么?

  • 为什么此参数前面没有ocl::KernelArg

  • orb.cl中的内核有7个参数,但只设置了5个,为什么?
  • 返回hr_ker.args(...)确切返回了什么?

1 个答案:

答案 0 :(得分:2)

这种语法是一种内部OpenCV“糖”,不重复一些常见的代码块。遗憾的是,没有好的文档,所以学习它的唯一方法是查看源代码和示例。

一些提示:

  • OpenCL API和opencv之间的连接位于modules\core\src\ocl.cpp(请参阅KernelKernel::ImplProgramProgramSourceKernelArg类。
  • 存储在* .cl文件中的内核源代码(例如ORB内核位于modules \ features2d \ src \ opencl \ orb.cl文件中)。关于内核的模块构建代码正在复制到自动生成的cpp文件(例如opencl_kernels_features2d.cpp),代码可以由ocl::features2d::orb_oclsrc访问。
  • 要在opencv中使用opencl实现,您需要传递给函数cv::UMat而不是常规cv::Mat(请参阅CV_OCL_RUN_宏和cv::OutputArray::isUMat()方法)。

基本上opencv中的所有opencl实现都会执行以下操作:

  • 定义内核参数,如全局大小,块大小等。
  • 使用包含源代码和已定义参数的字符串创建cv :: ocl :: Kernel。 (如果没有创建内核或者没有指定输入参数的opencl实现,则处理传递给常规cpu代码。)
  • 通过cv::ocl::KernelArgs传递内核参数。有几种类型的参数可以优化处理:只读,只写,常量等。
  • 运行内核。

因此,对于使用opencl实现的最终用户来说,透明。如果出现问题,处理将切换到cpu实现。

让我们讨论以下代码片段:

  return hr_ker.args(ocl::KernelArg::ReadOnlyNoSize(imgbuf),
            ocl::KernelArg::PtrReadOnly(layerinfo),
            ocl::KernelArg::PtrReadOnly(keypoints),
            ocl::KernelArg::PtrWriteOnly(responses),
            nkeypoints).run(1, globalSize, 0, true);

和ocl函数声明:

ORB_HarrisResponses(__global const uchar* imgbuf, int imgstep, int imgoffset0,
                    __global const int* layerinfo, __global const int* keypoints,
                    __global float* responses, int nkeypoints )
  • nkeypoints是整数,因此无需将其包装到ocl::KernelArg。它将直接传递给内核。
  • ocl::KernelArg::ReadOnlyNoSize实际上扩展为三个参数:imgbuf,imgstep,imgoffset0。
  • 其他内核参数不会扩展,因此它代表单个参数。
  • hr_ker.args会返回对cv::ocl::Kernel的引用,因此您可以使用以下构造:kernel.args(...).run(...)

一些有用的链接:

希望它会有所帮助。