13.3.3 Convolutions Using the Accumulation Buffer

The convolution operation may be implemented by building the output
image in the accumulation buffer.
For each kernel entry ,
translate the input image by from its original position and
then accumulate the translated image using the command
`glAccum GL_ ACCUM, G[i][j](GL_ ACCUM, G[i][j])`. This translation can be performed
by

Here is an example of using the accumulation buffer to convolve using a
Sobel filter, commonly used to do edge detection. This filter is used to
find horizontal edges:

Since the accumulation buffer can only store values in the range (-1..1), first modify the kernel such that at any point in the computation the values do not exceed this range:

The operations needed to apply the filter are:

- Draw the input image.
`glAccum``GL_ LOAD`, 1/4(`GL_ LOAD`, 1/4)- Translate the input image left by one pixel.
`glAccum``GL_ ACCUM`, 2/4(`GL_ ACCUM`, 2/4)- Translate the input image left by one pixel.
`glAccum``GL_ ACCUM`, 1/4(`GL_ ACCUM`, 1/4)- Translate the input image right by two pixels and down by two pixels.
`glAccum``GL_ ACCUM`, -1/4(`GL_ ACCUM`, -1/4)- Translate the input image left by one pixel.
`glAccum``GL_ ACCUM`, -2/4(`GL_ ACCUM`, -2/4)- Translate the input image left by one pixel.
`glAccum``GL_ ACCUM`, -1/4(`GL_ ACCUM`, -1/4)- Return the results to the framebuffer
(
`glAccum`).`GL_ RETURN`, 4(`GL_ RETURN`, 4)

A general algorithm for the 2D convolution operation is:

Draw the input image for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { glAccum(GL_ACCUM, G[i][j]*scale); Move or redraw the input image to the left by 1 pixel } Move or redraw the input image to the right by width pixels Move or redraw the input image down by 1 pixel } glAccum(GL_RETURN, 1/scale);

float minPossible = 0, maxPossible = 1; for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { if (G[i][j] < 0) { minPossible += G[i][j]; } else { maxPossible += G[i][j]; } } } scale = 1.0 / ((-minPossible > maxPossible) ? -minPossible : maxPossible);Since the accumulation buffer has limited precision, more accurate results can be obtained by changing the order of the computation and computing

For separable kernels, convolution can be implemented using image translations and accumulations. A general algorithm is:

Draw the input image for (i = 0; i < width; i++) { glAccum(GL_ACCUM, Grow[i] * rowScale); Move or redraw the input image to the left 1 pixel } glAccum(GL_RETURN, 1 / rowScale); for (j = 0; j < height; j++) { glAccum(GL_ACCUM, Gcol[j] * colScale); Move or redraw the framebuffer image down by 1 pixel } glAccum(GL_RETURN, 1 / colScale);In this example, it is assumed that scales for the row and column filters have been determined in a similar fashion to the general two-dimensional filter, such that the accumulation buffer values will never go out of range.