Streaming aperture matrix processor: an algorithm, processing one or several {@link Matrix n-dimensional matrices} and returning one resulting matrix,where the value of every element of the resulting matrix depends on (and only on) the source elements in an aperture with the fixed shape "around" the same position. This class allows to optimize such type of processing in all cases, when the source matrix is not {@link Matrix#isDirectAccessible() direct accessible}, for example, if it is very large and created via {@link LargeMemoryModel}: this class automatically splits the source matrix into blocks which can fit in Java memory, downloads them into (directly accessible) matrices, created by {@link SimpleMemoryModel}, and processes them by the abstract method {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed}, overridden by the user. It is supposed that the type of matrix elements is one of primitive Java types (boolean, char, byte, short, int, long, float, double) and, so, represents an integer or a real number, according to comments to {@link PFixedArray#getLong(long)} and {@link PArray#getDouble(long)} methods.See below for more details.
First of all, let's define all terms and specify, what kind of algorithms can be performed by this class.
This class works with some {@link Matrix AlgART matrix} M, called the source matrix,some list of additional matrices
r = g (v0, v1, ..., vN−1, w0, w1, ..., wK−1).The processing function g is a parameter of this object and is specified by the concrete implementation of {@link #asProcessed(Class,Matrix,List,Pattern)} abstract method.As
This class declares two base methods:
Usually, this class really represents a streaming aperture processor, according the rules listed above. Such implementations of this class are called standard implementations. In standard implementations, it is enough to implement only the abstract method {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed}. But it is also allowed this class to represent any other algorithm, that converts M matrix and a set of
Note 1: the definition of the aperture above always supposes the pseudo-cyclic continuation of the source matrix, as described in {@link Matrix#pseudoCyclicIndex(long)} method. You can use{@link ContinuedStreamingApertureProcessor} (an example of non-standard implementation of this class)to change this behaviour to another continuation way.
Note 2: it is easy to see that all basic morphology, defined in {@link net.algart.matrices.morphology.Morphology} interface(in a simple case when the number of morphology pattern dimensions is equal to the number of the source matrix dimensions M. {@link Matrix#dimCount() dimCount()}, as this class requires), and all rank operations, defined in {@link net.algart.matrices.morphology.RankMorphology} interface,are streaming aperture processors, when they use standard pseudo-cyclic continuation of the matrix ( {@link net.algart.matrices.morphology.ContinuedMorphology} and{@link net.algart.matrices.morphology.ContinuedRankMorphology} work in other way).The basic morphology operations have no additional arguments Mk, as well as aperture sum rank operation. The percentile has 1 additional argument r, the rank has 1 additional argument v, the mean between percentiles and mean between values have 2 additional arguments. Most of filters, using in image processing, like the traditional linear filters, are also streaming aperture processors.
The main task, solved by this class, is a ready implementation of the second ( {@link #process(Matrix,Matrix,List,Pattern) process}) method on the base of the first method ( {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed}) for a case of the standard implementations of this class. Namely, the implementation, offered by this class, performs the necessary calculations via one or more calls of {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed} method,and it tries to optimize them by downloading parts of the source matrix M into quick accessible (i.e. {@link Matrix#isDirectAccessible() direct accessible}) temporary matrices, created by {@link SimpleMemoryModel}, and applying {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed}to them. The idea of this optimization is the following. Usually, calculating the result of {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed} for every aperture position xrequires accessing to N elements of the source matrix in the aperture. If the source matrix is not direct accessible, it can require essential time, especially if it is created by {@link LargeMemoryModel}. But if you are using this class, you can call {@link #process(Matrix,Matrix,List,Pattern) process} method and be almost sure,that it will call {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed} method with relativelylittle {@link Matrix#isDirectAccessible() direct accessible} temporary matrices.Such preloading usually increases performance in times even without any additional efforts; but if you want to provide maximal performance, you should check (in your implementation of {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed}), whether the passed src matrix is {@link Matrix#isDirectAccessible() direct accessible}, and, probably, provide a special optimized branch of the algorithm which works with the {@link DirectAccessible#javaArray() internal Java array}.
The amount of Java memory, which {@link #process(Matrix,Matrix,List,Pattern) process} methodmay spend for the optimization, is specified via {@link #maxTempBufferSize(PArray)} methodand usually corresponds to {@link net.algart.arrays.Arrays.SystemSettings#maxTempJavaMemory() Arrays.SystemSettings.maxTempJavaMemory()} limit.
This optimization is possible only in standard implementations, when your {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed} method really representssome streaming aperture processor. It means that it calculates and returns the results of some processing function g (not depending on the order of first N arguments), as described in the definition above. If these conditions are not fulfilled, the result of {@link #process(Matrix,Matrix,List,Pattern) process} method can be incorrect. For example,a typical possible error while implementing {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed}is using the value w of the element of the source matrix M at the position x. It can lead to error, because {@link #process(Matrix,Matrix,List,Pattern) process} method sometimes{@link Pattern#shift(net.algart.math.Point) shifts} the passed pattern and correspondingly{@link Matrices#asShifted(Matrix,long) shifts} the source matrix Mfor optimization goals — so, your {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed}method, while trying to access to the element of the source matrix M at the position x, will really read the value of another element instead. If you need to implement an algorithm, where the result element r at the position x depends also on the element of the source matrix at the same position x, you should pass the source matrix M also as one of additional Mk matrices. You can find an example of this technique in comments to {@link net.algart.matrices.morphology.RankProcessors#getPercentilePairProcessor(ArrayContext,net.algart.math.functions.Func,boolean,int) RankProcessors.getPercentilePairProcessor} method, where the usage of it for implementing the corresponding{@link net.algart.matrices.morphology.BasicRankMorphology} methods is described.
Note that this class does not try to preload necessary parts of the additional Mk matrices into Java memory (i.e. temporary matrices, created by {@link SimpleMemoryModel}). The reason is that the aperture size N is usually much greater than the number of additional matrices K (in most applications K is from 0 to 2..3), so it is not too important to optimize access to additional matrices. But, if necessary, you can do it yourself in your {@link #asProcessed(Class,Matrix,List,Pattern) asProcessed} method by good implementing{@link Array#getData(long,Object,int,int)} method in the "lazy" built-in array of the resulting matrix.To do this, you need to load the corresponding subarrays of the additional arguments into your own Java arrays by the corresponding {@link Array#getData(long,Object,int,int)} calls for all arrays
This package provides a set of methods for creating objects, extending this class for all basic {@link net.algart.matrices.morphology.RankMorphology rank operations}, in {@link net.algart.matrices.morphology.RankProcessors} class.
Warning: this class can process only patterns where
The classes, implementing this interface, are usually immutable and thread-safe: there are no ways to modify settings of the created instance. It is not guaranteed for any classes, but it is guaranteed for all instances created by the methods of the classes of this package.
AlgART Laboratory 2007–2014
@author Daniel Alievsky @version 1.2 @since JDK 1.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|