АЭС CUDA GaussFilter портит изображения
Я пытаюсь использовать CUDA с Qt для размытия изображения. Я использую библиотеку NPP, nppiFilterGauss_8u_C1R прекрасно работает
void cuda_npp_gauss_filter_qt(uchar* pSourceData, uchar* pResultData, const int &ImageLineStep, const int &ImageWidth, const int &ImageHeight)
{
NppiSize oSizeROI;
oSizeROI.width = ImageWidth;
oSizeROI.height = ImageHeight;
Npp32s SourceStep = ImageLineStep;
Npp32s DestinationStep = ImageLineStep;
size_t AllocationSizeInBytes = ImageLineStep * ImageHeight;
Npp8u *pSource, *pDestination;
cudaMalloc<Npp8u>(&pSource,AllocationSizeInBytes);
cudaMalloc<Npp8u>(&pDestination,AllocationSizeInBytes);
cudaMemcpy(pSource, pSourceData, AllocationSizeInBytes, cudaMemcpyHostToDevice);
nppiFilterGauss_8u_C1R(pSource, SourceStep, pDestination, DestinationStep, oSizeROI, NPP_MASK_SIZE_15_X_15);
cudaMemcpy(pResultData, pDestination, AllocationSizeInBytes, cudaMemcpyDeviceToHost);
}
но nppiFilterGaussAdvanced_8u_C1R искажает изображения
void cuda_npp_gauss_filter_qt_advanced(uchar* pSourceData, uchar* pResultData, const int &ImageLineStep, const int &ImageWidth, const int &ImageHeight, const int &Radius)
{
NppiSize oSizeROI;
oSizeROI.width = ImageWidth;
oSizeROI.height = ImageHeight;
Npp32s SourceStep = ImageLineStep;
Npp32s DestinationStep = ImageLineStep;
size_t AllocationSizeInBytes = ImageLineStep * ImageHeight;
Npp8u *pSource, *pDestination;
cudaMalloc<Npp8u>(&pSource,AllocationSizeInBytes);
cudaMalloc<Npp8u>(&pDestination,AllocationSizeInBytes);
//-------------------------------------------------------
int nFilterTaps = 2*((int)((float)ceil(Radius) + 0.5F)) + 1;
//-------------------------------------------------------
//-------------------------------------------------------
//-------------- Gaussian kernel ------------------------
double sigma = 0.3*((nFilterTaps-1)*0.5 - 1) + 0.8;
cv::Mat GaussianKernel = cv::getGaussianKernel(nFilterTaps, sigma, CV_32F);
//-------------------------------------------------------
//-------------------------------------------------------
cudaMemcpy(pSource, pSourceData, AllocationSizeInBytes, cudaMemcpyHostToDevice);
nppiFilterGaussAdvanced_8u_C1R (pSource, SourceStep, pDestination, DestinationStep, oSizeROI, nFilterTaps, (Npp32f*)GaussianKernel.data);
cudaMemcpy(pResultData, pDestination, AllocationSizeInBytes, cudaMemcpyDeviceToHost);
}
Я использую OpenCV для создания гауссовского ядра.
Xubuntu 16.04.1, Qt 5.7-1, CUDA 8.044, OpenCV 2.4.9. Благодарю.
2 ответа
Для функций АЭС требуется выделение памяти на устройстве. OpenCV Mat (GaussianKernel
в этом случае) размещается на хосте по умолчанию.
Поэтому следующая строка кода становится недействительной.
nppiFilterGaussAdvanced_8u_C1R (pSource, SourceStep, pDestination, DestinationStep, oSizeROI, nFilterTaps, (Npp32f*)GaussianKernel.data);
Параметр (Npp32f*)GaussianKernel.data
следует скопировать на устройство перед переходом к функции АЭС. Это может быть достигнуто так:
float* GaussianKernel_d;
size_t GaussianKernelBytes = GaussianKernel.step() * GaussianKernel.rows;
cudaMalloc<float>(&GaussianKernel_d, GaussianKernelBytes);
cudaMemcpy(GaussianKernel_d, GaussianKernel.data, GaussianKernelBytes, cudaMemcpyHostToDevice);
nppiFilterGaussAdvanced_8u_C1R (pSource, SourceStep, pDestination, DestinationStep, oSizeROI, nFilterTaps, GaussianKernel_d);
Спасибо за помощь. Это работает сейчас.
//-------------------------------------------------------
//-------------- Gaussian kernel ------------------------
double sigma = 0.3*((nFilterTaps-1)*0.5 - 1) + 0.8;
cv::Mat GaussianKernel = cv::getGaussianKernel(nFilterTaps, sigma, CV_32F);
Npp32f* pGaussianKernel;
size_t GaussianKernelBytes = GaussianKernel.step * GaussianKernel.rows;
cudaMalloc<Npp32f>(&pGaussianKernel, GaussianKernelBytes);
cudaMemcpy(pGaussianKernel, GaussianKernel.data, GaussianKernelBytes, cudaMemcpyHostToDevice);
//-------------------------------------------------------
//-------------------------------------------------------
cudaMemcpy(pSource, pSourceData, AllocationSizeInBytes, cudaMemcpyHostToDevice);
nppiFilterGaussAdvanced_8u_C1R (pSource, SourceStep, pDestination, DestinationStep, oSizeROI, nFilterTaps, pGaussianKernel);
cudaMemcpy(pResultData, pDestination, AllocationSizeInBytes, cudaMemcpyDeviceToHost);