Question

I've been having some trouble making a copy of an image using PyOpenCL. I wanted to try copying as I really want to do other processing, but im not able to understand this basic task of accessing every pixel. Please help me catch the error to make sure it works.

Here is the program

import pyopencl as cl
import numpy
import Image
import sys

img = Image.open(sys.argv[1])
img_arr = numpy.asarray(img).astype(numpy.uint8)
dim = img_arr.shape

host_arr = img_arr.reshape(-1)

ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)
mf = cl.mem_flags
a_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=host_arr)
dest_buf = cl.Buffer(ctx, mf.WRITE_ONLY, host_arr.nbytes)

kernel_code = """
    __kernel void copyImage(__global const uint8 *a, __global uint8 *c)
    {
        int rowid = get_global_id(0);
        int colid = get_global_id(1);

        int ncols = %d;
        int npix = %d; //number of pixels, 3 for RGB 4 for RGBA

        int index = rowid * ncols * npix + colid * npix;
        c[index + 0] = a[index + 0];
        c[index + 1] = a[index + 1];
        c[index + 2] = a[index + 2];
    }
    """ % (dim[1], dim[2])

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

prg.copyImage(queue, (dim[0], dim[1]) , None, a_buf, dest_buf)

result = numpy.empty_like(host_arr)
cl.enqueue_copy(queue, result, dest_buf)

result_reshaped = result.reshape(dim)
img2 = Image.fromarray(result_reshaped, "RGB")
img2.save("new_image_gpu.bmp")

The image I gave as input was enter image description here

However, the output from the program was enter image description here

I'm not able to make sense of why those black lines appear. Please help me solve this bug.

Thank You

OK ! so I've found a solution. I changed all uint8 to int, and in the numpy array i removed the "astype(numpy.uint8)". I dont know why, I just tried this and it worked. An explanation as to why would be helpful. Also, does this mean this will take much more memory now ? It works, but now I think it takes much more memory. Any workaround using the uint8 will be helpful.

Was it helpful?

Solution

There is a mismatch between the datatypes your are using in Python and OpenCL. In numpy, a uint8 is an 8-bit unsigned integer (which I presume is what you were after). In OpenCL, a uint8 is an 8-element vector of 32-bit unsigned integers. The correct datatype for an 8-bit unsigned integer in OpenCL is just uchar. So, your astype(numpy.uint8) is fine, but it should be accompanied by arrays of __global const uchar* in your OpenCL kernel.

If you are dealing with images, I would also recommend looking into OpenCL's dedicated image types, which can take advantage of the native support for handling images available in some hardware.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top