Skip to content

Multi-dimensional local filters (convolution, mathematical morphology, etc.) for Julia.

License

Notifications You must be signed in to change notification settings

emmt/LocalFilters.jl

Repository files navigation

LocalFilters.jl

Doc. Dev Doc. Stable License Build Status Build Status Coverage

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;

Available filters

LocalFilters provides a number of linear and non-linear filters. All methods have an in-place counterpart which can be called to avoid allocations.

Linear filters

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.

Mathematical morphology

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.

Other non-linear filters

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.

Build your own filters

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.

Installation

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.