获取图像去噪 CUDA 示例使用 MATLAB CUDAKernel 工作



TL;DR

我正在寻找一种方法来提取现有 CUDA 工具包示例的一部分并将其转换为 MATLAB 中的 CUDAKernel 可执行文件。

故事

为了获得非本地均值 (NLM) 2D 过滤器的短运行时实现,我偶然发现了 CUDA 工具包提供的 imageDenoising 示例,该示例实现了该过滤器的两个变体,称为 NLM 和 NLM2(或"快速 NLM")。

由于以前没有 CUDA 编码的经验,我最初试图遵循 MATLAB 关于该主题的文档,这导致了几个奇怪的错误,包括:ptx 编译、多个入口点和 C 原型中的输入数量错误。在这一点上,我意识到这不会是一个"正常工作"的案例,需要一些修补。

因此,我决定通过简单地删除imageDenoising.cu文件的一部分并将相关.cuh..._nlm_kernel.cuh..._nlm2_kernel.cuh)合并到.cu中来消除多入口点问题,以便在任何给定时间获得单个入口点。令我惊讶的是,这实际上设法编译了,我终于能够创建一个没有错误的CUDAKernel(使用命令 k = parallel.gpu.CUDAKernel('imageDenoising.ptx', 'uint8_T *, int, int, float, float'); )。

然而,这还不够,因为我错误地得出结论,第一个参数是 RGB 矩阵形式的未处理图像(即 X*Y*3 uint8),所以我得到的结果正是输入,但在第一个 4 个元素中带有0

搜索了更多之后,我意识到在这样的转换过程中,还有一些我完全不知道的、关键的方面(比如需要初始化__device__变量),在这个阶段我决定寻求帮助。

问题所在

我目前想知道如何有效地从这里继续。虽然我很想听听这种方法是否通常可以取得成果(以及是否有这个过程的完整示例在某处可用),我应该注意哪些其他陷阱,以及我可以采取哪些替代行动方案(考虑到我在 CUDA 方面的知识非常有限以及我不会雇用其他人为我做这件事), 我记住这是SO,所以我必须有一个特定的编程问题,所以这里是:

如何修改imageDenoising.cu,以便从中构造的 MATLAB CUDAKernel也接受未处理的图像作为输入?

注意:在我的应用程序中,输入矩阵是二维灰度double矩阵。

相关: CudaMalloc 如何工作?

附言

一段工作代码显然是受欢迎的,但我真的宁愿"学习钓鱼"。

我最终对 CUDAKernel 采取了另一种方法,使用 .MEX ,通过执行以下操作:

  1. 设置外部库 OpenCV v2.4.10(不是 v3!)和 mexopencv。
  2. 为OpenCV的fastNlMeans编写一个小包装器函数,使用mexopencv的准则对未实现的函数进行降噪,如下所示(不包括文档):

#include "mexopencv.hpp"
using namespace cv;
void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{
    // Check arguments
    if (nlhs != 1 || nrhs<1 || ((nrhs % 2) != 1) )
        mexErrMsgIdAndTxt("fastNLM:invalidArgs", "Wrong number of arguments");
    // Argument vector  
    vector<MxArray> rhs(prhs, prhs + nrhs);
    // Option processing
      // Defaults:
    double h = 3;
    int templateWindowSize = 7;
    int searchWindowSize = 21;
      // Parsing input name-value pairs:
    for (int i = 1; i<nrhs; i += 2) {
        string key = rhs[i].toString();
        if (key == "h")
            h = rhs[i + 1].toDouble();
        else if (key == "templateWindowSize")
            templateWindowSize = rhs[i + 1].toInt();
        else if (key == "searchWindowSize")
            searchWindowSize = rhs[i + 1].toInt();
        else
            mexErrMsgIdAndTxt("mexopencv:error", "Unrecognized option");
    }
    // Process
    Mat src(rhs[0].toMat()), dst;
    fastNlMeansDenoising(src, dst, h, templateWindowSize, searchWindowSize);
    // Convert cv::Mat back to mxArray*
    plhs[0] = MxArray(dst);
}
  1. 编译它.....和中提琴 - 一个工作 CUDA 加速的 NLM 过滤器。

我的问题本身的答案可以通过比较opencvsourcesmodulesphotosrccudanlm.cu(这是opencv2路径)与imageDenoising_nlm2_kernel.cuh

这个解决方案对我来说效果很好,因为对我来说,运行 NLM 过滤器比使用 CUDAKernel 更重要。

我从中学到的主要教训(我想传递给其他人)是:

在 MATLAB 中运行 CUDA 代码也可以通过 CUDAKernel 以外的方式完成,例如使用.mex包装器,如上所示。

最新更新