Better way to get neighborhood on image2d_t?

Hello guys, I have a kernel to manipulate a image, I’m using image2D to do it and I need to get the neighborhood pixels of the actual pixel, the way i figured out to do it was this way:


  float4 b1, b2, b3, b4, b5, b6, b7, b8, b9;
  b1 = read_imagef(buffer, sampler, (x - 1, y - 1));
  b2 = read_imagef(buffer, sampler, (x, y - 1));
  b3 = read_imagef(buffer, sampler, (x + 1, y - 1));
  b4 = read_imagef(buffer, sampler, (x - 1, y));
  b5 = read_imagef(buffer, sampler, (x, y));
  b6 = read_imagef(buffer, sampler, (x + 1, y));
  b7 = read_imagef(buffer, sampler, (x - 1, y + 1));
  b8 = read_imagef(buffer, sampler, (x, y + 1));
  b9 = read_imagef(buffer, sampler, (x + 1, y + 1));

this way i have 9 float4 variables making an kernel 3x3, but I wonder if there is a more efficient way to do it, I’m open to ideas.

ps: for border I’m using CLK_ADDRESS_CLAMP_TO_EDGE

Thanks!

Have you considered using a for loop?

Yes but in the end the result will be the same and I think it will be a little slower with a loop, what I really want is some way to get the 3x3 neighborhood of the pixel without calling read_imagef for every one of then.

Thanks!

Then use a “normal” memory buffer at the expense of CLK_ADDRESS_CLAMP_TO_EDGE.

Sorry, I didn’t got what you mean as “normal” memory buffer, I’m really new to opencl.

Using a buffer in global memory (a pointer argument to the kernel) manually fetching the pixels will bypass the hardware that GPUs have to accelerate texture fetches.

Is there something in particular about read_imagef() that concerns you? It’s the most efficient way to read texture data.

what is happening is that I’m not sure if the read_imagef is returning the right pixel to me.
I’m making a kernel to do anisotropic diffusion in opencl, I have an somehow working version using float4 buffers, but I have to check for borders using the buffer because it doesn’t have CLAMP_TO_EDGE.
Then I decided to remake the kernel using image2d_t to remove the border check, so far so good, It was not a hard conversion, but now the result I’m getting is different between the two kernels, It looks like the image2d_t filter just make the blur ignoring the border of the objects in the image.
First I though it was some problem i my calculations, but if I just do a ctrl + c, ctrl + v of the calculation part to the older buffer-based kernel it works like a charm, so what rest in my kernel to be a problem is the read_imagef to get the 3x3 neighborhood of the actual pixel.
I’m uploading an comparison imagem of the older kernel and the newer kernel, and the part that I get the neighborhood on the older kernel.

older buffer-based kernel:


    int p1, p2, p3, p4, p5, p6, p7, p8, p9;
    float4 b1, b2, b3, b4, b5, b6, b7, b8, b9, output;

    p1 = coord - width - 1;
    p2 = p1 + 1;
    p3 = p2 + 1;
    p4 = p1 + width;
    p5 = p4 + 1;
    p6 = p5 + 1;
    p7 = p4 + width;
    p8 = p7 + 1;
    p9 = p8 + 1;

    b1 = buffer[p1];
    b2 = buffer[p2];
    b3 = buffer[p3];
    b4 = buffer[p4];
    b5 = buffer[p5];
    b6 = buffer[p6];
    b7 = buffer[p7];
    b8 = buffer[p8];
    b9 = buffer[p9];

newer image2d_t-based kernel:


  const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST;

  float4 b1, b2, b3, b4, b5, b6, b7, b8, b9;

  b1 = read_imagef(input, sampler, (int2) (x - 1, y + 1));
  b2 = read_imagef(input, sampler, (int2) (x, y + 1));
  b3 = read_imagef(input, sampler, (int2) (x + 1, y + 1));
  b4 = read_imagef(input, sampler, (int2) (x - 1, y));
  b5 = read_imagef(input, sampler, (int2) (x, y));
  b6 = read_imagef(input, sampler, (int2) (x + 1, y));
  b7 = read_imagef(input, sampler, (int2) (x - 1, y - 1));
  b8 = read_imagef(input, sampler, (int2) (x, y - 1));
  b9 = read_imagef(input, sampler, (int2) (x + 1, y - 1));

Original image:
http://imagebin.org/165938

Older kernel result image:
http://imagebin.org/165939

Newer kernel result image:
http://imagebin.org/165940
ps: If you think it would help to see the full kernel code just tell me and I will see if I can post it here.

Ok, I’m so stupid… I found the problem, I simply forgot that read_imagef returns a value in the range [0.0… 1.0]… an simply 255 * read_imagef resolved the problem…

Thanks a lot for the help anyway!

hi!i am not familiar with this stuff,what is image 2d_t?hope to hear from you soon.thanks :slight_smile: