Neighborhoods, structuring elements, and kernels
In LocalFilters
, a filtering operation, say
dst = filter(A, B)
involves, at each index i
of a source array A
, the values A[i-k]
of A
for all indices k
of B
. In LocalFilters
, the following terminology is used for B
:
B
is called a neighborhood or a structuring element for mathematical morphology operations (see Section Non-linear morphological filters) if its purpose is to define the indices in the source relatively to a given index in the destination. Such neighborhoods can be hyper-rectangular Cartesian sliding windows represented by aRectangularBox
instance or regions with more complex shapes which are represented by arrays with offset axes and boolean entries (true
where entries are part of the neighborhood).B
is called a kernel when its values are combined by the filter with those of the source. This is typically the case of discrete convolutions and correlations.
Neighborhoods and structuring elements
A neighborhood (a.k.a. structuring element in mathematical morphology) is a central concept in LocalFilters
. The neighborhood defines which values are involved in a local operation for each output value of the filter. Neighborhoods are assumed to be shift invariant but may have any support shape and may have embedded weights (e.g., to implement local convolution).
Types of neighborhoods
From the user point of view, there are three kinds of neighborhoods:
Rectangular boxes are rectangular neighborhoods whose edges are aligned with the axes of array indices and which may be centered or have arbitrary offsets along the dimensions. These neighborhoods are represented by instances of
LocalFilters.RectangularBox
.Arbitrarily shaped neighborhoods are neighborhoods with arbitrary shape and offset. These neighborhoods are represented by instances of
LocalFilters.Kernel
with boolean element type. These neighborhoods are constructed from an array of booleans and an optional starting index.Kernels are neighborhoods whose elements are weights and which may have arbitrary offset. These neighborhoods are represented by instances of
LocalFilters.Kernel
with numerical element type. These neighborhoods are constructed from an array of weights and an optional starting index.
Syntaxes for neighborhoods
The default neighborhood is a centered hyper-rectangular Cartesian sliding window of width 3 in each of its dimensions. He Cartesian means that the edges of the neighborhood are algned with the array axes.
A scalar integer
w
yields a centered rectangular box of sizew
along all dimensions.w
must be at least equal to 1 and the geometrical center of the box is defined according to the conventions infftshift
.A tuple
t
of integers yields a centered rectangular box whose size ist[i]
along thei
-th dimension. All values oft
must be larger or equal to 1. Tip: Remember that you can usev...
to convert a vectorv
into a tuple.An array
A
yields aLocalFilters.Kernel
whose coefficients are the values ofA
and whose neighborhood is the centered bounding-box ofA
.A Cartesian region
R
(an instance ofCartesianIndices
) yields aLocalFilters.RectangularBox
which is a rectangular neighborhood whose support contains all relative positions withinfirst(R)
andlast(R)
.A rectangular box neighborhood created by calling
LocalFilters.RectangularBox
as:LocalFilters.RectangularBox(R) LocalFilters.RectangularBox(I1, I2) LocalFilters.RectangularBox(dims, offs) LocalFilters.RectangularBox(inds)
where
R
is an instance ofCartesianIndices
,I1
andI2
are twoCartesianIndex
specifying the first and last relative position within the neighborhood,dims
andoffs
are tuples of integers specifying the dimensions of the neighborhood and its offsets,inds
are unit ranges.Assuming
dim
is an integer, then:LocalFilters.RectangularBox{N}(dim)
yields an
N
-dimensional rectangular box of sizedim
along all dimensions and centered at the geometrical center of the box (with the same conventions asfftshift
).Similarly, assuming
i1
andi2
are integers, then:LocalFilters.RectangularBox{N}(i1:i2)
yields an
N
-dimensional rectangular box with index rangei1:i2
along all dimensions.
Methods on a neighborhood
The following statements make sense on a neighborhood B
:
eltype(B) -> element type of B
ndims(B) -> number of dimensions of B
length(B) -> number of elements in the bounding-box of B
size(B) -> size of the bounding-box of B along all dimensions
size(B,d) -> size of the bounding-box of B along d-th dimension
first(B) -> CartesianIndex of first position in the bounding-box
of B relative to its anchor
last(B) -> CartesianIndex of last position in the bounding-box
of B relative to its anchor
B[i] -> yields the kernel value of B at index i
Note that the index i
in B[i]
is assumed to be between first(B)
and last(B)
, for efficiency reasons this is not checked. The type returned by eltype(B)
is Bool
for a neighborhood which is just defined by its support (e.g. a LocalFilters.CenteredBox
or a LocalFilters.RectangularBox
), the element type of its kernel otherwise.
CartesianIndices(B)
yields the Cartesian indices of relative positions of the bounding-box of neighborhood B
.
If the argument B
which defines a neighborhood (see previous section) is not an instance of a type derived from LocalFilters.Neighborhood
, it may be explicitly converted by:
convert(LocalFilters.Neighborhood{N}, B)
with N
the number of dimensions of the target array.
Kernels
A LocalFilters.Kernel
can be used to define a weighted neighborhood (for weighted local average or for convolution) or a structuring element (for mathematical morphology). It is a rectangular array of coefficients over a, possibly off-centered, rectangular neighborhood. In general, it is sufficient to specify ::LocalFilters.Kernel{T,N}
in the signature of methods, with T
the type of the coefficients and N
the number of dimensions (the third parameter A
of the type is to fully qualify the type of the array of coefficients).
A kernel is built as:
B = LocalFilters.Kernel{T}(C, start=default_start(C))
where C
is the array of coefficients (which can be retrieved by coefs(B)
) and start
the initial CartesianIndex
for indexing the kernel (which can be retrieved by first_cartesian_index(B)
). The start
parameter let the caller choose an arbitrary origin for the kernel coefficients; when a filter is applied, the following mapping is assumed:
B[k] ≡ C[k + off]
where off = first_cartesian_index(C) - first_cartesian_index(B)
.
If start
is omitted, its value is set so that the origin (whose index is zero(CartesianIndex{N})
with N
the number of dimensions) of the kernel indices is at the geometric center of the array of coefficients (see LocalFilters.default_start
). Optional type parameter T
is to impose the type of the coefficients.
To convert the element type of the coefficients of an existing kernel, do:
LocalFilters.Kernel{T}(K)
which yields a kernel whose coefficients are those of the kernel K
converted to type T
.
It is also possible to convert instances of RectangularBox
into a kernel with boolean coefficients by calling:
LocalFilters.Kernel(B)
where B
is the neighborhood to convert into an instance of Kernel
.