Syntax/Functions 用于 OpenCV 的 OpenCL 实现

Syntax/Functions used in the OpenCL-Implemantation of OpenCV

我试图了解 OpenCV 中 OpenCL 的使用,但我不明白:

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

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 实现的基本了解以回答以下问题:

我在网上找不到文档或相关问题。 谢谢

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

 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.cl build 中的内核代码 ORB_HarrisResponses 被创建为 hr_ker(对吗?)。

if hr_ker.empty() return 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);

在内核参数的这一部分中设置了 imgbuflayerinfokeypoints 并且内核的输出存储在响应中。

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

给你的一些提示:

  • 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 returns 引用 cv::ocl::Kernel 因此您可以使用以下结构:kernel.args(...).run(...).

一些有用的链接:

希望对您有所帮助。