Chapter 15. Sobel Edge Detection Filter

In this chapter, we use an OpenCL kernel to implement the Sobel edge detection filter as a simple example of how kernels work with images in OpenCL.

What Is a Sobel Edge Detection Filter?

The Sobel edge filter is a directional edge detector filter because it computes the image gradients along the x- and y-axes. These image gradients along the x- and y-axes (described as Gx and Gy) are computed by convolving the source image with the following convolution kernels:

image

The gradient magnitude is computed as

image

Implementing the Sobel Filter as an OpenCL Kernel

Listing 15.1 describes the OpenCL Sobel kernel. We use images because we can write a single kernel that can support different source image formats. In addition, images benefit from the presence of a texture cache and dedicated texture addressing hardware on GPUs.

Listing 15.1 An OpenCL Sobel Filter


//******************************************************************
//
// The operator uses two 3 x 3 kernels which are convolved with the
// original image to compute derivatives, one for horizontal changes
// & another for vertical.
//
// Gx, the horizontal derivative, is computed using the following
// 3 x 3 kernel:
//
//         [  -1     0    +1 ]
//  Gx =   [  -2     0    +2 ]
//         [  -1     0    +1 ]
//
// Gy, the vertical derivative, is computed using the following
// 3 x 3 kernel:
//
//         [  -1    -2    -1 ]
//  Gy =   [   0     0     0 ]
//         [  +1    +2    +1 ]
//
//
//******************************************************************

const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE |
                          CLK_FILTER_NEAREST;

kernel void
sobel_rgb(read_only image2d_t src, write_only image2d_t dst)
{
    int x = (int)get_global_id(0);
    int y = (int)get_global_id(1);

    if (x >= get_image_width(src) || y >= get_image_height(src))
        return;

    float4 p00 = read_imagef(src, sampler, (int2)(x - 1, y - 1));
    float4 p10 = read_imagef(src, sampler, (int2)(x,     y - 1));
    float4 p20 = read_imagef(src, sampler, (int2)(x + 1, y - 1));

    float4 p01 = read_imagef(src, sampler, (int2)(x - 1, y));
    float4 p21 = read_imagef(src, sampler, (int2)(x + 1, y));

    float4 p02 = read_imagef(src, sampler, (int2)(x - 1, y + 1));
    float4 p12 = read_imagef(src, sampler, (int2)(x,     y + 1));
    float4 p22 = read_imagef(src, sampler, (int2)(x + 1, y + 1));

    float3 gx = -p00.xyz + p20.xyz +
                 2.0f * (p21.xyz - p01.xyz)
                -p02.xyz + p22.xyz;

    float3 gy = -p00.xyz - p20.xyz +
                 2.0f * (p12.xyz - p10.xyz) +
                 p02.xyz + p22.xyz;

    float3  g = native_sqrt(gx * gx + gy * gy);

    // we could also approximate this as g = fabs(gx) + fabs(gy)
    write_imagef(dst, (int2)(x, y), (float4)(g.x, g.y, g.z, 1.0f));
 }


Figure 15.1 shows the input image passed to the Sobel filter on the left and the result of the OpenCL Sobel filter applied to this image on the right.

Figure 15.1 OpenCL Sobel kernel: input image and output image after applying the Sobel filter

image

The Sobel OpenCL kernel in Listing 15.1 produces an RGB image. We can also apply the Sobel filter and produce a grayscale image. Listing 15.2 describes the Sobel OpenCL kernel that produces a grayscale image.

Listing 15.2 An OpenCL Sobel Filter Producing a Grayscale Image


const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE |
                          CLK_FILTER_NEAREST;

kernel void
sobel_grayscale(read_only image2d_t src, write_only image2d_t dst)
{
    int x = (int)get_global_id(0);
    int y = (int)get_global_id(1);

    if (x >= get_image_width(src) || y >= get_image_height(src))
        return;

    float4 p00 = read_imagef(src, sampler, (int2)(x - 1, y - 1));
    float4 p10 = read_imagef(src, sampler, (int2)(x,     y - 1));
    float4 p20 = read_imagef(src, sampler, (int2)(x + 1, y - 1));

    float4 p01 = read_imagef(src, sampler, (int2)(x - 1, y));
    float4 p21 = read_imagef(src, sampler, (int2)(x + 1, y));

    float4 p02 = read_imagef(src, sampler, (int2)(x - 1, y + 1));
    float4 p12 = read_imagef(src, sampler, (int2)(x,     y + 1));
    float4 p22 = read_imagef(src, sampler, (int2)(x + 1, y + 1));

    float3 gx = -p00.xyz + p20.xyz +
                 2.0f * (p21.xyz - p01.xyz)
                -p02.xyz + p22.xyz;

    float3 gy = -p00.xyz - p20.xyz +
                 2.0f * (p12.xyz - p10.xyz) +
                 p02.xyz + p22.xyz;

    float gs_x = 0.3333f * (gx.x + gx.y + gx.z);
    float gs_y = 0.3333f * (gy.x + gy.y + gy.z);

    float g = native_sqrt(gs_x * gs_x + gs_y * gs_y);
    write_imagef(dst, (int2)(x, y), (float4)(g, g, g, 1.0f));
 }


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.65.65