Main Content

Sliding Neighborhood Operations

A sliding neighborhood operation is an operation that is performed a pixel at a time, with the value of any given pixel in the output image being determined by the application of an algorithm to the values of the corresponding input pixel's neighborhood. A pixel's neighborhood is some set of pixels, defined by their locations relative to that pixel, which is called the center pixel. The neighborhood is a rectangular block, and as you move from one element to the next in an image matrix, the neighborhood block slides in the same direction. (To operate on an image a block at a time, rather than a pixel at a time, use the distinct block processing function. See Distinct Block Processing for more information.)

The following figure shows the neighborhood blocks for some of the elements in a 6-by-5 matrix with 2-by-3 sliding blocks. The center pixel for each neighborhood is marked with a dot. For information about how the center pixel is determined, see Determine the Center Pixel.

Neighborhood Blocks in a 6-by-5 Matrix

Determine the Center Pixel

The center pixel is the actual pixel in the input image being processed by the operation. If the neighborhood has an odd number of rows and columns, the center pixel is actually in the center of the neighborhood. If one of the dimensions has even length, the center pixel is just to the left of center or just above center. For example, in a 2-by-2 neighborhood, the center pixel is the upper left one.

For any m-by-n neighborhood, the center pixel is

floor(([m n]+1)/2)

In the 2-by-3 block shown in the preceding figure, the center pixel is (1,2), or the pixel in the second column of the top row of the neighborhood.

General Algorithm of Sliding Neighborhood Operations

To perform a sliding neighborhood operation,

  1. Select a single pixel.

  2. Determine the pixel's neighborhood.

  3. Apply a function to the values of the pixels in the neighborhood. This function must return a scalar.

  4. Find the pixel in the output image whose position corresponds to that of the center pixel in the input image. Set this output pixel to the value returned by the function.

  5. Repeat steps 1 through 4 for each pixel in the input image.

For example, the function might be an averaging operation that sums the values of the neighborhood pixels and then divides the result by the number of pixels in the neighborhood. The result of this calculation is the value of the output pixel.

Border Padding Behavior in Sliding Neighborhood Operations

As the neighborhood block slides over the image, some of the pixels in a neighborhood might be missing, especially if the center pixel is on the border of the image. For example, if the center pixel is the pixel in the upper left corner of the image, the neighborhoods include pixels that are not part of the image.

To process these neighborhoods, sliding neighborhood operations pad the borders of the image, usually with 0's. In other words, these functions process the border pixels by assuming that the image is surrounded by additional rows and columns of 0's. These rows and columns do not become part of the output image and are used only as parts of the neighborhoods of the actual pixels in the image.

Implementing Linear and Nonlinear Filtering as Sliding Neighborhood Operations

You can use sliding neighborhood operations to implement many kinds of filtering operations. One example of a sliding neighbor operation is convolution, which is used to implement linear filtering. MATLAB® provides the conv and filter2 functions for performing convolution, and the toolbox provides the imfilter function. See What Is Image Filtering in the Spatial Domain? for more information about these functions.

In addition to convolution, there are many other filtering operations you can implement through sliding neighborhoods. Many of these operations are nonlinear in nature. For example, you can implement a sliding neighborhood operation where the value of an output pixel is equal to the standard deviation of the values of the pixels in the input pixel's neighborhood.

To implement a variety of sliding neighborhood operations, use the nlfilter function. nlfilter takes as input arguments an image, a neighborhood size, and a function that returns a scalar, and returns an image of the same size as the input image. nlfilter calculates the value of each pixel in the output image by passing the corresponding input pixel's neighborhood to the function.

Note

Many operations that nlfilter can implement run much faster if the computations are performed on matrix columns rather than rectangular neighborhoods. For information about this approach, see Use Column-wise Processing to Speed Up Sliding Neighborhood or Distinct Block Operations.

For example, this code computes each output pixel by taking the standard deviation of the values of the input pixel's 3-by-3 neighborhood (that is, the pixel itself and its eight contiguous neighbors).

I = imread("tire.tif");
I2 = nlfilter(I,[3 3],"std2");

You can also write code to implement a specific function, and then use this function with nlfilter. For example, this command processes the matrix I in 2-by-3 neighborhoods with a function called myfun.m. The syntax @myfun is an example of a function handle.

I2 = nlfilter(I,[2 3],@myfun);

If you prefer not to write code to implement a specific function, you can use an anonymous function instead. This example converts the image to class double because the square root function is not defined for the uint8 data type.

I = im2double(imread("tire.tif"));
f = @(x) sqrt(min(x(:)));
I2 = nlfilter(I,[2 2],f);

(For more information on function handles, see Create Function Handle. For more information about anonymous functions, see Anonymous Functions.)

The following example uses nlfilter to set each pixel to the maximum value in its 3-by-3 neighborhood.

Note

This example is only intended to illustrate the use of nlfilter. For a faster way to perform this local maximum operation, use imdilate.

I = imread("tire.tif");
f = @(x) max(x(:));
I2 = nlfilter(I,[3 3],f);
imshow(I);
figure, imshow(I2);

Each Output Pixel Set to Maximum Input Neighborhood Value