Линейная выборка OpenCL image3d

Я делаю линейную интерполяцию с OpenCL, но результат не такой, как ожидалось. Поэтому я сделал простой тест, код ядра показан ниже:

const sampler_t sampler = CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP_TO_EDGE;
// Kernel block.
kernel void interpolate(
                   global float4*input,
                   image3d_t image,
                   global float4*output)
{
    size_t i = get_global_id(0);
    float4 coord = input[i];
    float4 tap = read_imagef(image, sampler, coord);
    output[i] = tap;
}

Пиксели (в RGBA) изображения 2x2x2, как показано ниже:

cl_float4 image_data[8] = {
    {0, 0, 0, 0},
    {100, 0, 0, 0},
    {0, 100, 0, 0},
    {100, 100, 0, 0},
    {0, 0, 100, 0},
    {100, 0, 100, 0},
    {0, 100, 100, 0},
    {100, 100, 100, 0},
};

Я использовал 11 координат ((0, 0, 0), (0,1, 0,1, 0,1)... (1, 1, 1), от 0 до 1 с шагом 0,1), чтобы прочитать изображение, и я ожидаю, что результаты будут быть (0, 0, 0), (10, 10, 10)... (100, 100, 100), но я получил:

coordinate:0.000000, result: 0.000000
coordinate:0.100000, result: 0.000000
coordinate:0.200000, result: 0.000000
coordinate:0.300000, result: 10.156250
coordinate:0.400000, result: 30.078125
coordinate:0.500000, result: 50.000000
coordinate:0.600000, result: 69.921875
coordinate:0.700000, result: 89.843750
coordinate:0.800000, result: 100.000000
coordinate:0.900000, result: 100.000000
coordinate:1.000000, result: 100.000000

Он просто возвращает значение края, когда координаты меньше 0,25 или больше 0,75.

Кто-нибудь может это объяснить? Спасибо.


person wtl    schedule 16.11.2013    source источник


Ответы (1)


Откуда: http://www.khronos.org/registry/cl/specs/opencl-1.x-latest.pdf#page=213

«Если какой-либо из выбранных Tijk или Tij в приведенных выше уравнениях относится к месту за пределами изображения, цвет границы используется в качестве значения цвета для Tijk или Tij».

Ниже 0,25 и выше 0,75 в вашем случае выполняется интерполяция по значениям пикселей за пределами изображения, поэтому они прижимаются к краю. Поэтому все значения являются просто краевыми значениями.

Почему это так? Поскольку центр пикселя краевого пикселя не равен 0, вместо этого в вашем случае он равен 0,25 (0 — левый край, а 0,5 — правый край). Следовательно, выборка значений от 0 до 0,25 вызывает интерполяцию пикселя с самим собой. Вам просто нужно получить доступ к массиву от 0,25 до 0,75, и все готово. В случае большего количества пикселей вам просто нужно снова получить к ним доступ. Например, с 4 пикселями вы начинаете с 0,125 (1/4/2).

person sharpneli    schedule 16.11.2013
comment
Я согласен. Спецификация включает точную математику, используемую для перехода от вашей координаты к элементам, к которым осуществляется доступ, и смешиванию, используемому между ними. Сначала изучите случай 1D или 2D, так как в игре меньше элементов. С ненормализованными координатами вы можете добавить 0,5 для учета смещения центра (вы можете преобразовать свое значение 0,0 в 1,0, умножив количество элементов минус один, а затем добавить 0,5. - person Dithermaster; 16.11.2013
comment
Спасибо за вашу помощь, Sharpneli и @Dithermaster. Я тестировал код как на CPU, так и на GPU, но результаты между ними сильно различаются. Я задал еще один вопрос по этой ссылке изображение с линейным фильтром clk в opencl"> stackoverflow.com/questions/20027292/, можете ли вы ответить на него? - person wtl; 17.11.2013