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
:
-
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. Neighborhoods are built by the
kernel
function. -
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 ofA
in a neighborhood defined byB
. -
correlate(A,B)
performs a discrete correlation ofA
by the kernelB
. This is the most general linear filter. -
convolve(A,B)
performs a discrete convolution ofA
by the kernelB
. This is the same as a discrete correlation ofA
byreverse_kernel(B)
.
LocalFilters
implements the following mathematical
morphology operations:
-
erode(A,B=3)
performs an erosion (local minimum) ofA
by the structuring elementB
; -
dilate(A,B=3)
performs a dilation (local maximum) ofA
by the structuring elementB
; -
localextrema(A,B=3)
yields the erosion and the dilation ofA
by the structuring elementB
; -
opening(A,B=3)
performs an erosion followed by a dilation ofA
by the structuring elementB
; -
closing(A,B=3)
performs a dilation followed by an erosion ofA
by the structuring elementB
; -
top_hat(A,B=3[,S])
performs a summit detection ofA
by the structuring elementB
(argumentS
may be optionally supplied to pre-smoothA
byS
); -
bottom_hat(A,B=3[,S])
performs a valley detection ofA
by the structuring elementB
(argumentS
may be optionally supplied to pre-smoothA
byS
).
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 centered 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 arrayA
withF
the range kernel for smoothing differences in values,G
the spatial kernel for smoothing differences in coordinates, andB
the neighborhood. Alternatively one can specify the range and spatial parametersbilateralfilter(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
When initial
is a function, A
and dst
must have the same indices; localfilter!
will throw a DimensionMismatch
if this is not the case.
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 arrayB
of Booleans is done with:localfilter!(dst, A, B, #= initial =# (; num = zero(eltype(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 ofA
byB
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 defaultfinal = identity
, does the job. -
Computing a local maximum (that is, a dilation in mathematical morphology terms) of array
A
with a kernelB
whose entries are Booleans can be done with:localfilter!(dst, A, B, #= initial =# typemin(eltype(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 theupdate
method to avoid branching.
To install the last official version, press the ]
key to enter Julia's Pkg
REPL mode
and type at the ... pkg>
prompt:
add LocalFilters
To use the last development version, type instead:
add https://github.com/emmt/LocalFilters.jl
The LocalFilters
package is pure Julia code and nothing has to be build.