Julia package LocalFilters
implements
multi-dimensional local filters such as discrete convolution or correlation,
local mean, mathematical morphology, etc., and provides support to build custom
local filters.
The Reference Manual provides more exhaustive documentation.
This page summarizes the principles and the features of LocalFilters
. This
document is structured as follows:
Available filters lists ready to use filters.
Neighborhoods describes the concept of neighborhoods, also known as sliding windows in image processing or structuring element in mathematical morphology.
Build your own filters explains how to implement custom local filters.
Installation gives instructions to install the package.
Packages with overlapping functionalities:
ImageFiltering for local filters on multidimensional arrays (not just images), also implement various boundary conditions;
ImageMorphology for fast morphological operations with separable structuring elements;
LocalFilters
provides a number of linear and non-linear filters. All methods
have an in-place counterpart which can be called to avoid allocations.
LocalFilters
provides the following linear filters:
localmean(A,B=3)
performs a local averaging of A
in a neighborhood defined
by B
.
correlate(A,B)
performs a discrete correlation of A
by the kernel B
.
This is the most general linear filter.
convolve(A,B)
performs a discrete convolution of A
by the kernel B
.
This is the same as a discrete correlation of A
by the symmetrical of B
.
LocalFilters
implements the following mathematical
morphology operations:
erode(A,B=3)
performs an erosion (local minimum) of A
by the structuring
element B
;
dilate(A,B=3)
performs a dilation (local maximum) of A
by the structuring
element B
;
localextrema(A,B=3)
yields the erosion and the dilation of A
by the
structuring element B
;
opening(A,B=3)
performs an erosion followed by a dilation of A
by the
structuring element B
;
closing(A,B=3)
performs a dilation followed by an erosion of A
by the
structuring element B
;
top_hat(A,B=3[,S])
performs a summit detection of A
by the structuring
element B
(argument S
may be optionally supplied to pre-smooth A
by
S
);
bottom_hat(A,B=3[,S])
performs a valley detection of A
by the structuring
element B
(argument S
may be optionally supplied to pre-smooth A
by
S
).
In mathematical morphology, the structuring element B
defines the local
neighborhood of each index in the source array. It can be a sliding
hyper-rectangular Cartesian window or an array of Booleans to define a more
complex neighborhood shape. If B
is a single odd integer (as it is by
default), the structuring element is assumed to be a sliding window of size B
along every dimension of A
.
LocalFilters
provides an instance of the bilateral
filter:
bilateralfilter(A,F,G,B)
performs a bilateral filtering of array A
with
F
the range kernel for smoothing differences in values, G
the spatial
kernel for smoothing differences in coordinates, and B
the neighborhood.
Alternatively one can specify the range and spatial parameters
bilateralfilter(A,σr,σs,B=2*round(Int,3σs)+1)
for using Gaussian kernels
with standard deviations σr
and σs
.In LocalFilters
, a local filtering operation, say dst = filter(A, B)
with
A
the source of the operation and B
the neighborhood or the kernel
associated with the filter, is implemented by the following pseudo-code:
for i ∈ indices(dst)
v = initial isa Function ? initial(A[i]) : initial
for j ∈ indices(A) ∩ (indices(B) + i)
v = update(v, A[j], B[j-i])
end
dst[i] = final(v)
end
where indices(A)
denotes the set of indices of A
while indices(B) + i
denotes the set of indices j
such that j - i ∈ indices(B)
with indices(B)
the set of indices of B
. In other words, j ∈ indices(A) ∩ (indices(B) + i)
means all indices j
such that j ∈ indices(A)
and j - i ∈ indices(B)
,
hence A[j]
and B[j-i]
are in-bounds.In LocalFilters
, indices i
and j
are Cartesian indices for multi-dimensional arrays, thus indices(A)
is the
analogous of CartesianIndices(A)
in Julia in that case. For vectors, indices
i
and j
are linear indices.
The behavior of the filter is completely determined by the neighborhood or
kernel B
, by the type of the state variable v
initialized by initial
for
each entry of the destination, and by the methods update
and final
.
Such a filter can be applied by calling localfilter!
as:
localfilter!(dst, A, B, initial, update, final = identity) -> dst
As shown by the following examples, this simple scheme allows the implementation of a variety of linear and non-linear local filters:
Implementing a local average of A
in a neighborhood defined by an array
B
of Booleans is done with:
localfilter!(dst, A, B,
#= initial =# (; num = zero(a), den = 0),
#= update =# (v,a,b) -> ifelse(b, (; num = v.num + a, den = v.den + 1), v),
#= final =# (v) -> v.num / v.den)
Assuming T = eltype(dst)
is a suitable element type for the result, a
discrete correlation of A
by B
can be implemented with:
localfilter!(dst, A, B,
#= initial =# zero(T),
#= update =# (v,a,b) -> v + a*b)
There are no needs to specify the final
method here, as the default
final = identity
, does the job.
Computing a local maximum (that is, a dilation in mathematical morphology
terms) of array A
with a kernel B
whose entries are Booleans can be done
with:
localfilter!(dst, A, B,
#= initial =# typemin(a),
#= update =# (v,a,b) -> ((b & (v < a)) ? a : v))
As in the above example, there are no needs to specify the final
method
here. Note the use of a bitwise &
instead of a &&
in the update
method
to avoid branching.
To install the last official version, press the ]
key to enter Julia's Pkg
REPL mode and type:
add LocalFilters
at the ... pkg>
prompt.
The LocalFilters
package is pure Julia code and nothing has to be build.