Engee documentation

Filtering functions

Functions

imfilter([T], img, kernel, [border="replicate"], [alg]) --> imgfilt
imfilter([r], img, kernel, [border="replicate"], [alg]) --> imgfilt
imfilter(r, T, img, kernel, [border="replicate"], [alg]) --> imgfilt

Filter a one, two or multidimensional array img with a kernel by computing their correlation.

Extended help

Choices for r

Optionally, you can dispatch to different implementations by passing in a resource r as defined by the ComputationalResources package.

For example:

imfilter(ArrayFireLibs(), img, kernel)

would request that the computation be performed on the GPU using the ArrayFire libraries.

Choices for T

Optionally, you can control the element type of the output image by passing in a type T as the first argument.

Choices for img

You can specify a one, two, or multidimensional array defining your image.

Choices for kernel

The kernel[0, 0,..] parameter corresponds to the origin (zero displacement) of the kernel; you can use centered to place the origin at the array center, or use the OffsetArrays package to set kernel's indices manually. For example, to filter with a random centered 3x3 kernel, you could use either of the following:

kernel = centered(rand(3,3))
kernel = OffsetArray(rand(3,3), -1:1, -1:1)

The kernel parameter can be specified as an array or as a "factored kernel", a tuple (filt1, filt2, ...) of filters to apply along each axis of the image. In cases where you know your kernel is separable, this format can speed processing. Each of these should have the same dimensionality as the image itself, and be shaped in a manner that indicates the filtering axis, e.g., a 3x1 filter for filtering the first dimension and a 1x3 filter for filtering the second dimension. In two dimensions, any kernel passed as a single matrix is checked for separability; if you want to eliminate that check, pass the kernel as a single-element tuple, (kernel,).

Choices for border

At the image edge, border is used to specify the padding which will be used to extrapolate the image beyond its original bounds.

"replicate" (default)

The border pixels extend beyond the image boundaries.

   ╭────┏━━━━━━┓────╮
   │aaaa┃abcdef┃ffff│
   ╰────┗━━━━━━┛────╯

"circular"

The border pixels wrap around. For instance, indexing beyond the left border returns values starting from the right border.

   ╭────┏━━━━━━┓────╮
   │cdef┃abcdef┃abcd│
   ╰────┗━━━━━━┛────╯

"reflect"

The border pixels reflect relative to a position between pixels. That is, the border pixel is omitted when mirroring.

   ╭────┏━━━━━━┓────╮
   │dcba┃abcdef┃fedc│
   ╰────┗━━━━━━┛────╯

"symmetric"

The border pixels reflect relative to the edge itself.

   ╭────┏━━━━━━┓────╮
   │edcb┃abcdef┃edcb│
   ╰────┗━━━━━━┛────╯

Fill(m)

The border pixels are filled with a specified value .

   ╭────┏━━━━━━┓────╮
   │mmmm┃abcdef┃mmmm│
   ╰────┗━━━━━━┛────╯

Inner()

Indicate that edges are to be discarded in filtering, only the interior of the result is to be returned.

NA()

Choose filtering using "NA" (Not Available) boundary conditions. This is most appropriate for filters that have only positive weights, such as blurring filters.

See also: Pad, padarray, Inner, NA and NoPad

Choices for alg

The alg parameter allows you to choose the particular algorithm: Algorithm.FIR() (finite impulse response, aka traditional digital filtering) or Algorithm.FFT() (Fourier-based filtering). If no choice is specified, one will be chosen based on the size of the image and kernel in a way that strives to deliver good performance. Alternatively you can use a custom filter type, like KernelFactors.IIRGaussian.

imfilter!(imgfilt, img, kernel, [border="replicate"], [alg])
imfilter!(r, imgfilt, img, kernel, border::Pad)
imfilter!(r, imgfilt, img, kernel, border::NoPad, [inds=axes(imgfilt)])

Filter an array img with kernel kernel by computing their correlation, storing the result in imgfilt.

The indices of imgfilt determine the region over which the filtered image is computed---you can use this fact to select just a specific region of interest, although be aware that the input img might still get padded. Alteratively, explicitly provide the indices inds of imgfilt that you want to calculate, and use NoPad boundary conditions. In such cases, you are responsible for supplying appropriate padding: img must be indexable for all of the locations needed for calculating the output. This syntax is best-supported for FIR filtering; in particular, that that IIR filtering can lead to results that are inconsistent with respect to filtering the entire array.

