2017-03-18 99 views
0

我寫了一個簡單的OpenCL程序,其目標是使用OpenCL image2d結構複製輸入圖像。這似乎是一個簡單的工作,但我一直堅持下去。OpenCL「read_imageui」總是返回零0

內核具有總是返回零值的「read_imageui」。輸入圖像是全白色的jpeg圖像。

使用OpenCV imread完成圖像加載。

這裏是內核:

const sampler_t smp = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST; 


__kernel void copy(__read_only image2d_t in, __write_only image2d_t out) 
{ 
    int idx = get_global_id(0); 
    int idy = get_global_id(1); 

    int2 pos = (int2)(idx,idy); 
    uint4 pix = read_imageui(in,smp,pos); 

    write_imageui(out,pos,pix); 

} 

這裏是主機代碼:

int main(){ 
    //get all platforms (drivers) 
    std::vector<cl::Platform> all_platforms; 
    cl::Platform::get(&all_platforms); 
    if(all_platforms.size()==0){ 
     std::cout<<" No platforms found. Check OpenCL installation!\n"; 
     exit(1); 
    } 
    cl::Platform default_platform=all_platforms[0]; 
    std::cout << "Using platform: "<<default_platform.getInfo<CL_PLATFORM_NAME>()<<"\n"; 
    std::cout <<" Platform Version: "<<default_platform.getInfo<CL_PLATFORM_VERSION>() <<"\n"; 
    //cout << "Image 2D support : " << default_platform.getInfo<CL_DEVICE_IMAGE_SUPPORT>()<<"\n"; 

    //get default device of the default platform 
    std::vector<cl::Device> all_devices; 
    default_platform.getDevices(CL_DEVICE_TYPE_ALL, &all_devices); 
    if(all_devices.size()==0){ 
     std::cout<<" No devices found. Check OpenCL installation!\n"; 
     exit(1); 
    } 
    cl::Device default_device=all_devices[0]; 
    std::cout<< "Using device: "<<default_device.getInfo<CL_DEVICE_NAME>()<<"\n"; 

    //creating a context 

    cl::Context context(default_device); 
    //cl::Program::Sources sources; 
    //sources.push_back(LoadKernel('kenel2.cl')); 


    //load kernel coad 
    cl::Program program(context,LoadKernel("image_test.cl")); 

    //build kernel code 
    if(program.build(all_devices)!=CL_SUCCESS){ 
     std::cout<<" Error building: "<<program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device)<<"\n"; 
     exit(1); 
    } 

    /* IMAGE FORMTS */ 

    // Determine and show image format support 
    vector<cl::ImageFormat > supportedFormats; 
    context.getSupportedImageFormats(CL_MEM_READ_ONLY,CL_MEM_OBJECT_IMAGE2D,&supportedFormats); 

    cout <<"No. of supported formats " <<supportedFormats.size()<<endl; 
    Mat white = imread("white_small.jpg"); 

    cvtColor(white, white, CV_BGR2RGBA); 

    //white.convertTo(white,CV_8UC4); 
    Mat out = Mat(white); 
    out.setTo(Scalar(0)); 

    char * inbuffer = reinterpret_cast<char *>(white.data); 
    char * outbuffer = reinterpret_cast<char *>(out.data); 

    //cout <<"Type of input : " <<white.type<<endl; 

    int sizeOfImage = white.cols * white.rows * white.channels(); 
    int outImageSize = white.cols * white.rows * white.channels(); 
    int w = white.cols; 
    int h = white.rows; 

    cout <<"Creating Images ... "<<endl; 
    cout <<"Dimensions ..." <<w << " x "<<h<<endl; 


    const cl::ImageFormat format(CL_RGBA, CL_UNSIGNED_INT8); 
    cl::Image2D imageSrc(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, format, white.cols, white.rows,0,inbuffer); 
    cl::Image2D imageDst(context, CL_MEM_WRITE_ONLY, format , white.cols, white.rows,0,NULL); 

    cout <<"Creating Kernel Program ... "<<endl; 

    cl::Kernel kernelCopy(program, "copy"); 
    kernelCopy.setArg(0, imageSrc); 
    kernelCopy.setArg(1, imageDst); 

    cout <<"Creating Command Queue ... "<<endl; 
    cl::CommandQueue queue(context, default_device); 

    cout <<"Executing Kernel ... "<<endl; 
    int64 e = getTickCount(); 
    for(int i = 0 ; i < 100 ; i ++) 
    { 


     queue.enqueueNDRangeKernel(kernelCopy, cl::NullRange, cl::NDRange(w, h), cl::NullRange); 
     queue.finish(); 
    } 

    cout <<((getTickCount() - e)/getTickFrequency())/100 <<endl;; 

    cl::size_t<3> origin; 
    cl::size_t<3> size; 
    origin[0] = 0; 
    origin[1] = 0; 
    origin[2] = 0; 
    size[0] = w; 
    size[1] = h; 
    size[2] = 1; 

    cout <<"Transfering Images ... "<<endl; 
    //unsigned char *tmp = new unsigned char (w * h * 4); 
    //CL_TRUE means that it waits for the entire image to be copied before continuing 
    queue.enqueueReadImage(imageDst, CL_TRUE, origin, size, 0, 0, outbuffer); 
    queue.finish(); 
    imwrite("result.jpg",out); 
    /* OLD CODE ==================================================*/ 

    return 0; 
} 

但是,如果我改變內核

uint4 pix2 = (uint4)(255,255,255,1); 
write_imageui(out,pos,pix2); 

它輸出一個白色圖像。這意味着我如何使用read_image

+0

我運行它的英特爾酷睿i5,Ubuntu的14.04 –

+0

圖像採樣器可以不是JPEG格式的工作,除非GPU支持,因爲它被壓縮。據我所知,只有紋理。 Mat是否從文件中讀取不變的字節或解密的像素數據? –

+0

我認爲imread返回解碼圖像。所以mat.data指向解碼的圖像數據。 –

回答

0

它出現了與Mat拷貝構造函數中的「引用計數」有關的內容。

如果不是使用

Mat white = imread("white_small.jpg"); 

    cvtColor(white, white, CV_BGR2RGBA); 

    //white.convertTo(white,CV_8UC4); 
    Mat out = Mat(white); 

初始化輸出矩陣 「走出去」 作爲

Mat out = Mat(white.size,CV_8UC4) 

然後正常工作。

我無法完全理解究竟是什麼導致了它,但我知道這是由於Mat拷貝構造函數在作爲第一種語法時的「引用計數」。

0

當寫:

Mat out = Mat(white); 

它像white淺拷貝到out。 Bot white.data和out.data指針將指向相同的內存,引用計數將遞增。所以,當你撥打out.setTo時,white墊子也會看到相同的變化。如下聲明出來會是個不錯的想法:

Mat out = Mat(white.size,CV_8UC(white.channels()));