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.
n neighborhood, the center pixel
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,
Select a single pixel.
Determine the pixel's neighborhood.
Apply a function to the values of the pixels in the neighborhood. This function must return a scalar.
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.
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
functions for performing convolution, and the toolbox provides the
imfilter function. See What Is Image Filtering in the Spatial Domain? for more information about
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 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.
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
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
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);
The following example uses
nlfilter to set each pixel to the
maximum value in its 3-by-3 neighborhood.
This example is only intended to illustrate the use of
nlfilter. For a faster way to perform this local maximum
I = imread("tire.tif");
f = @(x) max(x(:));
I2 = nlfilter(I,[3 3],f);
Each Output Pixel Set to Maximum Input Neighborhood Value