我编写了一个简单的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
的方式有问题答案 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);
这就像white
到out
的浅层副本。 Bot white.data和out.data指针将指向相同的内存,引用计数将递增。因此,当您致电out.setTo
时,white
Mat也会看到同样的变化。声明如下可能是个好主意:
Mat out = Mat(white.size,CV_8UC(white.channels()));