2017-06-01 9 views
4

OpenCV OpenCLをサポートしていないFGPA用のOpenCL Matを自己書き換え型のOpenCLカーネルに渡したいとします。OpenCLカーネルにMatを渡すと、セグメンテーションフォルトが発生する

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

OpenCVのマットと間違っ取り扱いによりpropablyあるwhichs私はセグメンテーションフォールトを得るFPGA上でそれをexcecuting。

EDIT: 編集ホスト・コード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++の問題だと思います。

は、sizeof(T) * channels * rows * colsuchar*である。

通常、画像をロードするときはTがucharで、チャンネルがグレースケールのimgでない場合は3です。 3チャンネルのucharは24ビット/ピクセルで、グレースケール(ロード中)は8ビット/ピクセルで、uintのサイズは32ビットです。ある時点で、メモリの外に出てセグメンテーションエラーが発生します。また、構造体内でデータポインタを使用しない場合は、データそのものではなく、ヘッダ情報とポインタのみをデータにコピーしている可能性があります。

私はあなたに&img変更することをお勧め:最後に、あなたは正しいデータを持っている必要がありimg.data

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

を。私は、OpenCLのはUCHAR使用可能かどうかわからないのですが、それは、このような別の型にcv::Matを変更できない場合:画像をロードした後

img.convertTo(img, CV_32S); 

。これはintに変更されます... opencvはunsigned intの行列をサポートしていません...他の場所(すなわちsizeof(uint))でそれを必ず変更してください。入力を変換する場合は、タイプ。

フロートをご希望の場合はCV_32Fを、ご希望の場合はCV_64Fをご使用ください。

+0

ありがとうございました!あなたは私の日を救った:Dはimg.dataに変更&imgし、ucharをucharに変更すると問題が解決した – Drian

関連する問題