Uncategorized

OpenCL in Python: Installing and Testing PyOpenCL

If you're on OSX, make sure XCode is installed on your machine before beginning. On Linux, just go for it with apt-get install python3-pyopencl

Step 1: Install Python 3.9.0 from python.org (or via apt-get install python3) (https://www.python.org/downloads/release/python-390/)

Step 2: Install Curl and Pip if needed

sudo apt-get install curl
sudo apt-get install python3-pip 

or 

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python3 get-pip.py

Step 3: Install the PyOpenCL Package using pip

pip3 install pyopencl

Now, ensure that your computer’s OpenCL Devices are seen. Start a python terminal, then run:

import pyopencl
from pyopencl.tools import get_test_platforms_and_devices
get_test_platforms_and_devices()

Execution should yield something like:

[(<pyopencl.Platform 'Apple' at 0x7fff0000>, [<pyopencl.Device 'Intel(R) Core(TM) i7-3820QM CPU @ 2.70GHz' on 'Apple' at 0xffffffff>, <pyopencl.Device 'HD Graphics 4000' on 'Apple' at 0x1024400>, <pyopencl.Device 'GeForce GT 650M' on 'Apple' at 0x1022700>])]

If instead you get an error such as:

pyopencl._cl.LogicError: clGetPlatformIDs failed: PLATFORM_NOT_FOUND_KHR

You likely don’t have an OpenGL instance installed. Try Installing POCL first, then trying again.

Now, you can test the setup with the following Median Filter sample modified slightly from Andreas Kl√∂ckner’s sample code. This sample reads and writes images to disk, so you’ll first need to install the ImageIO package using pip:

pip3 install imageio

Start a python terminal, then run the following (or save the following to a .py file on your machine). The terminal will ask you for a path to an image file, as well as request that you choose a platform and device from your computer’s device list during execution.

import imageio as io
import pyopencl as cl
import numpy as np

path = input("File to filter: ")

img = io.imread(path, as_gray=True).astype(np.float32)
ctx = cl.create_some_context()

queue = cl.CommandQueue(ctx)

mf = cl.mem_flags

src = '''
void sort(int *a, int *b, int *c) {
   int swap;
   if(*a > *b) {
      swap = *a;
      *a = *b;
      *b = swap;
   }
   if(*a > *c) {
      swap = *a;
      *a = *c;
      *c = swap;
   }
   if(*b > *c) {
      swap = *b;
      *b = *c;
      *c = swap;
   }
}
__kernel void medianFilter(__global float *img, __global float *result, __global int *width, __global int *height)
{
    int w = *width;
    int h = *height;
    int posx = get_global_id(1);
    int posy = get_global_id(0);
    int i = w*posy + posx;
    // Keeping the edge pixels the same
    if( posx == 0 || posy == 0 || posx == w-1 || posy == h-1 )
    {
        result[i] = img[i];
    }
    else
    {
        int pixel00, pixel01, pixel02, pixel10, pixel11, pixel12, pixel20, pixel21, pixel22;
        pixel00 = img[i - 1 - w];
        pixel01 = img[i- w];
        pixel02 = img[i + 1 - w];
        pixel10 = img[i - 1];
        pixel11 = img[i];
        pixel12 = img[i + 1];
        pixel20 = img[i - 1 + w];
        pixel21 = img[i + w];
        pixel22 = img[i + 1 + w];
        //sort the rows
        sort( &(pixel00), &(pixel01), &(pixel02) );
        sort( &(pixel10), &(pixel11), &(pixel12) );
        sort( &(pixel20), &(pixel21), &(pixel22) );
        //sort the columns
        sort( &(pixel00), &(pixel10), &(pixel20) );
        sort( &(pixel01), &(pixel11), &(pixel21) );
        sort( &(pixel02), &(pixel12), &(pixel22) );
        //sort the diagonal
        sort( &(pixel00), &(pixel11), &(pixel22) );
        // median is the the middle value of the diagonal
        result[i] = pixel11;
    }
}
'''

prg = cl.Program(ctx, src).build()

img_g =  cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=img)
result_g = cl.Buffer(ctx, mf.WRITE_ONLY, img.nbytes)
width_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=np.int32(img.shape[1]))
height_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=np.int32(img.shape[0]))

prg.medianFilter(queue, img.shape, None , img_g, result_g, width_g, height_g)

result = np.empty_like(img)
cl.enqueue_copy(queue, result, result_g)

io.imsave('medianFilter-OpenCL.jpg',result)

I used the following image as input:

Which yields the following greyscale output after median filtering:

Leave a Reply

Your email address will not be published. Required fields are marked *