4

CUDA NPPライブラリは、nppiFilter_8u_C1Rコマンドを使用した画像のフィルタリングをサポートしていますが、エラーが発生し続けます。boxFilterNPPサンプルコードを起動して実行するのに問題はありません。

eStatusNPP = nppiFilterBox_8u_C1R(oDeviceSrc.data(), oDeviceSrc.pitch(), 
                                  oDeviceDst.data(), oDeviceDst.pitch(), 
                                  oSizeROI, oMaskSize, oAnchor);

しかし、代わりにnppiFilter_8u_C1Rを使用するように変更すると、eStatusNPPはエラー-24(NPP_TEXTURE_BIND_ERROR)を返します。以下のコードは、元のboxFilterNPPサンプルに加えた変更です。

NppiSize oMaskSize = {5,5};
npp::ImageCPU_32s_C1 hostKernel(5,5);

for(int x = 0 ; x < 5; x++){
    for(int y = 0 ; y < 5; y++){
        hostKernel.pixels(x,y)[0].x = 1;
    }
}

npp::ImageNPP_32s_C1 pKernel(hostKernel);

Npp32s nDivisor = 1;

eStatusNPP = nppiFilter_8u_C1R(oDeviceSrc.data(), oDeviceSrc.pitch(), 
                               oDeviceDst.data(), oDeviceDst.pitch(), 
                               oSizeROI, 
                               pKernel.data(),
                               oMaskSize, oAnchor,
                               nDivisor);

これはCUDA4.2と5.0で試され、同じ結果になりました。

oMaskSize = {1,1}の場合、コードは期待どおりの結果で実行されます

4

3 に答える 3

7

Filter は、2 つの関数間の畳み込みが 2 番目の関数の方向を逆にするという数学的規則に従って、上方向および左方向に拡張するマスクを適用します。

ボックス フィルター マスクは下方向および右方向に伸びています。これはおそらくより直感的です。

いずれにせよ、問題は、DESTINATION[0, 0] を計算するために、変更されたコードの入力画像を実質的に SOURCE[-4, -4) でサンプリングする必要があるという事実によって引き起こされます。入力イメージはテクスチャ サンプラーを介してアクセスされるため、ソース イメージ ポインタ オフセットを (-4, -4) だけバインドすると、表示されているテクスチャ バインド エラーが発生します。

回避策: この問題の最も簡単な回避策は、アンカー ポイントを (4, 4) に設定することです。これにより、効果的にマスクが右下に移動します。K[-4, -4] -> K[0, 0]カーネル配列 (つまり、K[0, 0] -> K[-4, -4]など)の重みを反転する必要があることに注意する必要があります。

于 2012-10-09T00:48:08.410 に答える
3

ImageCPUカーネルを/として保存したときに同じ問題が発生しましたImageNPP

適切な解決策は、カーネルを従来の 1D 配列としてデバイスに格納することです。私はこれを試してみましたが、良い結果が得られました (予測不可能な画像やゴミの画像はありませんでした)。

1D のアイデアについては、この StackOverflow 投稿のFrank Jargstorff に感謝します。

NppiSize oMaskSize = {5,5};
Npp32s hostKernel[5*5];

for(int x = 0 ; x < 5; x++){
    for(int y = 0 ; y < 5; y++){
        hostKernel[x*5+y] = 1;
    }
}

Npp32s* pKernel; //just a regular 1D array on the GPU
cudaMalloc((void**)&pKernel, 5 * 5 * sizeof(Npp32s));
cudaMemcpy(pKernel, hostKernel, 5 * 5 * sizeof(Npp32s), cudaMemcpyHostToDevice);

この元の画像を使用して、1D カーネル配列を使用してコードから取得したぼやけた結果を次に示します。 ここに画像の説明を入力

私が使用した他のパラメータ:

Npp32s nDivisor = 25;
NppiPoint oAnchor = {4, 4};
于 2012-10-16T05:24:34.107 に答える
1

お手伝いありがとう。エラーは解決しましたが、奇妙な動作が見られます。直前に実行したプログラムによって画像が変化し、画像は私が何をしようとしているのかを示していません。

私が模倣しようとしている例は、nppiFilterBox_8u_C1R を使用した nppiFilterBox_8u_C1R で、カーネルを 1 に設定し、nDivisor をカーネルの合計に設定します。

このコードは、boxFilterNPP サンプル コードを変更したものです。

NppiSize oMaskSize = {5,5};
npp::ImageCPU_32s_C1 hostKernel(5,5);
for(int x = 0 ; x < 5; x++){
    for(int y = 0 ; y < 5; y++){
        hostKernel.pixels(x,y)[0].x = 1;
    }
}

npp::ImageNPP_32s_C1 pKernel(hostKernel);
Npp32s nDivisor = 25;
NppiPoint oAnchor = {4, 4};
eStatusNPP = nppiFilter_8u_C1R(oDeviceSrc.data(),oDeviceSrc.pitch(), 
                               oDeviceDst.data(), oDeviceDst.pitch(), 
                               oSizeROI, 
                               pKernel.data(),
                               oMaskSize, oAnchor,
                               nDivisor);

カーネルは 1 つだけなので、重みを反転する必要はありません。

このコードが返す 5 種類の画像を以下に示します。ほとんどの場合、最後のものが返されます。

http://1ordrup.dk/kasper/image/Lena_boxFilter1.jpg
http://1ordrup.dk/kasper/image/Lena_boxFilter2.jpg
http://1ordrup.dk/kasper/image/Lena_boxFilter3.jpg
http://1ordrup.dk/kasper/image/Lena_boxFilter4.jpg 
http://1ordrup.dk/kasper/image/Lena_boxFilter5.jpg

これが発生する理由は、カーネルが正しく初期化されていないか、使用されていないためだと思います。したがって、疑似ランダムコンテンツのデータがカーネルに使用されます。

于 2012-10-09T12:12:38.817 に答える