【问题标题】:C++: Get BGR image (cv::Mat) from GPU memory (cudaMemcpy2D)C++:从 GPU 内存 (cudaMemcpy2D) 获取 BGR 图像 (cv::Mat)
【发布时间】:2020-05-13 17:58:00
【问题描述】:

我正在研究图像处理并使用 OpenCV 为 RGB 和单色相机开发相机包装器。现在我必须使用与 CUDA 配合使用的现有算法来处理这两个相机图像流。为此,我必须将 Mat 图像复制到我的设备(该算法不使用 gpumat)。我使用cv::Mat::ptr 来访问图像的数据。当我使用 cudaMemcpy2D 将图像返回到主机时,我收到了 RGB 图像的暗图像(仅零)。即使我使用cudaMemcpy2D 将其加载到设备并在下一步使用cudaMemcpy2D 将其带回它也不会工作(我的意思是我不会在两者之间进行任何图像处理)。不过,它适用于单声道图像:

width = 1920; (image dimensions are the same for mono and BGR)
height = 1080;
Mat mat_mono(height, width, CV_8UC1);
Mat mat_mono_disp(height, width, CV_8UC1);
size_t pitch_mono;
uint8_t* image_mono_gpu,
size_t matrixLenMono = width;

cudaMallocPitch(&image_mono_gpu, &pitch_mono, width, height);

mat_mono = MonoCamera.CaptureMat(1); // wrapper for the mono camera that grabs the image

// copy to device
cudaMemcpy2D(image_mono_gpu, pitch_mono, mat_mono.ptr(), width, matrixLenMono, height, cudaMemcpyHostToDevice);

// copy back to host
cudaMemcpy2D(mat_mono_disp.ptr(), matrixLenMono, image_mono_gpu, pitch_mono, matrixLenMono, height, cudaMemcpyDeviceToHost);

namedWindow("Display window", WINDOW_AUTOSIZE);
imshow("Display window", mat_mono_disp);

这是 RGB(或者更确切地说是 BGR)图像的代码,在从设备中检索图像后,我只收到一张深色图像:

Mat mat_BGR(height, width, CV_8UC3);
Mat mat_BGR_disp(height, width, CV_8UC3);
size_t pitch_BGR;
uint8_t* image_BGR_gpu,
size_t matrixLenBGR = width * 3;

cudaMallocPitch(&image_BGR_gpu, &pitch_BGR, matrixLenBGR, height);

mat_BGR = RGBCamera.CaptureMat(1); // wrapper for the RGB camera that grabs the image

// copy to device
cudaMemcpy2D(image_BGR_gpu, pitch_BGR, mat_BGR.ptr(), width, matrixLenBGR, height, cudaMemcpyHostToDevice);

// copy back to host
cudaMemcpy2D(mat_BGR_disp.ptr(), matrixLenBGR, image_BGR_gpu, pitch_BGR, matrixLenBGR, height, cudaMemcpyDeviceToHost);

namedWindow("Display window", WINDOW_AUTOSIZE);
imshow("Display window", mat_BGR_disp);

这是否意味着将cv::Mat:ptr 与单色图像一起使用是一种特殊情况?我不知道在使用 BGR 图像时还需要考虑什么。

【问题讨论】:

  • 在将Mat 复制到设备时,在cudaMemcpy2D 的第四个参数中使用mat_BGR.step 而不是width
  • @sgarizvi:如果您愿意添加这个问题,那将是一个完美的简短答案
  • 非常感谢,这就是解决方案! @sgarizvi

标签: c++ opencv cuda


【解决方案1】:

正如previous answer 中所指出的,当执行OpenCV Mat 的2D 内存复制到使用cudaMallocPitch(或任何strided 2D memory)分配的设备内存时,我们必须使用OpenCV Mat 的step 成员来指定每一行的对齐方式。

在提供的代码中,正确的方法是在cudaMemcpy2D 的第四个参数中使用mat_BGR.step 而不是width

cudaMemcpy2D(image_BGR_gpu, pitch_BGR, mat_BGR.ptr(), mat_BGR.step, matrixLenBGR, height, cudaMemcpyHostToDevice);
                                                              ^^^^

【讨论】:

    猜你喜欢
    • 2021-05-23
    • 1970-01-01
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多