PyOpenCL сокращение Ядро на каждый пиксель изображения в виде массива вместо каждого байта (режим RGB, 24 бита)
Я пытаюсь вычислить среднюю яркость изображения RGB. Для этого я нахожу яркость каждого пикселя, т.е.
L(r,g,b) = X*r + Y*g + Z*b (some linear combination).
А затем найдите среднее значение, суммируя яркость всех пикселей и деля на ширину * высоту. Чтобы ускорить это, я использую pyopencl.reduction.ReductionKernel
Массив, который я передаю ему, представляет собой Single Dimension Numpy Array, поэтому он работает так же, как и в приведенном примере.
import Image
import numpy as np
im = Image.open('image_00000001.bmp')
data = np.asarray(im).reshape(-1) # so data is a single dimension list
# data.dtype is uint8, data.shape is (w*h*3, )
Я хочу включить в него следующий код из примера. т.е. я бы внес изменения в тип данных и тип массивов, которые я передаю. Это пример:
a = pyopencl.array.arange(queue, 400, dtype=numpy.float32)
b = pyopencl.array.arange(queue, 400, dtype=numpy.float32)
krnl = ReductionKernel(ctx, numpy.float32, neutral="0",
reduce_expr="a+b", map_expr="x[i]*y[i]",
arguments="__global float *x, __global float *y")
my_dot_prod = krnl(a, b).get()
За исключением того, что мой map_expr будет работать с каждым пикселем и преобразовывать каждый пиксель в его значение яркости. И уменьшить expr остается прежним.
Проблема в том, что он работает с каждым элементом массива, и мне нужно, чтобы он работал с каждым пикселем, который состоит из 3 последовательных элементов одновременно (RGB).
Одно из решений состоит в том, чтобы иметь три разных массива, один для R, один для G и один для B, что сработало бы, но есть ли другой способ?
1 ответ
Изменить: я изменил программу, чтобы проиллюстрировать использование char4 вместо float4:
import numpy as np
import pyopencl as cl
import pyopencl.array as cl_array
deviceID = 0
platformID = 0
workGroup=(1,1)
N = 10
testData = np.zeros(N, dtype=cl_array.vec.char4)
dev = cl.get_platforms()[platformID].get_devices()[deviceID]
ctx = cl.Context([dev])
queue = cl.CommandQueue(ctx)
mf = cl.mem_flags
Data_In = cl.Buffer(ctx, mf.READ_WRITE, testData.nbytes)
prg = cl.Program(ctx, """
__kernel void Pack_Cmplx( __global char4* Data_In, int N)
{
int gid = get_global_id(0);
//Data_In[gid] = 1; // This would change all components to one
Data_In[gid].x = 1; // changing single component
Data_In[gid].y = 2;
Data_In[gid].z = 3;
Data_In[gid].w = 4;
}
""").build()
prg.Pack_Cmplx(queue, (N,1), workGroup, Data_In, np.int32(N))
cl.enqueue_copy(queue, testData, Data_In)
print testData
Я надеюсь, что это помогает.