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
However, the output from the program was
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.
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.