Making PyOpenCL handle NumPy arrays as images

PyOpenCL Image objects take a shape tuple that gives (width, height, depth), but NumPy arrays specify shape in the order (rows, columns, …) a.k.a. (height, width, …) where the ellipsis indicates higher dimensions.  What’s important is that the width and height dimensions have been swapped.  The PyOpenCL documentation suggests creating the NumPy arrays in the Fortran or column-major order, instead of the default row major order.  While that is fine for single channel images, RGB and RGBA images still get messed up.  The solution turned out to be quite easy: swap the first and second dimension.  I assume an OpenCL context (ctx) has already been created and you have an image shape tuple specified as image_shape=(rows, columns, …).  This line creates the OpenCL 2D image and stores it in input_image_cl:

input_image_cl = cl.Image(ctx, cl.mem_flags.READ_ONLY, cl.ImageFormat(ch_order, cl.channel_type.UNORM_INT8), image_shape[1::-1])

Now, lets say you have a NumPy array, called input_img, storing the image, the following will write that array to the OpenCL image.  I assume that you already have an OpenCL command queue for writing data to the device, called mem_write_queue.  Also, make sure that input_image is in row-major order, not column-major order (Fortran order).

cl.enqueue_copy(mem_write_queue, input_image_cl, input_img, is_blocking=True, origin=(0, 0), region=input_img.shape[1::-1])

All this works for row-major ordering because OpenCL uses that order as well.  If your array is in column-major order you can use numpy.asarray (does not make a copy), numpy.copy or the copy method in numpy.ndarray and pass the parameter order=’C’.  Remember that row-major order assumes that the last dimension varies fastest.

Of course, if you use OpenCL buffer objects then this isn’t a problem.  I think this should also work for 3D images as well, just keep in mind that the third dimension must be used for the colour channels, while the 4th dimension is for the z-axis.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s