gpt4 book ai didi

opencv - 将 Mat 传递给 OpenCL 内核会导致段错误

转载 作者:太空宇宙 更新时间:2023-11-03 20:52:57 25 4
gpt4 key购买 nike

我想将 OpenCL Mat 传递给 FGPA 的自写 OpenCL 内核(不支持 OpenCV OpenCL)。

主机代码:

Mat img = imread( "template.jpg", IMREAD_GRAYSCALE );
Mat output(img.rows, img.cols, CV_8UC1);
// Program, Context already declared
// Create Kernel
cl_kernel kernel = NULL;
kernel = clCreateKernel(program, "copy", &status);
// Create Command Queue and associate it with the device you want to execute on
cl_command_queue cmdQueue;
cmdQueue = clCreateCommandQueue(context,devices[0], 0, &status);

// Buffer, prob i do something wrong here
cl_mem buffer_img = clCreateBuffer(context,CL_MEM_READ_ONLY, sizeof(uint) * img.cols * img.rows, NULL,&status);
cl_mem buffer_outputimg = clCreateBuffer(context,CL_MEM_WRITE_ONLY, sizeof(uint) * img.cols * img.rows,NULL,&status);

status = clEnqueueWriteBuffer(cmdQueue, buffer_img,CL_FALSE,0,sizeof(uint) * img.cols * img.rows,&img,0,NULL,NULL);
// set kernel arguments
status = clSetKernelArg(kernel,0,sizeof(cl_mem),&buffer_img);
status = clSetKernelArg(kernel,1,sizeof(cl_mem),&buffer_outputimg);

size_t globalWorkSize[2];
globalWorkSize[0] = img.cols;
globalWorkSize[1] = img.rows;
status = clEnqueueNDRangeKernel(cmdQueue,kernel,2,NULL, globalWorkSize, NULL,0, NULL,NULL);
clEnqueueReadBuffer(cmdQueue,buffer_outputimg,CL_TRUE,0,sizeof(uint) * img.cols * img.rows, &output, 0, NULL, NULL);

//stop cpu till queue is finish
clFinish(cmdQueue);

内核代码:

__kernel void copy(__global  uchar *  input, __global  uchar *  output) 
{
const int x = get_global_id(0);
const int y = get_global_id(1);
//copy
output[y * get_global_size(0) + x] = input[y * get_global_size(0) + x] ;
}

在 FPGA 上执行它时出现段错误,这可能是由于 OpenCV Mat 处理不当造成的。

编辑:按照 api55 的建议编辑主机代码解决了这个问题:

Mat img = imread( "scene.jpg", IMREAD_GRAYSCALE );
Mat output(img.rows, img.cols, CV_8UC1);
// Program, Context already declared
// Create Kernel
cl_kernel kernel = NULL;
kernel = clCreateKernel(program, "copy", &status);
// Create Command Queue and associate it with the device you want to execute on
cl_command_queue cmdQueue;
cmdQueue = clCreateCommandQueue(context,devices[0], 0, &status);
checkError(status, "Failed to create commadnqueue");

// Buffer
cl_mem buffer_img = clCreateBuffer(context,CL_MEM_READ_ONLY, sizeof(uchar) * img.cols * img.rows, NULL,&status);
cl_mem buffer_outputimg = clCreateBuffer(context,CL_MEM_WRITE_ONLY, sizeof(uchar) * img.cols * img.rows,NULL,&status);
checkError(status, "Failed to create buffer_mask");

status = clEnqueueWriteBuffer(cmdQueue, buffer_img,CL_FALSE,0,sizeof(uchar) * img.cols * img.rows,img.data,0,NULL,NULL);
checkError(status, "Failed to enqueue buffer_img");


status = clSetKernelArg(kernel,0,sizeof(cl_mem),&buffer_img);
status = clSetKernelArg(kernel,1,sizeof(cl_mem),&buffer_outputimg);

size_t globalWorkSize[2];
globalWorkSize[0] = img.cols;
globalWorkSize[1] = img.rows;
status = clEnqueueNDRangeKernel(cmdQueue,kernel,2,NULL, globalWorkSize, NULL,0, NULL,NULL);
clEnqueueReadBuffer(cmdQueue,buffer_outputimg,CL_TRUE,0,sizeof(uchar) * img.cols * img.rows, output.data,0,NULL,NULL);

imwrite("output.jpg", output);

最佳答案

我对 opencl 没有太多经验,但我认为这是一个 opencv/c++ 问题。

opencv mat 数据位于 img.data 中,它是一个大小为 sizeof(T) * channels * rows * colsuchar* >。

通常,加载图片时T为uchar,channels为3(除非是灰度img)。 3 channel uchar 是每像素 24 位,灰度(加载时)是每像素 8 位,您使用的是 32 位大小的 uint。在某些时候它会超出内存并进行段错误。此外,如果您不在结构中使用数据指针,则可能会复制 header 信息和指向数据的指针,而不是数据本身。

我建议你改变&img:

status = clEnqueueWriteBuffer(cmdQueue, buffer_img,CL_FALSE,0,sizeof(uint) * img.cols * img.rows,&img,0,NULL,NULL);

img.data

最后,您需要拥有正确的数据。我不确定 opencl 是否可以使用 uchar,但如果不能,请将 cv::Mat 更改为另一种类型,如下所示:

img.convertTo(img, CV_32S);

加载图像后。这会将其更改为 int...opencv 不支持具有无符号整数的矩阵...只需确保在其他地方相应地更改它(即 sizeof(uint)) 如果您转换输入,请记住创建具有相同类型的输出。

如果您喜欢 float ,请使用 CV_32F,如果您喜欢 double ,请使用 CV_64F

关于opencv - 将 Mat 传递给 OpenCL 内核会导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44300490/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com