All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.algart.matrices.ApertureProcessor Maven / Gradle / Ivy

Go to download

Open-source Java libraries, supporting generalized smart arrays and matrices with elements of any types, including a wide set of 2D-, 3D- and multidimensional image processing and other algorithms, working with arrays and matrices.

There is a newer version: 1.4.23
Show newest version
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2007-2024 Daniel Alievsky, AlgART Laboratory (http://algart.net)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package net.algart.matrices;

import net.algart.arrays.Matrix;
import net.algart.math.IRectangularArea;

import java.util.Map;

/**
 * 

Abstract aperture matrix processor: an algorithm, processing a group of * {@link Matrix n-dimensional matrices} and returning a group of resulting matrices, * where the value of every element of every resulting matrix depends only on * the elements of the source matrices in some aperture "around" the same position. * This aperture should be a subset of some rectangular area ({@link IRectangularArea}); * this area (possibly different for different source matrices) is called a dependence aperture * of the aperture processor. All matrices must have same dimensions. * This interface is used, for example, together with {@link TiledApertureProcessorFactory} class.

* *

Below is more precise formal definition of the aperture matrix processors. * All classes, implementing this interface, should comply this definition.

* *

The main method of this interface, {@link #process(Map, Map) process}, * works with some group of {@link Matrix AlgART matrices} Mi, iQ, * called the arguments or source matrices, * and a group of another AlgART matrices M'j, jR, * called the results or resulting matrices. * Here the indexes i and j (elements of the index sets Q and R) * can be objects of any nature and should be represented by Java objects of the generic type K — * the generic argument of this interface (for example, Integer or String). * The indexes of arguments and results are also called their keys. * The group of the source arguments and the group of results are represented by java.util.Map, * more precisely, by a generic type java.util.Map<K, {@link Matrix}<?>>:

* *
 *     {@link #process(Map, Map)
 * process}(java.util.Map<K, {@link Matrix}<?>> dest, java.util.Map<K, {@link Matrix}<?>> src)
 * 
* *

The group destof resulting matrices M'j can be passed to * {@link #process(Map, Map) process} method, or can be formed by this method dynamically * (an empty map dest can be passed in this case), * or it is possible that a part of resulting matrices is passed in dest while calling the method * and other resulting matrices are added to dest map by the method itself.

* *

In all comments, the designations M'j * and R means the group (dest) and the index set * (dest.keySet()) of resulting matrices * after the call of {@link #process(Map, Map) process} method.

* *

Some of the resulting matrices M'j (but not the source arguments), * passed to {@link #process(Map, Map) process} method, can be {@code null} — * it means that {@link #process(Map, Map) process} method must create them itself. * (And it also may create some additional matrices M'j, not contained * in dest while calling this method.) * All non-null resulting matrices M'j, passed to the method in dest * argument, must be updatable, i.e. their {@link Matrix#array() built-in arrays} * must implement {@link net.algart.arrays.UpdatableArray} interface. * The dimensions of all source and non-null resulting matrices must be the same: * {@link Matrix#dimEquals(Matrix)} method must return true for any pair of them. * The sets of indexes of arguments Q and results R, as well as the dimensions of matrices, * may vary for different calls of {@link #process(Map, Map) process} method. * (Even the number of dimensions n may vary, but it is a rarer situation.) * Degenerated cases Q=∅ (no arguments) and R=∅ (no results) are allowed. * If Q=∅ (no matrices are passed in src map) and * the dest map, passed to {@link #process(Map, Map) process} method, * either is empty or contains only {@code null} matrices, * then {@link #process(Map, Map) process} method usually does nothing. * See {@link #process(Map, Map) comments to that method} for additional details.

* *

For each source argument Mi this aperture processor defines * the corresponding dependence aperture Ai: a rectangular set of * integer points, represented by {@link IRectangularArea} class and returned by * {@link #dependenceAperture(Object) dependenceAperture(i)} method. * This aperture can depend only on the argument index i and cannot vary for different calls * of {@link #dependenceAperture(Object) dependenceAperture} method for the same processor.

* *

The goal of the main {@link #process(Map, Map) process} method is * to fill elements of the resulting matrices M'j * (usually all elements of all M'j, jR) on the base * of the elements of the source matrices Mi. * There should be a guarantee, that every element of any resulting n-dimensional matrix * M'j with coordinates * x = (x0, x1, ..., xn−1) * can depend only on elements of each source matrix Mi with coordinates

* *
* x+a = * x0+a0, * x1+a1, ..., * xn−1+an−1, *
* *

where * a = (a0, a1, ..., an−1) * is one of points belonging to the corresponding dependence aperture * Ai={@link #dependenceAperture(Object) dependenceAperture(i)}. * Please draw attention that we use plus sing + in this definition, instead of more traditional minus sign − * (used, for example, in specifications of {@link StreamingApertureProcessor} * or {@link net.algart.matrices.morphology.RankMorphology}). * In many cases, it is convenient to use {@link DependenceApertureBuilder} class to create * dependence apertures for an aperture processor.

* *

If this rule is violated, for example, if the aperture, returned by * {@link #dependenceAperture(Object) dependenceAperture} method, is too little (the results depend on elements * outside this aperture), then {@link #process(Map, Map) process} method still works, * but the results of processing can be incorrect. * If the aperture, returned by {@link #dependenceAperture(Object) dependenceAperture} method, is too large * (the results do not depend on most of elements in the aperture), * then {@link #process(Map, Map) process} method still works and the results are correct, * but excessively large aperture sizes can slow down the calculations.

* *

The {@link #process(Map, Map) process} method fills all resulting matrices. * But if some of the resulting matrices M'j, passed via dest map * while calling this method, is {@code null}, then it must be automatically created. * Moreover, if some of the resulting matrices M'j was not {@code null} * while calling this method, the method still may create new matrix for this key (index) j * and store it in dest map instead of the original matrix. * In addition, this method may create (and store in dest map) some new resulting matrices * with new keys (indexes), which were not contained in dest while calling the method. * But here must be the following guarantee: the set of indexes j of the resulting matrix * M'j, created and stored in dest map by this method in addition to * existing key/value pairs in dest map, * cannot vary for different calls of {@link #process(Map, Map) process} * method of the same instance of the processor.

* *

If {@link #process(Map, Map) process} method allocates some resulting matrix, * then all these matrices must be created with the same dimensions as all the source and non-null resulting * matrices, passed to the method. * The type of elements of the newly created matrix is selected by some rules, depending on the implementation. * Typical example — it is selected to be equal to the element type of some source matrices. * But here must be the following guarantee: the element type of the resulting matrix M'j * with the given index j cannot vary for different calls of {@link #process(Map, Map) process} * method of the same processor, if the element types of all source matrices Mi * do not vary while these calls. In other words, a concrete instance of the processor may * select the element type of newly created matrices only on the base of the element types of the arguments, * but not, for example, on the base of the matrix dimensions.

* * @param the type of the keys. * @author Daniel Alievsky */ public interface ApertureProcessor { /** * Main method of the aperture processor, that performs processing the source matrices src * with saving results in the resulting matrices dest. * The source matrices * Mi, iQ * are passed in src map: Mi=src.get(i). * The resulting matrices * M'j, jR, * are passed or, maybe, dynamically created and stored in dest map: * M'j=dest.get(j). * So, the sets of indexes Q and R are the Java sets * src.keySet() and dest.keySet() (after the call of this method). * See {@link ApertureProcessor comments to ApertureProcessor} for more details. * *

Note 1: some of the source matrices may be references to the same object * (src.get(i)==src.get(j)) — such situations must be processed correctly by this method. * *

Note 2: this method must not modify src map and the source matrices, contained in this map. * *

Note 3: this method must not remove key/value pairs from dest map * (but may add new resulting matrices). * *

Note 4: if some resulting matrix M'j, passed in dest map * as dest.get(j), is {@code null} while calling this method, * it must be automatically created and stored back in dest * map for the same key (index) j. * (Besides this, this method may create and store in dest another additional resulting matrices * with another indexes.) * *

Note 5: if this method creates some resulting matrices itself, then dest map should be mutable. * The created resulting matrices are saved in this map by dest.put(K,...) call. * *

Note 6: if this method stores some resulting matrices it dest map, they must have the same * dimensions as all matrices, passed in src and dest maps while calling the method. * This method must not store {@code null} values in dest map. * *

Note 7: resulting matrices, created by this method instead of {@code null} values in dest map * or in addition to the existing matrices in dest map, * may be not updatable, i.e. it is possible that their {@link Matrix#array() built-in arrays} will not * implement {@link net.algart.arrays.UpdatableArray} interface. * The simplest example: the algorithm may return, as a result (saved in dest), * some lazy view of one of the source matrices src.get(i) * or even just a reference to a source matrix src.get(i). * (But if this object is a tiled processors, returned by * {@link TiledApertureProcessorFactory#tile(ApertureProcessor)} method, then it is impossible: * in this case, all resulting matrices, created by this method and stored in * dest map, are always updatable, and their {@link Matrix#array() built-in arrays} * implement {@link net.algart.arrays.UpdatableArray}.) * *

Note 8: unlike this, all non-null values, present in dest map while calling this method, * must be updatable — because this method may need to store results in them. * It is true even if this method does not use the old non-null values * M'j and replace them with newly created matrices — * even in this case the method may check, that they are not updatable, and throw an exception if so. * *

Note 9: the sets of indexes of arguments Q and results R, * as well as the dimensions of matrices, may vary for different calls of this method. * (Even the number of dimensions may vary in some implementations, but it is a rarer situation. * The tiled processors, returned by {@link TiledApertureProcessorFactory#tile(ApertureProcessor)} method, * work only with a fixed number of dimensions, equal to {@link TiledApertureProcessorFactory#dimCount()}.) * *

Note 10: degenerated cases Q=∅ (src.isEmpty(): no arguments) and * R=∅ (dest.isEmpty(): no results) are allowed. * If Q=R=∅, as well as if Q=∅ and * the dest map, passed to this method, * either is empty or contains only {@code null} matrices, * then this method usually does nothing — * it is really true for the tiled processors, returned by * {@link TiledApertureProcessorFactory#tile(ApertureProcessor)} method, * but it is not a strict requirement for other implementations. * * @param dest the resulting matrices: the result M'j * will be the value dest.get(j) of this map after calling this method. * @param src the source arguments: the argument Mi is the value * src.get(i) of this map. * @throws NullPointerException if dest or src argument * is {@code null}, * or if one of values in src map is {@code null}. * @throws IllegalArgumentException if some values in dest map are not {@code null} * and, at the same time, their {@link Matrix#array() * built-in arrays} are not * {@link net.algart.arrays.UpdatableArray updatable}; * ClassCastException can be also thrown in this case * instead of this exception. * @throws net.algart.arrays.SizeMismatchException if some matrices among the source arguments (values of * src map) or non-null resulting matrices * (values of dest map), passed while calling this * method, have different dimensions. It is a typical run-time * exception in this case, and it is really thrown by the tiled * processors, created by * {@link TiledApertureProcessorFactory#tile(ApertureProcessor)} * method; but other implementations are permitted to throw * another exceptions in this case. */ void process(Map> dest, Map> src); /** * Returns the dependence aperture Ai * for the source matrix Mi with the given index * i=srcMatrixKey. * See {@link ApertureProcessor comments to ApertureProcessor} for more details. * *

This method must return correct result for any key, which can appear and can be processed in * {@link #process(Map, Map) process} method as a key in its src map. * If srcMatrixKey argument has some "impossible" value, the result is not specified. * *

This method should work quickly and must never throw exceptions. * * @param srcMatrixKey the index (key) of the source matrix. * @return the dependence aperture of the processing algorithm for this source matrix. */ IRectangularArea dependenceAperture(K srcMatrixKey); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy