我正在尝试通过编写 cuda 内核代码来均衡直方图。主要问题是,在图像的某一行之前操作似乎是正确的,之后输出是错误的,但我不明白为什么,下面是代码和图像。
预期输出:
获得的输出:
我不明白为什么,我已经检查过直方图包含准确的值,实际上预期的输出是通过在CPU上执行操作获得的,我没有问题,只要我通过“获得的输出”到GPU的图像就是结果。现在我展示代码
__global__ void equalizeHistCUDA(unsigned char* input, unsigned char* output, int *cumulative_hist, int cols, int rows) {
int nGrayLevels = 256, area = cols*rows;
int i = blockIdx.y * blockDim.y + threadIdx.y;
int j = blockIdx.x * blockDim.x + threadIdx.x;
if (i < rows && j < cols){
int pixelValue = input[i * cols + j];
output[i * cols + j] = static_cast<uchar>((static_cast<double>(nGrayLevels) / area) * cumulative_hist[pixelValue]);
}
}
nThreadPerBlocco = dim3(4, 3);
numBlocks.y = gpu_resizedImage.rows / nThreadPerBlocco.y + ((gpu_resizedImage.rows % nThreadPerBlocco.y) == 0 ? 0 : 1);
numBlocks.x = gpu_resizedImage.cols / nThreadPerBlocco.x + ((gpu_resizedImage.cols % nThreadPerBlocco.x) == 0 ? 0 : 1);
cv::cuda::GpuMat gpu_equalizedImage(600,600,CV_8UC1);
equalizeHistCUDA<<<numBlocks,nThreadPerBlocco>>>(gpu_resizedImage.data,gpu_equalizedImage.data,cumHist_device,gpu_resizedImage.cols,gpu_resizedImage.rows);
cudaDeviceSynchronize();
cudaError_t cudaErr = cudaGetLastError();
if (cudaErr != cudaSuccess)
fprintf(stderr, "Errore CUDA: %s\n", cudaGetErrorString(cudaErr));
cv::Mat img;
gpu_equalizedImage.download(img);
cv::imwrite("test.jpg",img);
我已经检查过我使用的所有结构都已正确填充。有什么建议吗?
感谢帖子下评论的用户,我解决了问题。 显然 opencv x cuda 不会在 GPU 上连续分配图像,因此我的 cuda 内核代码计算线性化 mateniera 中的地址,但这没有用,因为 cuda 不像你在 cpu 上存储的那样存储。 解决方案是使用 XXXX 函数。完成此操作后,就可以像我一样访问了。 显然,opencv x cuda 不会在 GPU 上连续分配图像,因此我的 cuda 内核代码计算线性化 mateniera 中的地址,但这没有用,因为 cuda 不像它存储在 cpu 上那样存储。 解决方案是使用
cv::cuda::GpuMat gpu_equalizedImageSM = cv::cuda::createContinuous(gpu_resizedImage.rows,gpu_resizedImage.cols,CV_8UC1);
功能。完成此操作后,就可以像我一样访问了。