2012-10-15 28 views
5

Nvidia Performance Primitives (NPP) के साथ घूमते समय कचरा पैदा करता है उपयोगकर्ता द्वारा प्रदत्त कर्नेल के साथ उपयोगकर्ता द्वारा प्रदत्त छवि को हल करने के लिए nppiFilter फ़ंक्शन प्रदान करता है। 1 डी रूपांतरण कर्नेल के लिए, nppiFilter ठीक से काम करता है। हालांकि, nppiFilter 2 डी कर्नेल के लिए एक कचरा छवि का उत्पादन कर रहा है।एनवीडिया एनपीपी nppiFilter 2 डी कर्नेल

मैं इनपुट के रूप में ठेठ लीना छवि का इस्तेमाल किया: enter image description here


यहाँ एक -1 डी घुमाव गिरी है, जो अच्छा उत्पादन का उत्पादन के साथ मेरे प्रयोग है। गिरी [-1 0 1] साथ ऊपर कोड की

#include <npp.h> // provided in CUDA SDK 
#include <ImagesCPU.h> // these image libraries are also in CUDA SDK 
#include <ImagesNPP.h> 
#include <ImageIO.h> 

void test_nppiFilter() 
{ 
    npp::ImageCPU_8u_C1 oHostSrc; 
    npp::loadImage("Lena.pgm", oHostSrc); 
    npp::ImageNPP_8u_C1 oDeviceSrc(oHostSrc); // malloc and memcpy to GPU 
    NppiSize kernelSize = {3, 1}; // dimensions of convolution kernel (filter) 
    NppiSize oSizeROI = {oHostSrc.width() - kernelSize.width + 1, oHostSrc.height() - kernelSize.height + 1}; 
    npp::ImageNPP_8u_C1 oDeviceDst(oSizeROI.width, oSizeROI.height); // allocate device image of appropriately reduced size 
    npp::ImageCPU_8u_C1 oHostDst(oDeviceDst.size()); 
    NppiPoint oAnchor = {2, 1}; // found that oAnchor = {2,1} or {3,1} works for kernel [-1 0 1] 
    NppStatus eStatusNPP; 

    Npp32s hostKernel[3] = {-1, 0, 1}; // convolving with this should do edge detection 
    Npp32s* deviceKernel; 
    size_t deviceKernelPitch; 
    cudaMallocPitch((void**)&deviceKernel, &deviceKernelPitch, kernelSize.width*sizeof(Npp32s), kernelSize.height*sizeof(Npp32s)); 
    cudaMemcpy2D(deviceKernel, deviceKernelPitch, hostKernel, 
        sizeof(Npp32s)*kernelSize.width, // sPitch 
        sizeof(Npp32s)*kernelSize.width, // width 
        kernelSize.height, // height 
        cudaMemcpyHostToDevice); 
    Npp32s divisor = 1; // no scaling 

    eStatusNPP = nppiFilter_8u_C1R(oDeviceSrc.data(), oDeviceSrc.pitch(), 
              oDeviceDst.data(), oDeviceDst.pitch(), 
              oSizeROI, deviceKernel, kernelSize, oAnchor, divisor); 

    cout << "NppiFilter error status " << eStatusNPP << endl; // prints 0 (no errors) 
    oDeviceDst.copyTo(oHostDst.data(), oHostDst.pitch()); // memcpy to host 
    saveImage("Lena_filter_1d.pgm", oHostDst); 
} 

आउटपुट - यह एक उचित ढाल छवि की तरह दिखता है: enter image description here


हालांकि, nppiFilter एक कचरा छवि आउटपुट अगर मैं एक 2 डी घुमाव गिरी का उपयोग । जिन कारणों से मैं ऊपर कोड से बदल 2D गिरी [-1 0 1; -1 0 1; -1 0 1] साथ चलाने के लिए कर रहे हैं:

NppiSize kernelSize = {3, 3}; 
Npp32s hostKernel[9] = {-1, 0, 1, -1, 0, 1, -1, 0, 1}; 
NppiPoint oAnchor = {2, 2}; // note: using anchor {1,1} or {0,0} causes error -24 (NPP_TEXTURE_BIND_ERROR) 
saveImage("Lena_filter_2d.pgm", oHostDst); 

नीचे 2 डी गिरी [-1 0 1; -1 0 1; -1 0 1] का उपयोग कर उत्पादन छवि है।

मैं क्या गलत कर रहा हूं? , कुछ लंगर के लिए

    2 डी गिरी के साथ
  • :

enter image description here

This StackOverflow post एक ऐसी ही समस्या का वर्णन है, के रूप में उपयोगकर्ता Steenstrup की छवि में दिखाया गया है: http://1ordrup.dk/kasper/image/Lena_boxFilter5.jpg


कुछ अंतिम नोट्स मान (उदाहरण के लिए NppiPoint oAnchor = {0, 0} या {1, 1}), मुझे त्रुटि -24 मिलती है, जो टी NPP User Guide के अनुसार NPP_TEXTURE_BIND_ERROR पर ranslates। इस मुद्दे का संक्षेप में this StackOverflow post में उल्लेख किया गया था।

  • यह कोड बहुत verbose है। यह मुख्य प्रश्न नहीं है, लेकिन क्या इस कोड को और संक्षिप्त बनाने के लिए किसी के पास कोई सुझाव है?
  • उत्तर

    2

    आप कर्नेल सरणी के लिए 2 डी मेमोरी आवंटक का उपयोग कर रहे हैं। कर्नेल सरणी घने 1 डी सरणी हैं, सामान्य डीपीपी छवि के रूप में 2 डी घुमावदार सरणी नहीं है।

    बस 2 डी CUDA malloc को आकार कर्नेल विथथ * कर्नेलहेइट * आकार (एनपीपीओ 2) के एक साधारण कूडा मॉलोक के साथ प्रतिस्थापित करें और सामान्य CUDA memcopy को memcopy 2D नहीं करें।

    //1D instead of 2D 
    cudaMalloc((void**)&deviceKernel, kernelSize.width * kernelSize.height * sizeof(Npp32s)); 
    cudaMemcpy(deviceKernel, hostKernel, kernelSize.width * kernelSize.height * sizeof(Npp32s), cudaMemcpyHostToDevice); 
    

    एक तरफ, एक "स्केल फैक्टर" 1 स्केलिंग में अनुवाद नहीं करता है। स्केलिंग कारकों 2^(- स्केल फैक्टर) के साथ होता है।

    +0

    आह, बढ़िया। मैं अब 1 डी 'cudaMalloc' और 1 डी' cudaMemcpy' कोशिश कर रहा हूँ। इसके अलावा, ऐसा लगता है कि 'स्केल फैक्टर = 0' कोई स्केलिंग नहीं देगा, सही? – solvingPuzzles

    +0

    1 डी मॉलोक और memcpy करने से समस्या ठीक हो गई !! धन्यवाद! यहां 2 डी 3x3 कर्नेल के साथ संसाधित छवि है: http://i.stack.imgur.com/wziix.png – solvingPuzzles

    +1

    यदि एनपीपी '2^(- स्केल फैक्टर)' द्वारा स्केल करता है, तो मुझे लगता है कि 'स्केल फैक्टर = 0' को देना चाहिए 1 का विभाजक। हालांकि, 'स्केल फैक्टर = 0' सेटिंग मुझे एक खाली छवि देता है। – solvingPuzzles