【问题标题】:Get access to OpenCV GpuMat channels访问 OpenCV GpuMat 频道
【发布时间】:2019-11-06 01:02:01
【问题描述】:

我正在研究光线追踪器。我想通过使用 GPU 将每个像素的数据保存在 OpenCV Mat 中来优化我的代码。

现在,我将像素值保存在缓冲区 fb 中,这是一个由三个值 (RGB) 组成的向量:

__global__ void render(vec3 *fb, int max_x, int max_y, Camera **cam, Triangle *data, size_t n, )
{
    int i = threadIdx.x + blockIdx.x * blockDim.x;
    int j = threadIdx.y + blockIdx.y * blockDim.y;
    if ((i >= max_x) || (j >= max_y)) return;
    int pixel_index = j * max_x + i;
    float u = float(i) / float(max_x);
    float v = float(j) / float(max_y);
    Ray r = (*cam)->get_ray(u,v);
    fb[pixel_index] = color(r, data,n);
}

然后我将数据保存在 CPU 上的 Mat 中:

for (int j = ny - 1; j >= 0; j--) 
{
    for (int i = 0; i < nx; i++) 
    {
        size_t pixel_index = j * nx + i;
        int ir = int(255.99*fb[pixel_index].r());
        int ig = int(255.99*fb[pixel_index].g());
        int ib = int(255.99*fb[pixel_index].b());
        output.at<Vec3b>(j, i)[0] = (uchar)ib;
        output.at<Vec3b>(j, i)[1] = (uchar)ig;
        output.at<Vec3b>(j, i)[2] = (uchar)ir;
        //std::cout << ir << " " << ig << " " << ib << "\n";
    }
}

但是当我有一个大像素阵列时,这是一个非常缓慢的过程。这就是为什么我想使用 OpenCV GpuMat 并将数据直接保存在 GPU 上的原因。

问题是我真的找不到如何在 GPU Mat 的每个通道中保存数据的示例。这是一种简单的方法吗,类似于在 CPU 上保存数据?

【问题讨论】:

  • GpuMat 只是一个设备缓冲区的包装器,使在 opencv 中的工作更容易。您可以让其构造函数使用其默认分配器创建一个,或者您可以将设备指针作为*data 参数与维度/步幅/类型信息一起传递给已分配的缓冲区(如果使用流或多个GPU,强烈推荐)。您还可以使用 ogl:: 命名空间或通过标准 CUDA 方法与 OpenGL 进行互操作。例如,您可以通过将其缓冲区指针传递给内核来直接填充它。也许您应该详细说明您希望如何使用它?

标签: c++ opencv cuda


【解决方案1】:

请参阅documentation。上面写着

没有返回对其数据的引用的函数(因为 GPU 上的引用对 CPU 无效)

访问数据的唯一方法是通过data函数。但是指针只能在(cuda)内核代码中取消引用。而且没有 据我所知at 功能。所以你必须计算数据的偏移量。

【讨论】:

    【解决方案2】:

    感谢您的回答。他们让我思考如何以另一种方式做到这一点。我不确定这是否是处理它的最佳解决方案,但它可以工作,并且我认为这是在 GPU 上填充矩阵的一种安静简单的方法。

    1. 在 GPU 上为矩阵预留内存
    Mat output(ny, nx, CV_8UC3);
        const size_t numBytes = output.step * output.rows;
        unsigned char *d_output;
        cudaMalloc<unsigned char>(&d_output, numBytes);
    
    1. GPU 上的填充矩阵
    _global__ void render(vec3 *fb, int max_x, int max_y, Camera **cam, Triangle *data, size_t n, unsigned char* input, int step)
    {
    
        int i = threadIdx.x + blockIdx.x * blockDim.x;
        int j = threadIdx.y + blockIdx.y * blockDim.y;
        if ((i >= max_x) || (j >= max_y)) return;
        int pixel_index = j * max_x + i;
        int index = j * step + 3 * i;
        float u = float(i) / float(max_x);
        float v = float(j) / float(max_y);
        Ray r = (*cam)->get_ray(u,v);
        fb[pixel_index] = color(r, data,n);
        int ir = int(255.99*fb[pixel_index].r());
        int ig = int(255.99*fb[pixel_index].g());
        int ib = int(255.99*fb[pixel_index].b());
    
    
        input[index] = ib;
        input[index+1] = ig;
        input[index+2] = ir;
    
    
    }
    

    如果您对此代码提出任何建议和意见,我将不胜感激。

    【讨论】:

    • 我不喜欢第一步。我认为使用 GPUMat 并获得它的 datastep 信息会更容易。请记住,您必须使用cudaFree 释放设备内存。第二步对我来说看起来不错,只要您能以“是”回答以下问题:fbcamdata 指向设备内存? fb 是一个线性数组(没有填充)?
    猜你喜欢
    • 2020-01-13
    • 2018-04-12
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 2018-03-05
    • 2013-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多