See also: imfilter.

imgradients(img, kernelfun=KernelFactors.ando3, border="replicate") -> gimg1, gimg2, …​

Estimate the gradient of img in the direction of the first and second dimension at all points of the image, using a kernel specified by kernelfun.

Returns a tuple-of-arrays, (gimg1, gimg2, ...), one for each dimension of the input: gimg1 corresponds to the derivative with respect to the first dimension, gimg2 to the second, and so on.

Example

using Images, ImageFiltering, TestImages
img = testimage("mandrill")
imgr = imgradients(img, KernelFactors.sobel, "reflect")
mosaicview(imgr...)
mapwindow(f::F, img, window;
    border = "replicate",
    indices = default_imginds(img, window, border), callmode=:copy!)

Apply f to sliding windows of img, with window size or axes specified by window. For example,mapwindow(median!, img, window)returns an Array of values similar toimg(median-filtered, of course), whereasmapwindow(extrema, img, window)returns an Array of (min, max) tuples over a window of size window centered on each point ofimg`.

The function f receives a buffer buf` for the window of data surrounding the current point.

If window` is specified as a Dims-tuple (tuple-of-integers), then all the integers must be odd and the window is centered around the current image point.

For example, if window = (3,3), then f will receive an Array buf`corresponding to offsets (-1:1, -1:1) from theimgffor which this is currently being computed. Alternatively, window can be a tuple ofAbstractUnitRanges, in which case the specified ranges are used forbuf`; this allows you to use asymmetric windows if needed.

Restricting to a subimage

The indices keyword allows you to omit unnecessary computations, if you want to do things like mapwindow on a subimage, or a strided variant of mapwindow.

This call:

mapwindow(f, img, window, indices=(2:5, 1:2:7))

is more efficient than the equivalent:

mapwindow(f, img, window)[2:5, 1:2:7]

because it omits computation of the unused values.

Because the data in the buffer buf that is received by f is copied from img, and the buffer’s memory is reused, f should not return references to buf.

This code:

f = buf -> copy(buf) # as opposed to f = buf -> buf
mapwindow(f, img, window, indices=(2:5, 1:2:7))

would work as expected.

For functions that can only take AbstractVector inputs, you might have to first specialize default_shape:

f = v -> quantile(v, 0.75)
ImageFiltering.MapWindow.default_shape(::typeof(f)) = vec

and then mapwindow(f, img, (m, n)) should filter at the 75th quantile.

See also: imfilter.

mapwindow!(f, out, img, window; border="replicate", indices=axes(img))

Variant of mapwindow, with preallocated output. If out and img have overlapping memory regions, behaviour is undefined.

Kernel

Kernel is a module implementing filtering (correlation) kernels of full dimensionality. The following kernels are supported:

  • sobel

  • prewitt

  • ando3, ando4, and ando5

  • scharr

  • bickley

  • gaussian

  • DoG (Difference-of-Gaussian)

  • LoG (Laplacian-of-Gaussian)

  • Laplacian

  • gabor

  • moffat

See also: KernelFactors.

    diff1, diff2 = ando3()

Return correlation kernels for two-dimensional gradient compution using Ando’s "optimal" filters. The diff1 kernel computes the gradient along the y-axis (first dimension), and the diff2 kernel computes the gradient along the x-axis (second dimension). diff1 == rotr90(diff2)

    (diff,) = ando3(extended::NTuple{N,Bool}, d)

Return (a tuple of) the N-dimensional correlation kernel for gradient compution along the dimension d using Ando’s "optimal" filters of size 3. If extended[dim] is false, diff will have size 1 along that dimension.

Citation

S . Ando, "Consistent gradient operators," IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 22, no.3, pp. 252—​265, 2000. doi:10.1109/34.841757

    diff1, diff2 = ando4()

Return correlation kernels for two-dimensional gradient compution using Ando’s "optimal" filters. The diff1 kernel computes the gradient along the y-axis (first dimension), and the diff2 kernel computes the gradient along the x-axis (second dimension). diff1 == rotr90(diff2)

    (diff,) = ando4(extended::NTuple{N,Bool}, d)

Return (a tuple of) the N-dimensional correlation kernel for gradient compution along the dimension d using Ando’s "optimal" filters of size 4. If extended[dim] is false, diff will have size 1 along that dimension.

Citation

S . Ando, "Consistent gradient operators," IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 22, no.3, pp. 252—​265, 2000. doi:10.1109/34.841757

    diff1, diff2 = ando5()

Return correlation kernels for two-dimensional gradient compution using Ando’s "optimal" filters. The diff1 kernel computes the gradient along the y-axis (first dimension), and the diff2 kernel computes the gradient along the x-axis (second dimension). diff1 == rotr90(diff2)

    (diff,) = ando5(extended::NTuple{N,Bool}, d)

Return (a tuple of) the N-dimensional correlation kernel for gradient compution along the dimension d using Ando’s "optimal" filters of size 5. If extended[dim] is false, diff will have size 1 along that dimension.

Citation

S . Ando, "Consistent gradient operators," IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 22, no.3, pp. 252—​265, 2000. doi:10.1109/34.841757

    diff1, diff2 = bickley()

Return correlation kernels for two-dimensional gradient compution using the Bickley operator. The diff1 kernel computes the gradient along the y-axis (first dimension), and the diff2 kernel computes the gradient along the x-axis (second dimension). diff1 == rotr90(diff2)

    (diff,) = bickley(extended::NTuple{N,Bool}, d)

Return (a tuple of) the N-dimensional correlation kernel for gradient compution along the dimension d using the Bickley operator. If extended[dim] is false, diff will have size 1 along that dimension.

Citation

W . G. Bickley, "Finite difference formulae for the square lattice," The Quarterly Journal of Mechanics and Applied Mathematics, vol. 1, no. 1, pp. 35—​42, 1948. doi:10.1093/qjmam/1.1.35

DoG((σp1, σp2, ...), (σm1, σm2, ...), [l1, l2, ...]) -> k
DoG((σ1, σ2, ...))                                   -> k
DoG(σ::Real)                                         -> k

Construct a multidimensional difference-of-gaussian kernel k, equal to gaussian(σp, l)-gaussian(σm, l). When only a single σ is supplied, the default is to choose σp = σ, σm = √2 σ. Optionally provide the kernel length l; the default is to extend by two max(σp,σm) in each direction from the center. l must be odd.

If σ is provided as a single number, a symmetric 2d DoG kernel is returned.

gabor(size_x,size_y,σ,θ,λ,γ,ψ) -> (k_real,k_complex)

Returns a 2 Dimensional Complex Gabor kernel contained in a tuple where

  • size_x, size_y denote the size of the kernel

  • σ denotes the standard deviation of the Gaussian envelope

  • θ represents the orientation of the normal to the parallel stripes of a Gabor function

  • λ represents the wavelength of the sinusoidal factor

  • γ is the spatial aspect ratio, and specifies the ellipticity of the support of the Gabor function

  • ψ is the phase offset

#Citation N. Petkov and P. Kruizinga, “Computational models of visual neurons specialised in the detection of periodic and aperiodic oriented visual stimuli: bar and grating cells,” Biological Cybernetics, vol. 76, no. 2, pp. 83—​96, Feb. 1997. doi.org/10.1007/s004220050323

gaussian((σ1, σ2, ...), [(l1, l2, ...)]) -> g
gaussian(σ)                  -> g

Construct a multidimensional gaussian filter, with standard deviation σd along dimension d. Optionally provide the kernel length l, which must be a tuple of the same length.

If σ is supplied as a single number, a symmetric 2d kernel is constructed.

Laplacian((true,true,false,...))
Laplacian(dims, N)
Laplacian()

Laplacian kernel in N dimensions, taking derivatives along the directions marked as true in the supplied tuple. Alternatively, one can pass dims, a listing of the dimensions for differentiation. (However, this variant is not inferrable.)

Laplacian() is the 2d laplacian, equivalent to Laplaciantrue,true.

The kernel is represented as an opaque type, but you can use convert(AbstractArray, L) to convert it into array format.

LoG((σ1, σ2, ...)) -> k
LoG(σ)             -> k

Construct a Laplacian-of-Gaussian kernel k. σd is the gaussian width along dimension d. If σ is supplied as a single number, a symmetric 2d kernel is returned.

moffat(α, β, ls) -> k

Constructs a 2D, symmetric Moffat kernel k with core width, α, and power, β. Size of kernel defaults to 4 * full-width-half-max or as specified in ls. See this notebook for details.

Citation

Moffat, A. F. J. "A theoretical investigation of focal stellar images in the photographic emulsion and application to photographic photometry." Astronomy and Astrophysics 3 (1969): 455.

    diff1, diff2 = prewitt()

Return correlation kernels for two-dimensional gradient compution using the Prewitt operator. The diff1 kernel computes the gradient along the y-axis (first dimension), and the diff2 kernel computes the gradient along the x-axis (second dimension). diff1 == rotr90(diff2)

    (diff,) = prewitt(extended::NTuple{N,Bool}, d)

Return (a tuple of) the N-dimensional correlation kernel for gradient compution along the dimension d using the Prewitt operator. If extended[dim] is false, diff will have size 1 along that dimension.

Citation

J . M. Prewitt, "Object enhancement and extraction," Picture processing and Psychopictorics, vol. 10, no. 1, pp. 15—​19, 1970.

    diff1, diff2 = scharr()

Return correlation kernels for two-dimensional gradient compution using the Scharr operator. The diff1 kernel computes the gradient along the y-axis (first dimension), and the diff2 kernel computes the gradient along the x-axis (second dimension). diff1 == rotr90(diff2)

    (diff,) = scharr(extended::NTuple{N,Bool}, d)

Return (a tuple of) the N-dimensional correlation kernel for gradient compution along the dimension d using the Scharr operator. If extended[dim] is false, diff will have size 1 along that dimension.

Citation

H . Scharr and J. Weickert, "An anisotropic diffusion algorithm with optimized rotation invariance," Mustererkennung 2000, pp. 460—​467, 2000. doi:10.1007/978-3-642-59802-9_58

    diff1, diff2 = sobel()

Return correlation kernels for two-dimensional gradient compution using the Sobel operator. The diff1 kernel computes the gradient along the y-axis (first dimension), and the diff2 kernel computes the gradient along the x-axis (second dimension). diff1 == rotr90(diff2)

    (diff,) = sobel(extended::NTuple{N,Bool}, d)

Return (a tuple of) the N-dimensional correlation kernel for gradient compution along the dimension d using the Sobel operator. If extended[dim] is false, diff will have size 1 along that dimension.

Citation

P.-E. Danielsson and O. Seger, "Generalized and separable sobel operators," in Machine Vision for Three-Dimensional Scenes, H. Freeman, Ed. Academic Press, 1990, pp. 347—​379. doi:10.1016/b978-0-12-266722-0.50016-6

KernelFactors

KernelFactors is a module implementing separable filtering kernels, each stored in terms of their factors. The following kernels are supported:

  • box

  • sobel

  • prewitt

  • ando3, ando4, and ando5 (the latter in 2d only)

  • scharr

  • bickley

  • gaussian

  • IIRGaussian (approximate gaussian filtering, fast even for large σ)

See also: Kernel.

    kern1, kern2 = ando3()

Return a factored form of Ando’s "optimal" gradient filters for dimensions 1 and 2 of your image.

Citation

S . Ando, "Consistent gradient operators," IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 22, no.3, pp. 252—​265, 2000. doi:10.1109/34.841757

    kern = ando3(extended::NTuple{N,Bool}, d)

Return a factored Ando filter (size 3) for computing the gradient in N dimensions along axis d. If extended[dim] is false, kern will have size 1 along that dimension.

    kern1, kern2 = ando4()

Return separable approximations of Ando’s "optimal" 4x4 filters for dimensions 1 and 2 of your image.

Citation

S . Ando, "Consistent gradient operators," IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 22, no.3, pp. 252—​265, 2000. doi:10.1109/34.841757

    kern = ando4(extended::NTuple{N,Bool}, d)

Return a factored Ando filter (size 4) for computing the gradient in N dimensions along axis d. If extended[dim] is false, kern will have size 1 along that dimension.

Citation

S . Ando, "Consistent gradient operators," IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 22, no.3, pp. 252—​265, 2000. doi:10.1109/34.841757

    kern1, kern2 = ando5()

Return a separable approximations of Ando’s "optimal" 5x5 gradient filters for dimensions 1 and 2 of your image.

Citation

S . Ando, "Consistent gradient operators," IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 22, no.3, pp. 252—​265, 2000. doi:10.1109/34.841757

    kern = ando5(extended::NTuple{N,Bool}, d)

Return a factored Ando filter (size 5) for computing the gradient in N dimensions along axis d. If extended[dim] is false, kern will have size 1 along that dimension.

    kern1, kern2 = bickley()

Return factored Bickley filters for dimensions 1 and 2 of your image. Each is a 2-tuple of one-dimensional filters.

Citation

W . G. Bickley, "Finite difference formulae for the square lattice," The Quarterly Journal of Mechanics and Applied Mathematics, vol. 1, no. 1, pp. 35—​42, 1948. doi:10.1093/qjmam/1.1.35

    kern = bickley(extended::NTuple{N,Bool}, d)

Return a factored Bickley filter for computing the gradient in N dimensions along axis d. If extended[dim] is false, kern will have size 1 along that dimension.

gaussian(σ::Real, [l]) -> g

Construct a 1d gaussian kernel g with standard deviation σ, optionally providing the kernel length l. The default is to extend by two σ in each direction from the center. l must be odd.

gaussian((σ1, σ2, ...), [l]) -> (g1, g2, ...)

Construct a multidimensional gaussian filter as a product of single-dimension factors, with standard deviation σd along dimension d. Optionally provide the kernel length l, which must be a tuple of the same length.

IIRGaussian([T], σ; emit_warning::Bool=true)

Construct an infinite impulse response (IIR) approximation to a Gaussian of standard deviation σ. σ may either be a single real number or a tuple of numbers; in the latter case, a tuple of such filters will be created, each for filtering a different dimension of an array.

Optionally specify the type T for the filter coefficients; if not supplied, it will match σ (unless σ is not floating-point, in which case Float64 will be chosen).

Citation

I . T. Young, L. J. van Vliet, and M. van Ginkel, "Recursive Gabor Filtering". IEEE Trans. Sig. Proc., 50: 2798-2805 (2002).

    kern1, kern2 = prewitt()

Return factored Prewitt filters for dimensions 1 and 2 of your image. Each is a 2-tuple of one-dimensional filters.

Citation

J . M. Prewitt, "Object enhancement and extraction," Picture processing and Psychopictorics, vol. 10, no. 1, pp. 15—​19, 1970.

    kern = prewitt(extended::NTuple{N,Bool}, d)

Return a factored Prewitt filter for computing the gradient in N dimensions along axis d. If extended[dim] is false, kern will have size 1 along that dimension.

    kern1, kern2 = scharr()

Return factored Scharr filters for dimensions 1 and 2 of your image. Each is a 2-tuple of one-dimensional filters.

Citation

H . Scharr and J. Weickert, "An anisotropic diffusion algorithm with optimized rotation invariance," Mustererkennung 2000, pp. 460—​467, 2000. doi:10.1007/978-3-642-59802-9_58

    kern = scharr(extended::NTuple{N,Bool}, d)

Return a factored Scharr filter for computing the gradient in N dimensions along axis d. If extended[dim] is false, kern will have size 1 along that dimension.

    kern1, kern2 = sobel()

Return factored Sobel filters for dimensions 1 and 2 of a two-dimensional image. Each is a 2-tuple of one-dimensional filters.

Citation

P.-E. Danielsson and O. Seger, "Generalized and separable sobel operators," in Machine Vision for Three-Dimensional Scenes, H. Freeman, Ed. Academic Press, 1990, pp. 347—​379. doi:10.1016/b978-0-12-266722-0.50016-6

    kern = sobel(extended::NTuple{N,Bool}, d)

Return a factored Sobel filter for computing the gradient in N dimensions along axis d. If extended[dim] is false, kern will have size 1 along that dimension.

TriggsSdika(a, b, scale, M)

Defines a kernel for one-dimensional infinite impulse response (IIR) filtering. a is a "forward" filter, b a "backward" filter, M is a matrix for matching boundary conditions at the right edge, and scale is a constant scaling applied to each element at the conclusion of filtering.

Citation

B . Triggs and M. Sdika, "Boundary conditions for Young-van Vliet recursive filtering". IEEE Trans. on Sig. Proc. 54: 2365-2367 (2006).

TriggsSdika(ab, scale)

Create a symmetric Triggs-Sdika filter (with a = b = ab). M is calculated for you. Only length 3 filters are currently supported.

Kernel utilities

center(A, [r::RoundingMode=RoundDown])::Dims

Return the center coordinate of given array A. If size(A, k) is even, a rounding procedure will be applied with mode r.

Compatibility: OffsetArrays 1.9

This method requires at least OffsetArrays 1.9.

Examples

julia> A = reshape(collect(1:9), 3, 3)
3×3 Matrix{Int64}:
 1  4  7
 2  5  8
 3  6  9

julia> c = OffsetArrays.center(A)
(2, 2)

julia> A[c...]
5

julia> Ao = OffsetArray(A, -2, -2); # axes (-1:1, -1:1)

julia> c = OffsetArrays.center(Ao)
(0, 0)

julia> Ao[c...]
5

To shift the center coordinate of the given array to (0, 0, ...), you can use centered.

centered(A, cp=center(A)) -> Ao

Shift the center coordinate/point cp of array A to (0, 0, ..., 0). Internally, this is equivalent to OffsetArray(A, .-cp).

Compatibility: OffsetArrays 1.9

This method requires at least OffsetArrays 1.9.

Examples

julia> A = reshape(collect(1:9), 3, 3)
3×3 Matrix{Int64}:
 1  4  7
 2  5  8
 3  6  9

julia> Ao = OffsetArrays.centered(A); # axes (-1:1, -1:1)

julia> Ao[0, 0]
5

julia> Ao = OffsetArray(A, OffsetArrays.Origin(0)); # axes (0:2, 0:2)

julia> Aoo = OffsetArrays.centered(Ao); # axes (-1:1, -1:1)

julia> Aoo[0, 0]
5

Users are allowed to pass cp to change how "center point" is interpreted, but the meaning of the output array should be reinterpreted as well. For instance, if cp = map(last, axes(A)) then this function no longer shifts the center point but instead the bottom-right point to (0, 0, ..., 0). A commonly usage of cp is to change the rounding behavior when the array is of even size at some dimension:

julia> A = reshape(collect(1:4), 2, 2) # Ideally the center should be (1.5, 1.5) but OffsetArrays only support integer offsets
2×2 Matrix{Int64}:
 1  3
 2  4

julia> OffsetArrays.centered(A, OffsetArrays.center(A, RoundUp)) # set (2, 2) as the center point
2×2 OffsetArray(::Matrix{Int64}, -1:0, -1:0) with eltype Int64 with indices -1:0×-1:0:
 1  3
 2  4

julia> OffsetArrays.centered(A, OffsetArrays.center(A, RoundDown)) # set (1, 1) as the center point
2×2 OffsetArray(::Matrix{Int64}, 0:1, 0:1) with eltype Int64 with indices 0:1×0:1:
 1  3
 2  4

See also center.

kernelfactors(factors::Tuple)

Prepare a factored kernel for filtering. If passed a 2-tuple of vectors of lengths m and n, this will return a 2-tuple of ReshapedVectors that are effectively of sizes m×1 and 1×n. In general, each successive factor will be reshaped to extend along the corresponding dimension.

If passed a tuple of general arrays, it is assumed that each is shaped appropriately along its "leading" dimensions; the dimensionality of each is "extended" to N = length(factors), appending 1s to the size as needed.

reflect(kernel) --> reflectedkernel

Compute the pointwise reflection around 0, 0, …​ of the kernel kernel. Using imfilter with a reflectedkernel performs convolution, rather than correlation, with respect to the original kernel.

Boundaries and padding

BorderArray(inner::AbstractArray, border::AbstractBorder) <: AbstractArray

Construct a thin wrapper around the array inner, with given border. No data is copied in the constructor, instead border values are computed on the fly in getindex calls. Useful for stencil computations. See also padarray.

Examples

julia> using ImageFiltering

julia> arr = reshape(1:6, (2,3))
2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:
 1  3  5
 2  4  6

julia> BorderArray(arr, Pad((1,1)))
BorderArray{Int64,2,Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Pad{2}} with indices 0:3×0:4:
 1  1  3  5  5
 1  1  3  5  5
 2  2  4  6  6
 2  2  4  6  6

julia> BorderArray(arr, Fill(10, (2,1)))
BorderArray{Int64,2,Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Fill{Int64,2}} with indices -1:4×0:4:
 10  10  10  10  10
 10  10  10  10  10
 10   1   3   5  10
 10   2   4   6  10
 10  10  10  10  10
 10  10  10  10  10
struct Fill{T,N} <: AbstractBorder
    value::T
    lo::Dims{N}
    hi::Dims{N}
end

Fill is a type that designates a particular value which will be used to extrapolate pixels beyond the boundary of an image.

Output

The type Fill specifying the value with which the boundary of the image should be padded.

Details

When representing a two-dimensional spatial image filtering operation as a discrete convolution between an image and a filter, the results are undefined for pixels closer than pixels from the border of the image. To define the operation near and at the border, you need a scheme for extrapolating pixels beyond the edge. The Fill type allows you to specify a particular value which will be used in the extrapolation. For more elaborate extrapolation schemes, see Pad.

The type facilitates the padding of one, two, or multi-dimensional images.

You can specify a different amount of padding at the lower and upper borders of each dimension of the image (top, left, bottom, and right in two dimensions).

Example

To illustrate this, consider an image consisting of a row of six pixels which are specified alphabetically:

    ┏━━━━━━┓
    ┃abcdef┃
    ┗━━━━━━┛

Padding with a constant value m only on the left and right border looks like this:

╭────┏━━━━━━┓────╮
│mmmm┃abcdef┃mmmm│
╰────┗━━━━━━┛────╯

(Analogous consequences hold for the top and bottom border.)

See also: Pad, padarray, Inner and NoPad

Inner()
Inner(lo, hi)

Indicate that edges are to be discarded in filtering, only the interior of the result is to be returned.

Example:

imfilter(img, kernel, Inner())
NA(na=isnan)

Choose filtering using "NA" (Not Available) boundary conditions. This is most appropriate for filters that have only positive weights, such as blurring filters. Effectively, the output value is normalized in the following way:

          filtered array with Fill(0) boundary conditions
output =  -----------------------------------------------
          filtered 1     with Fill(0) boundary conditions

Array elements for which na returns true are also considered outside array boundaries.

NoPad()
NoPad(border)

Indicates that no padding should be applied to the input array, or that you have already pre-padded the input image. Passing a border object allows you to preserve "memory" of a border choice; it can be retrieved by indexing with [].

Example

The commands

np = NoPad(Pad(:replicate))
imfilter!(out, img, kernel, np)

run filtering directly, skipping any padding steps. Every entry of out must be computable using in-bounds operations on img and kernel.

    struct Pad{N} <: AbstractBorder
        style::Symbol
        lo::Dims{N}    # number to extend by on the lower edge for each dimension
        hi::Dims{N}    # number to extend by on the upper edge for each dimension
    end

Pad is a type that designates the form of padding which should be used to extrapolate pixels beyond the boundary of an image. Instances must set style, a Symbol specifying the boundary conditions of the image.

Output

The type Pad specifying how the boundary of an image should be padded.

Extended help

When representing a spatial two-dimensional image filtering operation as a discrete convolution between the image and a filter, the results are undefined for pixels closer than pixels from the border of the image. To define the operation near and at the border, one needs a scheme for extrapolating pixels beyond the edge. The Pad type allows one to specify the necessary extrapolation scheme.

The type facilitates the padding of one, two or multi-dimensional images.

You can specify a different amount of padding at the lower and upper borders of each dimension of the image (top, left, bottom and right in two dimensions).

Options

Some valid style options are described below. As an indicative example of each option the results of the padding are illustrated on an image consisting of a row of six pixels which are specified alphabetically:

        ┏━━━━━━┓
        ┃abcdef┃
        ┗━━━━━━┛

We show the effects of padding only on the left and right border, but analogous consequences hold for the top and bottom border.

:replicate (Default)

The border pixels extend beyond the image boundaries.

   ╭────┏━━━━━━┓────╮
   │aaaa┃abcdef┃ffff│
   ╰────┗━━━━━━┛────╯

See also: Fill, padarray, Inner and NoPad

:circular

The border pixels wrap around. For instance, indexing beyond the left border returns values starting from the right border.

   ╭────┏━━━━━━┓────╮
   │cdef┃abcdef┃abcd│
   ╰────┗━━━━━━┛────╯

See also: Fill, padarray, Inner and NoPad

:symmetric

The border pixels reflect relative to a position between pixels. That is, the border pixel is omitted when mirroring.

   ╭────┏━━━━━━┓────╮
   │edcb┃abcdef┃edcb│
   ╰────┗━━━━━━┛────╯

:reflect

The border pixels reflect relative to the edge itself.

   ╭────┏━━━━━━┓────╮
   │dcba┃abcdef┃fedc│
   ╰────┗━━━━━━┛────╯

See also: Fill,padarray, Inner and NoPad.

padarray([T], img, border)

Generate a padded image from an array img and a specification border of the boundary conditions and amount of padding to add.

Return a padded image. The function supports one, two or multi-dimensional images. You can specify the element type T of the output image.

See Pad and Fill for details.

Examples

Padding

The main syntax for Pad is (style, m, n, ...) or (style, (m, n)), where m pixels are added to dimension 1 (top and bottom), n pixels for dimension 2, and so forth.

Add 30 to left and right, 40 to top and bottom:

padarray(A, Pad(:replicate, 30, 40))
padarray(A, Pad(:circular, 30, 40))
padarray(A, Pad(:symmetric, 30, 40))
padarray(A, Pad(:reflect, 30, 40))

Add 30 above, 40 to left, 50 to bottom, 60 to right:

padarray(A, Pad(0, (30, 40), (50, 60)))
padarray(A, Pad(0, (30, 40), (50, 60)))

3D

padarray(A, Pad(:replicate, 1, 1, 1))
padarray(A, Fill(0, (1, 1, 1)))

Filling

The main syntax for Fill is (value, m, n) or (value, (m, n)) where the image is prepended by m pixels and appended by n pixels in each dimension.

Add 20 -1 values above, 30 to left, 40 to bottom, 50 to right:

padarray(A, Fill(-1, (20, 30), (40, 50)))

Find local extrema

findlocalmaxima(img; window=default_window(img), edges=true) -> Vector{CartesianIndex}

Returns the coordinates of elements whose value is larger than all of their immediate neighbors. edges is a Boolean specifying whether to include the first and last elements of each dimension, or a tuple-of-Bool specifying edge behavior for each dimension separately.

The default_window is 3 for each spatial dimension of img, and 1 otherwise, implying that maxima are detected over nearest-neighbors in each spatial "slice" by default.

findlocalminima(img; window=default_window(img), edges=true) -> Vector{CartesianIndex}

Like findlocalmaxima, but returns the coordinates of the smallest elements.

Algorithms

Filter using a direct algorithm

Filter using the Fast Fourier Transform

Filter with an Infinite Impulse Response filter

Filter with a cascade of mixed types (IIR, FIR)

Solvers for predefined models

This submodule provides predefined image-related models and its solvers that can be reused by many image processing tasks.

solve_ROF_PD!(out, buffer, img, λ, num_iters)

The in-place version of solve_ROF_PD.

It is not uncommon to use ROF solver in a higher-level loop, in which case it makes sense to preallocate the output and intermediate arrays to make it faster.

!!! note "Buffer" The content and meaning of buffer might change without any notice if the internal implementation is changed. Use preallocate_solve_ROF_PD helper function to avoid potential changes.

Examples

using ImageFiltering.Models: preallocate_solve_ROF_PD

out = similar(img)
buffer = preallocate_solve_ROF_PD(img)
solve_ROF_PD!(out, buffer, img, 0.2, 30)
solve_ROF_PD([T], img::AbstractArray, λ; kwargs...)

Return a smoothed version of img, using Rudin-Osher-Fatemi (ROF) filtering, more commonly known as Total Variation (TV) denoising or TV regularization. This algorithm is based on the primal-dual method.

This function applies to generic N-dimensional colorant array and is also CUDA-compatible. See also solve_ROF_PD! for the in-place version.

Arguments

  • T: the output element type. By default it is float32(eltype(img)).

  • img: the input image, usually a noisy image.

  • λ: the regularization coefficient. Larger λ results in more smoothing.

Parameters

  • num_iters::Int: The number of iterations before stopping.

Examples

using ImageFiltering
using ImageFiltering.Models: solve_ROF_PD
using ImageQualityIndexes
using TestImages

img_ori = float.(testimage("cameraman"))
img_noisy = img_ori .+ 0.1 .* randn(size(img_ori))
assess_psnr(img_noisy, img_ori) # ~20 dB

img_smoothed = solve_ROF_PD(img_noisy, 0.015, 50)
assess_psnr(img_smoothed, img_ori) # ~27 dB

# larger λ produces over-smoothed result
img_smoothed = solve_ROF_PD(img_noisy, 5, 50)
assess_psnr(img_smoothed, img_ori) # ~21 dB

Extended help

Mathematically, this function solves the following ROF model using the primal-dual method:

References

  • [1] Chambolle, A. (2004). "An algorithm for total variation minimization and applications". Journal of Mathematical Imaging and Vision. 20: 89—​97

  • [2] Wikipedia: Total Variation Denoising

Internal machinery

ReshapedOneD{N,Npre}(data)

Return an object of dimensionality N, where data must have dimensionality 1. The axes are 0:0 for the first Npre dimensions, have the axes of data for dimension Npre+1, and are 0:0 for the remaining dimensions.

data must support eltype and ndims, but does not have to be an AbstractArray.

ReshapedOneDs allow one to specify a "filtering dimension" for a 1-dimensional filter.