Nonlinear filtering using lookup tables
J = bwlookup(I,lut)
performs a 2-by-2 or 3-by-3 nonlinear neighborhood filtering operation on binary or
J = bwlookup(
I and returns the results in output image
J. The neighborhood processing determines an integer index value used
to access values in lookup table
lut. The fetched
lut value becomes the pixel value in output image
J at the targeted position.
You optionally can perform the filtering
Construct the vector
lut such that the filtering operation places a
1 at the targeted pixel location in the input image only when all four pixels in the 2-by-2 neighborhood of BW are set to
lutfun = @(x)(sum(x(:))==4); lut = makelut(lutfun,2)
lut = 16×1 0 0 0 0 0 0 0 0 0 0 ⋮
Load a binary image.
BW1 = imread('text.png');
Perform 2-by-2 neighborhood processing with 16-element vector
BW2 = bwlookup(BW1,lut);
Show zoomed before and after images.
figure; h1 = subplot(1,2,1); imshow(BW1), axis off; title('Original Image') h2 = subplot(1,2,2); imshow(BW2); axis off; title('Eroded Image') % 16X zoom to see effects of erosion on text set(h1,'Ylim',[1 64],'Xlim',[1 64]); set(h2,'Ylim',[1 64],'Xlim',[1 64]);
Perform an erosion along the edges of a binary image using a 2-by-2 neighborhood, running the code on a graphics processing unit (GPU).
lut so it is true only when
all four 2-by-2 locations equal 1
lut = makelut('sum(x(:))==4',2);
Load binary image.
I1 = imread('text.png');
Perform 2-by-2 neighborhood processing with 16-element
vector LUT. To run the code on a GPU, create a
contain the image.
I2 = bwlookup(gpuArray(I1),lut);
Show zoomed before and after images.
figure; h1 = subplot(1,2,1); imshow(I1), axis off; title('I1') h2 = subplot(1,2,2); imshow(I2); axis off; title('I2') % 16X zoom to see effects of erosion on text set(h1,'Ylim',[.5 64.5]); set(h1,'Xlim',[.5 64.5]); set(h2,'Ylim',[.5 64.5]); set(h2,'Xlim',[.5 64.5]);
I— Input image
Input image transformed by nonlinear neighborhood filtering operation, specified as
either a grayscale or binary (logical) image. In the case of numeric values, non-zero
pixels are considered
true which is equivalent to logical 1.
To perform the filtering using a GPU, specify
I as a
gpuArray that contains a grayscale or binary image.
lut— Lookup table of output pixel values
Lookup table of output pixel values, specified as a 16- or 512-element
vector. The size of
lut determines which of the
two neighborhood operations is performed.
lut contains 16 data elements,
then the neighborhood matrix is 2-by-2.
lut contains 512 data elements,
then the neighborhood matrix is 3-by-3.
If you perform the filtering using a GPU, then you optionally can specify
lut as a
gpuArray that contains a 16- or 512-element vector.
J— Output image
Output image, returned as a grayscale or binary image whose distribution of pixel
values are determined by the content of the lookup table,
J is the same size as the input image
I and the same data type as
If the filtering is performed using a GPU, then
J is returned
gpuArray that contains a grayscale or
The first step in each iteration of the filtering operation performed by
bwlookup entails computing the
index into vector
lut based on the binary pixel pattern of the neighborhood matrix on
I. The value in
lut accessed at
lut(index), is inserted into output image
J at the targeted pixel location. This results in image
J being the same data type as vector
Since there is a 1-to-1 correspondence in targeted pixel locations, image
J is the same size as image
I. If the targeted
pixel location is on an edge of image
I and if any part of the 2-by-2 or
3-by-3 neighborhood matrix extends beyond the image edge, then these non-image locations are
padded with 0 in order to perform the filtering operation.
The following figures show the mapping from binary 0 and 1 patterns
in the neighborhood matrices to its binary representation. Adding
1 to the binary representation yields
is used to access
For 2-by-2 neighborhoods,
length(lut) is 16. There are four pixels in
each neighborhood, and two possible states for each pixel, so the total number of
permutations is 24 = 16.
To illustrate, this example shows how the pixel pattern in a 2-by-2 matrix determines
which entry in
lut is placed in the targeted pixel location.
Create random 16-element
lut vector containing
scurr = rng; % save current random number generator seed state rng('default') % always generate same set of random numbers lut = uint8( round( 255*rand(16,1) ) ) % generate lut rng(scurr); % restore
lut = 208 231 32 233 161 25 71 139 244 246 40 248 244 124 204 36
Create a 2-by-2 image and assume for this example that the targeted pixel location
I = [1 0; 0 1]
I = 1 0 0 1
By referring to the color coded mapping figure above, the binary representation for
this 2-by-2 neighborhood can be computed as shown in the code snippet below. The logical
I(1,1) corresponds to blue in the figure which maps to the Least
Significant Bit (LSB) at position 0 in the 4-bit binary representation
(,20= 1). The logical 1 at
I(2,2) is red
which maps to the Most Significant Bit (MSB) at position 3 in the 4-bit binary
representation (23= 8) .
% I(1,1): blue square; sets bit position 0 on right % I(2,2): red square; sets bit position 3 on left binNot = '1 0 0 1'; % binary representation of 2x2 neighborhood matrix X = bin2dec( binNot ); % convert from binary to decimal index = X + 1 % add 1 to compute index value for uint8 vector lut A11 = lut(index) % value at A(1,1)
index = 10 A11 = 246
The above calculation predicts that output image A should contain the value 246 at
A = bwlookup(I,lut) % perform filtering
A = 246 32 161 231
A(1,1) does in fact equal 246.
For 3-by-3 neighborhoods,
length(lut) is 512. There are nine pixels
in each neighborhood, and two possible states for each pixel, so the total number of
permutations is 29 = 512.
The process for computing the binary representation of 3-by-3 neighborhood processing is the same as for 2-by-2 neighborhoods.
Usage notes and limitations:
This function supports the generation of C code using MATLAB®
Note that if you choose the generic
MATLAB Host Computer target
platform, the function generates code that uses a precompiled, platform-specific
shared library. Use of a shared library preserves performance optimizations
but limits the target platforms for which code can be generated. For
more information, see Understand Code Generation with Image Processing Toolbox.
When generating code, specify an input image of class
This function fully supports GPU arrays. For more information, see Image Processing on a GPU.