- Bump compatibility for
TypeUtilsversion 2.
-
New methods
localmap(f, A, B)andlocalmap!(f, dst, A, B)yield the result of applying the functionfto the values ofAtaken in a neighborhood defined byBaround each position inAforlocalmapor indstforlocalmap!. -
Methods to locally reduce along given dimensions with an associative operator and using the van Herk-Gil-Werman algorithm have been renamed
localreduceandlocalreduce!. Callinglocalfilterandlocalfilter!for that purpose is deprecated. -
LocalFilters.ball(DimS{N}, r)now yields a centeredN-dimensional ball where values are set according to whether the distance to the center is≤ r. Compared to the previous versions, add1//2torto get a similar shape. The algorithm is faster and has been fixed forN > 2. The result is identical whetherris integer or floating-point. -
In
localfilter!, argumentinitialmay be a function to compute the state variable from the value of the source array at the current destination index. This imposes that the source and destination arrays have the same axes. This fixes issue#3. -
In
localfilter, an optional first argument,T, may be specified to provide the element type of the result. -
Morphological methods have a
slowkeyword (falseby default) to force not using the the van Herk-Gil-Werman algorithm. -
localmeanandlocalmean!accept anullkeyword to specify the value of the result when the sum of weights in a neighborhood is zero. -
Macro
@publicto declare public methods even though they are not exported. This concept was introduced in Julia 1.11, for older Julia versions, nothing change. -
The algorithm to infer the result type is now based on Julia's arithmetic rules and can cope with arguments that have units.
-
Non-exported public aliases
LocalFilters.Kernel{N}andLocalFilters.Window{N}for union of types suitable to defineN-dimensional kernels or windows inLocalFilters. A kernel is an array of weights implementing a local filter or an array of Booleans representing a local neighborhood. A window is an array of Booleans representing a local neighborhood. As an optimization, a box is an hyper-rectangular neighborhood with axes aligned with the Cartesian axes. Thus, a window whose values are all true is also a box and a kernel with Boolean values is also a window. The functionkernel(Dims{N},B)yields anN-dimensional array for anyB::LocalFilters.Kernel{N}, with Boolean values for anyB::LocalFilters.Window{N}. -
Non-exported public type
LocalFilters.Box{N}is now an alias to an efficient type to representN-dimensional boxes, that is uniformly true windows or hyper-rectangular neighborhoods. Currently, instances of this type are fast uniformly true arrays with offset axes from theStructuredArrayspackage andLocalFilters.Box{N}is justFastUniformArray{Bool,N,true}. -
In local filtering operations, small integers arguments are automatically promoted to a wider integer type to avoid overflows. This is similar to what is done by base reduction methods such as
sumandprod. -
Exported method
B = reverse_kernel(args...)yields a reversed kernel such that correlation byBis identical to convolution byA = kernel(args...)and conversely. -
Building a structuring element with
B = strel(T, args...)acceptsargs...likekernel. -
Constants for filter ordering follow more general naming rules:
FORWARD_FILTERandREVERSE_FILTERinstead ofForwardFilterandReverseFilter. -
Filter ordering is always specified by the keyword
orderand isFORWARD_FILTERby default.
Version 2 of LocalFilters better integrates in the Julia ecosystem as fewer custom types
are introduced:
-
To represent hyper-rectangular Cartesian sliding windows, former type
RectangularBoxhas been replaced byCartesianIndices. -
Kernels with values or neighborhoods with more complex shape than hyper-rectangular Cartesian sliding windows are all represented by abstract arrays (with boolean entries to define a neighborhood). The former type
LocalFilters.Kernelis no longer provided. To account for offsets in the indexing, it is recommended to use theOffsetArrayspackage. The methodLocalFilters.centered(B)can be called to yield a kernel or a neighborhood whose index ranges are approximately centered. This method is not exported to avoid conflicts (for instance, it has a slightly different semantic inOffsetArrays).
Version 2 of LocalFilters provides more general, more consistent, and better optimized
methods:
-
Most filtering operations take an optional ordering argument
ordright before the argument, sayB, specifying the kernel or the neighborhood. IfordisForwardFilter,Bis indexed as in discrete correlations; otherwise, ifordisReverseFilter,Bis indexed as in discrete convolutions. The default ordering isForwardFilteras this is the most natural for many filters (except discrete convolutions of course) and as it yields faster code. For symmetric kernels and neighborhoods, the ordering has no incidence on the result. InLocalFiltersversion 1, indexing as in discrete convolutions was the only rule. -
The API of
localfilters!have changed a bit, the syntax islocalfilters!(dst,A,ord=ForwardFilter,B,initial,update,final=identity)withdstthe destination,Athe source,ordthe direction of the filter,Bthe kernel or neighborhood of the filter,initialthe value of the initial state variable,updatea method to update the state variable, andfinala method to yield the result to store in the destinationdstgiven the value of the state variable at the end of visiting the neighborhood. -
Constructor
LocalFilters.Indicesand helper methodLocalFilters.localindicesmay be used as an alternative tolocalfilters!to build custom filters. -
In all filters, a simple neighborhood that is a hyper-rectangular Cartesian sliding window can be specified in many different ways. Such a neighborhood is represented by an instance of
CartesianIndiceswith unit step ranges. MethodLocalFilters.kernel(Dims{N},args...)can be called to build such aN-dimensional neighborhood from argument(s)args.... -
Non-exported
LocalFilters.ballmethod is now type stable. CallLocalFilters.ball(Dims{N},r)instead ofLocalFilters.ball(N,r). -
The
strelmethod uses uniform arrays from packageStructuredArraysto represent structuring elements with the same value for all valid indices. -
In out-of-place filters, the destination array needs not be of the same size as the source array. The local filtering operation is applied for all indices of the destination, using boundary conditions to extract the corresponding value in the source array. Currently only flat boundary conditions are implemented but this may change in the future.
If the high level API was used, there should be almost no changes, except for
non-symmetric kernels or neighborhoods for which ReverseFilter ordering must be
specified to mimic the former behavior.
At a lower level, the following changes should be done:
-
Non-exported union
LocalFilters.IndexIntervalhas been replaced byLocalFilters.Axisto represent the type of any argument that can be used to define a sliding window axis: an integer length or an integer-valued index range. -
Non-exported method
LocalFilters.ismmboxhas been replaced byLocalFilters.is_morpho_math_box. -
Non-exported method
LocalFilters.cartesian_regionhas been replaced by the more general and better designed exported methodkernel. -
Replace
Neighborhood{N}(args...)bykernel(Dims{N}, args...)andNeighborhood{N}orRectangularBox{N}byLocalFilters.Box{N}. -
Replace
LocalFilters.KernelbyOffsetArrays.OffsetArray. -
Update the arguments of
localfilters!:initialis no longer a method but the initial state value,updatehas the same semantics, andfinaljust yields the result of the local filter given the last state value. By default,finalisidentity. -
Replace
LocalFilters.ball(N,r)byLocalFilters.ball(Dims{N},r)which is type-stable.
-
Fix an important performance bug related to anonymous functions. Methods
localmean!andconvolve!are about 60 times faster! -
The documentation has been largely revised and on-line documentation is generated by
Documenter.jland hosted on https://emmt.github.io/LocalFilters.jl/.
- A default window of width
2*round(Int,3σ)+1for the spatial filter in the bilateral filter if a Gaussian spatial filter of standard deviationσis chosen.
-
Scalar and array element type restrictions have been relaxed for most filter methods. This is to let users apply these methods to non-standard types.
-
Some optimizations.
-
Syntax
Kernel(T,G,B)has been deprecated in favor ofKernel{T}(G,B). -
Rename unexported methods
initialindex,finalindex,defaultstart,cartesianregion,convertcoefs, andstrictfloorrespectively asfirst_cartesian_indexandlast_cartesian_index,default_start,cartesianregion,convert_coefs, andstrictfloor.
- Drop compatibility with Julia versions < 1.0;
Compatonly needed to run tests.
-
Compatibility with Julia 0.6 to 1.1
-
Add fast separable filters with the van Herk-Gil-Werman algorithm. This algorithm is applied whenever possible (for
RectangularBox, or flatKernelwhose elements are all valid). -
New
strelfunction to build structuring elements. -
The type of the result of operations like local mean and convolution is more consistent (e.g., local mean yields a floating-point type result). Rounding to the nearest integer is automatically used when the floating-point result of an operation is stored into a array of integers.
-
Constructors for
Kernelbasically takes two arguments: the array of coefficients, sayA, and the initialCartesianIndexfor indexing the kernel. This simplify the interface, notably when the array of coefficientsAhas not 1-based indexing. -
Compatibility with Julia versions 0.6, 0.7 and 1.0 without loss of performances. This has been achieved thanks to the new
cartesianregion()method (see below). -
The method
cartesianregion()is provided to return either aCartesianIndices{N}or aCartesianRange{CartesianIndex{N}}(whichever is the most efficient depending on Julia version) to loop over theN-dimensional indices of anything whose type belongs toCartesianRegion{N}. TypeCartesianRegion{N}is an union of the types of anything suitable to define a Cartesian region of indices. -
Methods
initialindexandfinalindexare provided to retrieve the first and lastCartesianIndexfor indexing their argument. -
Types
CartesianBoxandCenteredBoxhave been merged in a single type namedRectangularBox(to avoid conflicts with the CartesianBoxes package). Hence,Neighborhoodhas two concrete subtypes:RectangularBoxandKernel. -
Method
anchorhas been removed because its result depends on the indexing of the embedded array of kernel coefficients. -
Add bilateral filter.