Hi, this is my first experience with OpenCL.I successfully made an easy opencl example for adding two vectors using multiple GPUs but now I am trying to run Gaussian Blur.I found example on the Internet:
gaussian-blur-using-opencl-and-the-built-in-images-textures by Erik Smistad(I can’t post links).
I am reusing his kernel and createBlurMask function and this is my host code:
int GaussianBlur(OpenCLass& OCLass)
{
cl_int errNum;
cl_device_id * devices = OCLass.getDevices();
cl_uint devicesCount = OCLass.getDevicesCount();
cl_image_format format;
_cl_image_desc desc;
cv::Mat img = cv::imread("R9.jpg", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
if (img.empty())
{
std::cout << "Couldn't load the image
";
return 1;
}
std::cout << std::endl << img.type() << std::endl;
std::cout << img.channels();
cv::Mat transformedImg;
cv::cvtColor(img, transformedImg, CV_BGR2RGBA);
std::cout << "
Transformed image: " << transformedImg.type();
std::cout << "
Transformed image channels: " << transformedImg.channels() << std::endl;
char *buffer = reinterpret_cast<char *>(transformedImg.data);
// imwrite("RGBA_Image.jpg", transformedImg);
//defining image format and desc
format.image_channel_data_type = CL_UNSIGNED_INT8;
format.image_channel_order = CL_RGBA;
desc.image_width = transformedImg.cols;
desc.image_height = transformedImg.rows;
size_t globalWorkSize = desc.image_width*desc.image_height;
// Compile OpenCL code
cl_program gaussianBlur = createProgram(OCLass.getContext(), devicesCount, devices, "GaussianBlur.cl");
cl_command_queue queue = clCreateCommandQueue(OCLass.getContext(), devices[0], NULL, NULL);
cl_mem memoryObjects[3];
// Create an OpenCL Image / texture and transfer data to the device
memoryObjects[0] = clCreateImage(OCLass.getContext(), CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &format, &desc, buffer, &errNum);
// Create a buffer for the result
memoryObjects[2] = clCreateBuffer(OCLass.getContext(), CL_MEM_WRITE_ONLY, sizeof(int)*globalWorkSize, NULL, &errNum);
// Create Gaussian mask
int maskSize;
float * mask = createBlurMask(10.0f, &maskSize);
// Create buffer for mask and transfer it to the device
memoryObjects[1] = clCreateBuffer(OCLass.getContext(), CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float)*(maskSize * 2 + 1)*(maskSize * 2 + 1), mask, &errNum);
// Run Gaussian kernel
cl_kernel kernel = clCreateKernel(gaussianBlur, "gaussian_blur", &errNum);
errNum = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memoryObjects[0]);
errNum = clSetKernelArg(kernel, 1, sizeof(cl_mem), &memoryObjects[1]);
errNum = clSetKernelArg(kernel, 2, sizeof(cl_mem), &memoryObjects[2]);
errNum = clSetKernelArg(kernel, 3, sizeof(int), (void*)&maskSize);
if (errNum != CL_SUCCESS)
{
std::cerr << "Error setting kernel Arguments.
" << std::endl;
Cleanup(gaussianBlur, kernel, memoryObjects, 3);
return 1;
}
size_t localWorkSize = chooseLocalWorkSize(kernel, devices, 1, globalWorkSize);
errNum = clEnqueueNDRangeKernel(OCLass.getCommandQueue(0), kernel, 2, 0, &globalWorkSize, NULL, 0, NULL, NULL);
if (errNum != CL_SUCCESS)
{
std::cerr << "Error queuing kernel for execution." << std::endl;
Cleanup(gaussianBlur, kernel, memoryObjects, 3);
return 1;
}
// Transfer image back to host
uchar* data = new uchar[globalWorkSize*4];
clEnqueueReadBuffer(queue, memoryObjects[2], CL_TRUE, 0, sizeof(uchar)*globalWorkSize*4, data, 0, NULL, NULL);
for (unsigned i = 0; i < 100; ++i)
{
std::cout << "data[" << i << "] = " << data[i] << std::endl;
}
//create cv::Size object for creating a Mat object with proper size
cv::Size s;
s.height = desc.image_height;
s.width = desc.image_width;
//create cv::Mat object with data
cv::Mat outputImageRGBA(s, CV_8UC4, data);
cv::Mat outputImageBGR;
//convert to BGR because imwrite doc: "Only 8-bit (or 16-bit unsigned (CV_16U) in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with ‘BGR’ channel order) images can be saved using this function."
cv::cvtColor(outputImageRGBA, outputImageBGR, CV_RGBA2BGR);
//save to disc with imwrite
cv::imwrite("BlurredPic.jpg", outputImageBGR);
Cleanup(gaussianBlur, kernel, memoryObjects, 3);
delete[] data;
}
The problem is that BlurredPic.jpg is completely black.
The author of the tutorial is using single channel image - CL_R and I am trying to do it with CL_RGBA type memory object.Do I need to change something in kernel to reflect this difference?Or the problem is with reading back the result memory buffer because neither element of the data array prints value?
Thanks in advance!