2016-12-03 21 views
-1

QtでCUDAを使用して画像をぼかしてみます。 私はNPPライブラリを使用し、nppiFilterGauss_8u_C1RはCUDA NPP GaussFilterが画像を破損します

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は、画像Iは、ガウスカーネルを作成するためのOpenCVを使用

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); 
    } 

が破損します。

Xubuntu 16.04.1、Qt 5.7-1、CUDA 8.044、OpenCV 2.4.9。おかげさまで

+2

1. "このコードはなぜ動作しませんか?"という質問が表示されます。 [mcve]が含まれることが期待されます。あなたが示したのは完全なコードではなく、MCVEではありません。 2.常に適切なエラーチェックを行う必要があります。すべてのnppコールのnppエラーをチェックし、すべてのcudaコールのCUDAエラーをチェックし、他の人に助けを求める前に 'cuda-memcheck' *でコードを実行してください。あなたがエラー出力を理解していなくても、あなたを助けようとしている他の人にとっては役に立ちます。私はガウスのカーネルデータがホストポインタではなくデバイスポインタであると考えています。あなたはそのデータをデバイスメモリに転送することになっています –

+2

また、イメージをイメージの中心にオフセットする必要があります。ガウシアンカーネルが適用されている場合は、各側に要素の半径が必要となるため、ソースイメージサイズと宛先イメージサイズに等しいROIサイズを持つことはできません。 'cuda-memcheck'であなたのコードを実行すると、問題を指摘するでしょう。 'cuda-memcheck'がエラーを報告しなくなるまで、私が指摘した行に沿って調整する必要があります。少なくともNPPに境界外のデータにアクセスするように求めているわけではありません。 –

答えて

3

NPP機能では、デバイスにメモリを割り当てる必要があります。 OpenCV Mat(この場合はGaussianKernel)は、デフォルトでホストに割り当てられます。

したがって、次のコード行は無効になります。

nppiFilterGaussAdvanced_8u_C1R (pSource, SourceStep, pDestination, DestinationStep, oSizeROI, nFilterTaps, (Npp32f*)GaussianKernel.data); 

パラメータ(Npp32f*)GaussianKernel.dataは、NPP機能に渡す前にデバイスにコピーする必要があります。

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); 
0

ご協力ありがとうございます。それは今働く。

//------------------------------------------------------- 
//-------------- 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); 
+0

それを知ってうれしい:)。あなたは答えを受け入れることを検討するかもしれません。 – sgarizvi

関連する問題