【问题标题】:OpenCL "read_imageui " always returns zero 0OpenCL "read_imageui" 总是返回零 0
【发布时间】:2018-01-04 01:38:14
【问题描述】:

我编写了一个简单的 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 的方式有问题

【问题讨论】:

  • 我在 Intel i5 , Ubuntu 14.04 上运行它
  • 图像采样器可能不适用于 jpeg 格式,除非 gpu 支持,因为它是压缩的。据我所知,只有纹理。 Mat 是从文件中读取不变的字节还是解密的像素数据?
  • 我认为 imread 返回解码图像。所以 mat.data 指向解码后的图像数据。
  • 底层图像数据white.data的表示是什么?您能否检查white.step 中的值,如果其中的值大于width * pixel_size,那么它可以在创建图像时用作音调。

标签: opencv opencl


【解决方案1】:

它与 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 复制构造函数在用作第一种语法时的“引用计数”。

【讨论】:

    【解决方案2】:

    写入时:

    Mat out = Mat(white);
    

    它就像whiteout 的浅拷贝。 Bot white.data 和 out.data 指针将指向相同的内存,并且引用计数将增加。所以,当你打电话给out.setTowhite Mat 也会看到同样的变化。如下声明可能是个好主意:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多