These days, looking at the OpenCL Programming Guide, follow the example in the book to implement the Sobel algorithm:
1. Combine OpenCV to read the image and save to the buffer;
2. Write and compile the kernel and save the results after display processing.
Kernel:
Const sampler_t Sampler = Clk_address_clamp_to_edge | Clk_filter_nearest;kernel void Sobel_rgb (read_only image2d_t src,write_only image2d_t DST) {int x = (int) get_global_id (0 int y = (int) get_global_id (1), if (x >= get_image_width (src) | | y >= get_image_height (src)) return;float4 p00 = Read _IMAGEF (SRC, sampler, (Int2) (X-1, y-1)); Float4 P10 = READ_IMAGEF (src, sampler, (Int2) (x, y-1)); Float4 P20 = Read_ima GEF (SRC, Sampler, (Int2) (x + 1, y-1)), float4 P01 = READ_IMAGEF (src, sampler, (Int2) (x-1, y)); Float4 P21 = READ_IMAGEF ( SRC, Sampler, (Int2) (x + 1, y)), float4 p02 = READ_IMAGEF (src, sampler, (Int2) (x-1, y + 1)); Float4 p12 = READ_IMAGEF (src, Sampler, (Int2) (x, y + 1)), float4 P22 = READ_IMAGEF (src, sampler, (Int2) (x + 1, y + 1)); FLOAT3 GX =-p00.xyz + p20.xyz + 2.0* (P21.XYZ-P01.XYZ)-p02.xyz + p22.xyz;float3 Gy =-p00.xyz + p02.xyz + 2.0* (p21.xyz-p10.xyz)-p20.xyz + p22.xyz;f LOAT3 g = native_sqrt (GX*GX + gy*gy); Write_imagef (DST, (Int2) (x, Y), (FLOAT4) (g.x,g.y,g.z,1.0f));}Todo:add OpenCL kernel code here.
C + + Source:
BOOK:OPENCL (R) programming guide//authors:aaftab Munshi, Benedict Gaster, Timothy Mattson, James Fung, Dan ginsburg//isbn-10:0-321-74964-2//isbn-13:978-0-321-74964-2//Publisher:addison-wesley Professional//urls:h ttp://safari.informit.com/9780132488006///http://www.openclprogrammingguide.com////imagefilter2d.cpp////T His example demonstrates performing Gaussian filtering on a 2D image using//opencl////Requires freeimage Library F or image i/o://http://freeimage.sourceforge.net/#include <iostream> #include <fstream> #include <sstre am> #include <string.h> #include <opencv.hpp> #ifdef __apple__#include <OpenCL/cl.h> #else # Include <CL/cl.h> #endif # include "FreeImage.h"/////Create a OpenCL context on the first available platform using// Either a GPU or CPU depending on what's Available.//cl_context Createcontext () {cl_int errnum;cl_uint NUMPLATFORMS;CL_PL ATFORM_ID Firstplatformid;cl_context Context = null;//First, select an OpenCL platform to run on. For this example, we//simply choose the first available platform. Normally, would//query for all available platforms and select the most appropriate one.errnum = Clgetplatformids (1, & Amp;firstplatformid, &numplatforms); if (errnum! = cl_success | | numplatforms <= 0) {std::cerr << "Failed to fi nd any OpenCL platforms. "<< Std::endl;return NULL;} Next, create an OpenCL context on the platform. Attempt to//Create a gpu-based context, and if that fails, try to create//a cpu-based context.cl_context_properties cont Extproperties[] ={cl_context_platform, (cl_context_properties) Firstplatformid,0};context = ClCreateContextFromType (Contextproperties, Cl_device_type_gpu,null, NULL, &errnum); if (errnum! = cl_success) {std::cout << "Could not Create GPU context, trying CPU ... "<< std::endl;context = Clcreatecontextfromtype (contextproperties, Cl_device_ Type_cpu,null, NULL, &errnum); if (errnum! = cl_success) {std::cerr << "Failed to create an OpenCL GPU or CPU context." << Std::endl;return NULL;}} return context;} Create a command queue on the first device available on the//context//cl_command_queue createcommandqueue (cl_cont Ext context, cl_device_id *device) {cl_int errnum;cl_device_id *devices;cl_command_queue commandqueue = NULL;size_t Devicebuffersize = -1;//First get the size of the devices Buffererrnum = Clgetcontextinfo (context, cl_context_devices, 0, NULL, &devicebuffersize), if (errnum! = cl_success) {std::cerr << "Failed call to Clgetcontextinfo (..., gl_ Context_devices,...) "; return NULL;} if (devicebuffersize <= 0) {std::cerr << "No devices available."; return NULL;} Allocate memory for the devices bufferdevices = new Cl_device_id[devicebuffersize/sizeof (cl_device_id)];errnum = Clge Tcontextinfo (context, cl_context_devices, Devicebuffersize, DEVICES, NULL); if (errnum! = cl_success) {Std::cerr < < "Failed to get Device IDs"; RetuRN NULL;} In this example, we just choose the first available device. In a//Real program, you would likely with all available devices or choose//the highest performance device based on OpenCL Device Queriescommandqueue = Clcreatecommandqueue (context, Devices[0], 0, NULL); if (commandqueue = = NULL) {Std::cerr < < "Failed to create commandqueue for device 0"; return NULL;} *device = Devices[0];d elete[] Devices;return commandqueue;} Create an OpenCL program from the kernel source File//cl_program Createprogram (cl_context context, cl_device_id Dev Ice, const char* fileName) {cl_int errnum;cl_program program;std::ifstream kernelfile (FileName, std::ios::in); Kernelfile.is_open ()) {Std::cerr << "Failed to open file for reading:" << fileName << Std::endl;return N ULL;} Std::ostringstream oss;oss << kernelfile.rdbuf (); std::string srcstdstr = OSS.STR (); const char *SRCSTR = Srcstdstr.c_str ();p Rogram = Clcreateprogramwithsource (context, 1, (const char**) &SRCSTR,null, NULL), if (program = = NULL) {std::cerr << "Failed to create CL program from source." << Std::endl;return NULL;} Errnum = Clbuildprogram (program, 0, NULL, NULL, NULL, NULL); if (errnum! = cl_success) {//Determine the reason for the Erro Rchar buildlog[16384];clgetprogrambuildinfo (program, Device, Cl_program_build_log,sizeof (Buildlog), BuildLog, NULL) ; Std::cerr << ' Error in kernel: ' << std::endl;std::cerr << buildlog;clreleaseprogram (program); return NULL;} return program;} Cleanup any created OpenCL resources//void Cleanup (cl_context context, Cl_command_queue Commandqueue,cl_program PR Ogram, Cl_kernel kernel, Cl_mem Imageobjects[2],cl_sampler sampler) {for (int i = 0; i < 2; i++) {if (imageobjects[i]! = 0) Clreleasememobject (imageobjects[i]);} if (commandqueue! = 0) Clreleasecommandqueue (commandqueue); if (kernel! = 0) Clreleasekernel (kernel); if (program! = 0) Clreleaseprogram (program); if (sampler! = 0) Clreleasesampler (sampler); if (context! = 0) ClreleaseContext (context);} Load an image using the Freeimage library and create a opencl//image out of It//cl_mem LoadImage (Cl_context cont Ext, char *filename, int &width, int &height) {//free_image_format FORMAT = freeimage_getfiletype (fileName, 0);// fibitmap* image = Freeimage_load (format, fileName);////Convert to 32-bit image//fibitmap* temp = Image;//image = Freeimag E_convertto32bits (image);//freeimage_unload (temp);//width = Freeimage_getwidth (image);//height = Freeimage_ GetHeight (image);/*char *buffer = new Char[width * Height * 4];memcpy (buffer, freeimage_getbits (image), Width * Height * 4 ); Freeimage_unload (image); */cv::mat image1 = Cv::imread (fileName); width = Image1.cols;height = Image1.rows;char *buffer = New Char[width * Height * 4];int w = 0;for (int v = height-1; v >= 0; v--) {for (int u = 0; u <width; u++) {buffer[w + +] = image1.at<cv::vec3b> (V, u) [0];buffer[w++] = image1.at<cv::vec3b> (V, u) [1];buffer[w++] = image1.at <cv::Vec3b> (V, u) [2];w++;}} Create OpenCL Imagecl_image_format climageformat;climageformat.image_channel_order = Cl_rgba;climageformat.image_ Channel_data_type = cl_unorm_int8;cl_int Errnum;cl_mem climage;climage = clcreateimage2d (Context,CL_MEM_READ_ONLY | Cl_mem_copy_host_ptr,&climageformat,width,height,0,buffer,&errnum); if (errnum! = CL_SUCCESS) {Std::cerr << "Error Creating CL Image Object" << Std::endl;return 0;} return climage;} Save an image using the Freeimage library//bool saveimage (char *filename, char *buffer, int width, int height) {free _image_format FORMAT = Freeimage_getfiffromfilename (fileName); Fibitmap *image = Freeimage_convertfromrawbits ((byte*) buffer, width,height, Width * 4, 32,0xff000000, 0x00ff0000, 0x0000FF00); return freeimage_save (format, image, FileName);} Round up to the nearest multiple of the group size//size_t RoundUp (int groupsize, int globalsize) {int r = Globalsiz E% groupsize;if (r = = 0) {return globalsize;} Else{return globalsize + groupsize-r;}} /Main () for Hellobinaryworld example//int main (int argc, char** argv) {cl_context context = 0;cl_command_queue COMMANDQ Ueue = 0;cl_program program = 0;cl_device_id device = 0;cl_kernel kernel = 0;cl_mem Imageobjects[2] = {0, 0};cl_sampler Sampler = 0;cl_int Errnum;/*if (argc! = 3) {std::cerr << "USAGE:" << argv[0] << "<inputImageFile> <outputImageFiles> "<< Std::endl;return 1;} *///Create An OpenCL context on first available Platformcontext = Createcontext (); if (context = = NULL) {Std::cerr << "Failed to create OpenCL context." << Std::endl;return 1;} Create a command-queue on the first device available//on the Created Contextcommandqueue = createcommandqueue (Context, &device); if (commandqueue = = NULL) {Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler); return 1;} Make sure the device supports images, otherwise exitcl_bool imagesupport = Cl_false;clgetdeviceinfo (device, cl_device_i Mage_support, sizeof (Cl_booL), &imagesupport, NULL); if (imagesupport! = cl_true) {std::cerr << "OpenCL device does not support images." <& Lt Std::endl; Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler); return 1;} Load input image from file and load it into//an OpenCL image objectint width, height;char *src0 = "C:/users/jiang/desk Top/image/tu1.jpg "; Imageobjects[0] = LoadImage (context, src0, width, height); if (imageobjects[0] = = 0) {Std::cerr < < "Error loading:" << std::string (SRC0) << Std::endl; Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler); return 1;} Create ouput image Objectcl_image_format Climageformat;climageformat.image_channel_order = Cl_rgba; Climageformat.image_channel_data_type = cl_unorm_int8;imageobjects[1] = clcreateimage2d (Context,CL_MEM_WRITE_ONLY, &climageformat,width,height,0,null,&errnum); if (errnum! = cl_success) {std::cerr << "Error creating CL Output image object. "<< Std::endl; Cleanup (Context, CommAndqueue, program, kernel, imageobjects, sampler); return 1;} Create Sampler for sampling image objectsampler = Clcreatesampler (Context,cl_false,//non-normalized Coordinatescl_ad Dress_clamp_to_edge,cl_filter_nearest,&errnum); if (errnum! = cl_success) {std::cerr << "Error creating CL Sampler object. "<< Std::endl; Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler); return 1;} Create OpenCL Program//program = Createprogram (context, device, "imagefilter2d.cl");p Rogram = Createprogram (Context, Device, "sobel.cl"), if (program = = NULL) {Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler); return 1 ;} Create OpenCL Kernelkernel = Clcreatekernel (program, "Sobel_rgb", null); if (kernel = = null) {Std::cerr << Failed To create kernel "<< Std::endl; Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler); return 1;} Set the kernel argumentserrnum = clsetkernelarg (kernel, 0, sizeof (CL_MEM), &imageobjects[0]); ErrnuM |= Clsetkernelarg (kernel, 1, sizeof (CL_MEM), &imageobjects[1]);/*errnum |= Clsetkernelarg (kernel, 2, sizeof (CL_ Sampler), &sampler) errnum |= clsetkernelarg (kernel, 3, sizeof (Cl_int), &width); Errnum |= Clsetkernelarg ( Kernel, 4, sizeof (Cl_int), &height); */if (errnum! = cl_success) {std::cerr << "Error setting kernel arguments." & lt;< Std::endl; Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler); return 1;} size_t Localworksize[2] = {};size_t Globalworksize[2] = {RoundUp (localworksize[0], width), RoundUp (localworksize[ 1], height)};//Queue the kernel up for executionerrnum = Clenqueuendrangekernel (Commandqueue, kernel, 2, null,globalwork Size, localworksize,0, NULL, NULL), if (errnum! = cl_success) {std::cerr << "Error queuing kernel for execution." < < Std::endl; Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler); return 1;} Read the output buffer back to the Hostchar *buffer = new Char[width * Height * 4];size_t Origin[3] = {0, 0, 0};size_t region[3] = {width, height, 1};errnum = Clenqueuereadimage (Commandqueue, Imageobject S[1], Cl_true,origin, region, 0, 0, buffer,0, NULL, NULL); if (errnum! = cl_success) {std::cerr << "Error reading ResU Lt buffer. "<< Std::endl; Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler); return 1;} Std::cout << std::endl;std::cout << "Executed program succesfully." << std::endl;//memset (buffer, 0xFF, Width * height * 4);//Save the image out to Diskchar *saveimage = "c:/users/jiang/desktop/image/tu2.jpg";//std::cou T << buffer << Std::endl;cv::mat imagecolor = Cv::imread (SRC0); Cv::mat imagecolor2;imagecolor2.create ( Imagecolor.rows, Imagecolor.cols, Imagecolor.type ()), int w = 0;for (int v = imagecolor2.rows-1; v >=0; v--) {for (int u =0; U <imageColor2.cols; u++) {imagecolor2.at<cv::vec3b> (V, u) [0] = buffer[w++];imagecolor2.at<cv::vec3b> (V, u) [1] = buffer[w++]; Imagecolor2.at<cv::vec3B> (V, u) [2] = buffer[w++];w++;}} Cv::imshow ("image", ImageColor2); Cv::imwrite (SaveImage, ImageColor2); Cv::waitkey (0);/*if (! SaveImage (saveimage, buffer, width, height)) {std::cerr << "Error Writing output Image:" << saveimage<< Std::endl; Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler);d elete[] Buffer;return 1;} */delete[] buffer; Cleanup (context, Commandqueue, program, kernel, imageobjects, sampler); return 0;}
OPENCL+OPENCV implementation of Sobel algorithm