2017-06-01 2 views
4

Ich möchte eine OpenCL Mat an einen selbstgeschriebenen OpenCL Kernel für einen FGPA übergeben (OpenCV OpenCL wird nicht unterstützt).Passing Mat zu OpenCL Kernel verursacht Segmentierungsfehler

Host- Code:

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-Code:

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

Wenn es auf dem FPGA excecuting ich einen Segmentation fault erhalten, Rechenblatt mit der OpenCV Mat propably aufgrund der falschen Handhabung ist.

EDIT: Edited-Host-Kodex von api55 vorgeschlagen löste das Problem:

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); 

Antwort

4

ich viel Erfahrung nicht mit OpenCL haben, aber ich denke, es ist ein opencv/C++ Problem.

Die openvv mat Daten liegen in img.data das ist ein uchar* der Größe sizeof(T) * channels * rows * cols.

Normalerweise T ist uchar beim Laden von Bildern, und Kanäle ist 3 (es sei denn, das ist eine Graustufe img). 3 Kanal Uchar ist 24 Bit pro Pixel und Graustufen (wie Sie laden) ist 8 Bit pro Pixel und Sie verwenden uint, die Größe von 32 Bit ist. Irgendwann wird es den Speicher verlassen und den Segmentierungsfehler machen. Wenn Sie den Datenzeiger in der Struktur nicht verwenden, kopieren Sie möglicherweise die Header-Information und nur den Zeiger auf den Daten und nicht die Daten.

Ich schlage vor, Sie &img sich ändern in:

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

zu img.data

Schließlich Sie die richtigen Daten haben müssen. Ich bin nicht sicher, ob OpenCL uchar verwenden kann, aber wenn es nicht kann, die cv::Mat auf eine andere Art, wie dies ändern:

img.convertTo(img, CV_32S); 

Nach dem Laden des Bildes. Dies wird es in int ändern ... opencv unterstützt keine Matrizen mit unsigned int ... einfach sicherstellen, dass Sie es entsprechend an den anderen Stellen ändern (dh sizeof(uint)) und wenn Sie die Eingabe konvertieren, denken Sie daran, die Ausgabe mit dem gleichen zu erstellen Art.

Wenn Sie float bevorzugen, verwenden Sie CV_32F und wenn Sie möchten, double CV_64F.

+0

Vielen Dank !! Du hast meinen Tag gerettet: D das Ändern von & img zu img.data und das Wechseln von uint zu uchar hat das Problem gelöst – Drian

Verwandte Themen