2017-06-01 146 views
4

我想將OpenCL Mat傳遞給FGPA的自寫OpenCL內核(不支持OpenCV OpenCL)。將Mat傳遞給OpenCL內核導致分割錯誤

HOST-代碼:

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] ; 
} 

當excecuting它在FPGA上我得到一個分割故障,偉馳是propably由於錯誤的處理與OpenCV的墊。

編輯: 編輯主機代碼由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); 

回答

4

我沒有與OpenCL的很多經驗,但我認爲這是一個OpenCV的/ C++的問題。

opencv mat數據位於img.data這是sizeof(T) * channels * rows * cols大小的uchar*

通常,T在加載圖像時是uchar,而通道是3(除非是灰度img)。 3通道uchar是每像素24位,並且灰度(正在加載時)是每像素8位,並且您使用uint,它的大小爲32位。在某些時候,它會超出內存並執行分段錯誤。另外,如果不在結構中使用數據指針,則可能正在複製標題信息以及指向數據的指針,而不是數據本身。

我建議你在改變&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不支持使用unsigned int的矩陣...只需確保在其他地方相應地更改它(即sizeof(uint)),並且如果轉換輸入,請記得使用相同的輸出創建輸出類型。

如果您更喜歡浮動,請使用CV_32F,如果您喜歡雙倍CV_64F

+0

非常感謝!您保存了我的一天:D將img更改爲img.data並將uint更改爲uchar解決了問題 – Drian