АЭС 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);
Другие вопросы по тегам