OpenCV - 将 GpuMat 复制到 cuda 设备数据中
OpenCV - Copy GpuMat into cuda device data
我正在尝试将 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);
但是输出并不像预期的那样。以下分别是输入和输出图像。
输入
输出
我已经尝试将 cv::Mat
来源提供给 cudaMemcpy
。它似乎工作正常。问题似乎出在 cv::cuda::GpuMat
和 cudaMemcpy
上。 here
中讨论了类似的问题
此外,如果图像是 256 或 512,程序似乎运行良好。
我缺少什么?要使 752x480 图像正常工作,应该做什么?
OpenCV GpuMat 使用跨步存储(因此图像不会连续存储在内存中)。简而言之,您的示例在大多数情况下都失败了,因为
- 您没有将整个图像复制到 CUDA 内存分配,并且
- 当您从 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 的整数次幂的图像。
我正在尝试将 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);
但是输出并不像预期的那样。以下分别是输入和输出图像。
输入
输出
我已经尝试将 cv::Mat
来源提供给 cudaMemcpy
。它似乎工作正常。问题似乎出在 cv::cuda::GpuMat
和 cudaMemcpy
上。 here
此外,如果图像是 256 或 512,程序似乎运行良好。
我缺少什么?要使 752x480 图像正常工作,应该做什么?
OpenCV GpuMat 使用跨步存储(因此图像不会连续存储在内存中)。简而言之,您的示例在大多数情况下都失败了,因为
- 您没有将整个图像复制到 CUDA 内存分配,并且
- 当您从 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 的整数次幂的图像。