OpenCL" read_imageui"始终返回零0

时间:2017-03-18 12:34:18

标签: opencv opencl

我编写了一个简单的OpenCL程序,其目标是使用OpenCL image2d结构复制输入图像。这似乎是一项简单的工作,但我一直坚持下去。

内核有" 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

的方式有问题

2 个答案:

答案 0 :(得分:0)

它出现了与Mat拷贝构造函数中的“引用计数”相关的东西。

如果不是使用

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

    cvtColor(white, white, CV_BGR2RGBA);

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

将输出矩阵“out”初始化为

Mat out = Mat(white.size,CV_8UC4)

然后它运作正常。

我无法完全理解究竟是什么造成了它,但我知道这是由于Mat拷贝构造函数的“引用计数”在用作第一语法时所致。

答案 1 :(得分:0)

写时:

Mat out = Mat(white);

这就像whiteout的浅层副本。 Bot white.data和out.data指针将指向相同的内存,引用计数将递增。因此,当您致电out.setTo时,white Mat也会看到同样的变化。声明如下可能是个好主意:

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