OpenCV-将GpuMat复制到cuda设备数据

时间:2018-07-25 11:35:42

标签: c++ opencv cuda gpu nvidia

我正在尝试将cv::cuda::GpuMat中的数据复制到要在内核中使用的uint8_t*变量中。

GpuMat包含分辨率为752x480且类型为CV_8UC1的图像数据。下面是示例代码:

uint8_t *imgPtr;
cv::Mat left, downloadedLeft;
cv::cuda::GpuMat gpuLeft;

left = imread("leftview.jpg", cv::IMREAD_GRAYSCALE);
gpuLeft.upload(left);

cudaMalloc((void **)&imgPtr, sizeof(uint8_t)*gpuLeft.rows*gpuLeft.cols);
cudaMemcpyAsync(imgPtr, gpuLeft.ptr<uint8_t>(), sizeof(uint8_t)*gpuLeft.rows*gpuLeft.cols, cudaMemcpyDeviceToDevice);

// following code is just for testing and visualization...
cv::cuda::GpuMat gpuImg(left.rows, left.cols, left.type(), imgPtr);
gpuImg.download(downloadedLeft);
imshow ("test", downloadedLeft);
waitKey(0);

但是输出不符合预期。以下分别是输入图像和输出图像。

输入 Input Image

输出 enter image description here

我尝试将cv::Mat源提供给cudaMemcpy。它似乎工作正常。问题似乎出在cv::cuda::GpuMatcudaMemcpy上。 here

中讨论了类似的问题

此外,如果的图像为256或512,则该程序似乎运行正常。

我想念的是什么?要使752x480图片正常工作,应该怎么做?

1 个答案:

答案 0 :(得分:2)

OpenCV GpuMat使用跨步存储(因此映像不会连续存储在内存中)。简而言之,您的示例在大多数情况下都会失败,因为

  1. 您不会将整个映像复制到CUDA内存分配中,并且
  2. 从GPU指针创建第二个GpuMat实例时,您没有正确指定内存布局。

通过阅读文档,您可能想要这样的东西:

uint8_t *imgPtr;
cv::Mat left, downloadedLeft;
cv::cuda::GpuMat gpuLeft;

left = imread("leftview.jpg", cv::IMREAD_GRAYSCALE);
gpuLeft.upload(left);

cudaMalloc((void **)&imgPtr, gpuLeft.rows*gpuLeft.step);
cudaMemcpyAsync(imgPtr, gpuLeft.ptr<uint8_t>(), gpuLeft.rows*gpuLeft.step, cudaMemcpyDeviceToDevice);

// following code is just for testing and visualization...
cv::cuda::GpuMat gpuImg(left.rows, left.cols, left.type(), imgPtr, gpuLeft.step);
gpuImg.download(downloadedLeft);
imshow ("test", downloadedLeft);
waitKey(0);

[由从未使用过OpenCV,未经编译或测试,使用自担风险的人撰写]

只有当GpuMat的行间距偶然等于列数乘以矩阵中存储的类型大小时,代码才能正常工作。这可能是尺寸约为2的幂的图像。