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

net.algart.matrices.morphology.TiledRankMorphology 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.

The 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.morphology;

import net.algart.arrays.*;
import net.algart.math.IPoint;
import net.algart.math.IRectangularArea;
import net.algart.math.functions.Func;
import net.algart.math.patterns.Pattern;
import net.algart.matrices.ApertureProcessor;
import net.algart.matrices.DependenceApertureBuilder;
import net.algart.matrices.TiledApertureProcessorFactory;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 

The filter allowing to transform any {@link RankMorphology} object to another instance of that interface, * which uses some given {@link TiledApertureProcessorFactory tiler} for processing the source matrices * (arguments of {@link RankMorphology} methods).

* *

This object is built on the base of some parent object, * implementing {@link RankMorphology}, and some tiler (an instance of * {@link TiledApertureProcessorFactory} class). * This object works almost identically to the parent object with the only difference, * that it uses the specified tiler for performing all operations.

* *

More precisely, each method of this object creates an implementation p of {@link ApertureProcessor} * interface. The only thing, performed by * {@link ApertureProcessor#process(Map, Map) process} method of * that object p, is calling the same method of parent object with the arguments * of p.{@link ApertureProcessor#process(Map, Map) process(dest,src)} method * (the source matrix or matrices are retrieved from src, the result is saved into dest). * The dependence aperture p.{@link ApertureProcessor#dependenceAperture(Object) dependenceAperture(...)} * is calculated automatically on the base of the patterns and the performed operation. * Then, the method of this object executes the required operation with help of * {@link #tiler() tiler()}.{@link TiledApertureProcessorFactory#tile(ApertureProcessor) * tile}(p).{@link ApertureProcessor#process(Map, Map) process(dest,src)} call * — the source matrix or matrices are passed via src, * the result is retrieved from dest. * As a result, the same operation is performed tile-by-tile.

* *

The methods "asOperation", returning a view of the passed sources matrices * (like {@link #asDilation(Matrix, Pattern)}, {@link #asPercentile(Matrix, double, Pattern)}, * {@link #asRank(Class, Matrix, Matrix, Pattern)}, etc.) are an exception * from this rule. These methods of this class works in the same way, as in * {@link ContinuedRankMorphology} class, the continuation mode of which is equal to * {@link #tiler() tiler()}.{@link TiledApertureProcessorFactory#continuationMode() continuationMode()}.

* *

Note: in improbable cases, when the dimensions of the source matrix and/or * the sizes of the pattern are extremely large (about 263), * so that the necessary appended matrices should have dimensions or total number of elements, * greater than Long.MAX_VALUE, * the methods of this class throw IndexOutOfBoundsException and do nothing. * See comments to {@link TiledApertureProcessorFactory} class, "Restriction" section for precise details. * Of course, these are very improbable cases.

* *

This class is immutable and thread-safe: * there are no ways to modify settings of the created instance.

* * @author Daniel Alievsky */ public class TiledRankMorphology extends TiledMorphology implements RankMorphology { private final RankMorphology parent; private final Matrix.ContinuationMode continuationMode; TiledRankMorphology(RankMorphology parent, TiledApertureProcessorFactory tiler) { super(parent, tiler); this.parent = parent; this.continuationMode = tiler.continuationMode(); } /** * Returns new instance of this class with the passed parent {@link RankMorphology} object * and the specified processing tiler. * *

Note: the {@link #context() context} of the created object is retrieved from * parent.{@link Morphology#context() context()}, and * the {@link TiledApertureProcessorFactory#context() context} of the passed tiler * is automatically replaced with the same one — the current {@link #tiler() tiler} * of the created object is tiler.{@link TiledApertureProcessorFactory#context(ArrayContext) * context}(newInstance.{@link #context() context()}). * It means that the {@link TiledApertureProcessorFactory#context() context} of the passed tiler is not important * and can be {@code null}.

* * @param parent parent object: the instance of {@link Morphology} interface * that will perform all operations. * @param tiler the tiler, which will be used for processing matrices by this class. * @return new instance of this class. * @throws NullPointerException if parent or tiler argument is {@code null}. */ public static TiledRankMorphology getInstance(RankMorphology parent, TiledApertureProcessorFactory tiler) { return new TiledRankMorphology(parent, tiler); } /** * Returns the parent {@link RankMorphology} object, * passed to {@link #getInstance(RankMorphology, TiledApertureProcessorFactory)} method. * * @return the parent {@link RankMorphology} object. */ @Override public RankMorphology parent() { return this.parent; } /** * Switches the context: returns an instance, identical to this one excepting * that it uses the specified newContext for all operations. * Usually, the returned instance is used only for performing a * {@link ArrayContext#part(double, double) subtask} of the full task. * *

More precisely, this method is equivalent to * {@link #getInstance(RankMorphology, TiledApertureProcessorFactory) * getInstance}({@link #parent()}.{@link RankMorphology#context(ArrayContext) * context}(newContext), {@link #tiler() tiler()}). * * @param newContext another context, used by the returned instance; can be {@code null}. * @return new instance with another context. */ @Override public RankMorphology context(ArrayContext newContext) { return new TiledRankMorphology(parent.context(newContext), tiler); } /*Repeat(INCLUDE_FROM_FILE, ContinuedRankMorphology.java, lazy) !! Auto-generated: NOT EDIT !! */ // **** LAZY FUNCTIONS **** public Matrix asPercentile(Matrix src, Matrix percentileIndexes, Pattern pattern) { Continuer c = new Continuer(null, src, percentileIndexes, pattern, parent, continuationMode); return c.reduce(parent.asPercentile(c.get(0), c.get(1), pattern)); } public Matrix asPercentile(Matrix src, double percentileIndex, Pattern pattern) { // important to call the same method of the parent, which will create a constant matrix with increased sizes Continuer c = new Continuer(null, src, pattern, parent, continuationMode); return c.reduce(parent.asPercentile(c.get(0), percentileIndex, pattern)); } public Matrix asRank(Class requiredType, Matrix baseMatrix, Matrix rankedMatrix, Pattern pattern) { Continuer c = new Continuer(null, baseMatrix, rankedMatrix, pattern, parent, continuationMode); return c.reduce(parent.asRank(requiredType, c.get(0), c.get(1), pattern)); } public Matrix asMeanBetweenPercentiles(Matrix src, Matrix fromPercentileIndexes, Matrix toPercentileIndexes, Pattern pattern, double filler) { Continuer c = new Continuer(null, src, fromPercentileIndexes, toPercentileIndexes, pattern, parent, continuationMode); return c.reduce(parent.asMeanBetweenPercentiles(c.get(0), c.get(1), c.get(2), pattern, filler)); } public Matrix asMeanBetweenPercentiles(Matrix src, double fromPercentileIndex, double toPercentileIndex, Pattern pattern, double filler) { // important to call the same method of the parent, which will create a constant matrix with increased sizes Continuer c = new Continuer(null, src, pattern, parent, continuationMode); return c.reduce(parent.asMeanBetweenPercentiles(c.get(0), fromPercentileIndex, toPercentileIndex, pattern, filler)); } public Matrix asMeanBetweenValues(Matrix src, Matrix minValues, Matrix maxValues, Pattern pattern, double filler) { Continuer c = new Continuer(null, src, minValues, maxValues, pattern, parent, continuationMode); return c.reduce(parent.asMeanBetweenValues(c.get(0), c.get(1), c.get(2), pattern, filler)); } public Matrix asMean(Matrix src, Pattern pattern) { Continuer c = new Continuer(null, src, pattern, parent, continuationMode); return c.reduce(parent.asMean(c.get(0), pattern)); } public Matrix asFunctionOfSum(Matrix src, Pattern pattern, Func processingFunc) { Continuer c = new Continuer(null, src, pattern, parent, continuationMode); return c.reduce(parent.asFunctionOfSum(c.get(0), pattern, processingFunc)); } public Matrix asFunctionOfPercentilePair(Matrix src, Matrix percentileIndexes1, Matrix percentileIndexes2, Pattern pattern, Func processingFunc) { Continuer c = new Continuer(null, src, percentileIndexes1, percentileIndexes2, pattern, parent, continuationMode); return c.reduce(parent.asFunctionOfPercentilePair(c.get(0), c.get(1), c.get(2), pattern, processingFunc)); } public Matrix asFunctionOfPercentilePair(Matrix src, double percentileIndex1, double percentileIndex2, Pattern pattern, Func processingFunc) { // important to call the same method of the parent, which will create a constant matrix with increased sizes Continuer c = new Continuer(null, src, pattern, parent, continuationMode); return c.reduce(parent.asFunctionOfPercentilePair(c.get(0), percentileIndex1, percentileIndex2, pattern, processingFunc)); } /*Repeat.IncludeEnd*/ // **** ACTUALIZING FUNCTIONS **** /*Repeat.SectionStart actual*/ public Matrix percentile(Matrix src, Matrix percentileIndexes, final Pattern pattern) { return tilingProcess(new RankMorphologyProcessor(src.dimCount(), pattern) { @Override public Matrix process(List> src) { return parent().percentile(src.get(0), src.get(1), pattern); } }, null, src, percentileIndexes); } public Matrix percentile(Matrix src, final double percentileIndex, final Pattern pattern) { return tilingProcess(new RankMorphologyProcessor(src.dimCount(), pattern) { @Override public Matrix process(List> src) { return parent().percentile(src.get(0), percentileIndex, pattern); } }, null, src); } public Matrix rank(final Class requiredType, Matrix baseMatrix, Matrix rankedMatrix, final Pattern pattern) { return tilingProcess(new RankMorphologyProcessor(baseMatrix.dimCount(), pattern) { @Override public Matrix process(List> src) { return parent().rank(requiredType, src.get(0), src.get(1), pattern); } }, null, baseMatrix, rankedMatrix).cast(requiredType); } public Matrix meanBetweenPercentiles(Matrix src, Matrix fromPercentileIndexes, Matrix toPercentileIndexes, final Pattern pattern, final double filler) { return tilingProcess(new RankMorphologyProcessor(src.dimCount(), pattern) { @Override public Matrix process(List> src) { return parent().meanBetweenPercentiles(src.get(0), src.get(1), src.get(2), pattern, filler); } }, null, src, fromPercentileIndexes, toPercentileIndexes); } public Matrix meanBetweenPercentiles(Matrix src, final double fromPercentileIndex, final double toPercentileIndex, final Pattern pattern, final double filler) { // important to call the same method of the parent, which will create a constant matrix with increased sizes return tilingProcess(new RankMorphologyProcessor(src.dimCount(), pattern) { @Override public Matrix process(List> src) { return parent().meanBetweenPercentiles(src.get(0), fromPercentileIndex, toPercentileIndex, pattern, filler); } }, null, src); } public Matrix meanBetweenValues(Matrix src, Matrix minValues, Matrix maxValues, final Pattern pattern, final double filler) { return tilingProcess(new RankMorphologyProcessor(src.dimCount(), pattern) { @Override public Matrix process(List> src) { return parent().meanBetweenValues(src.get(0), src.get(1), src.get(2), pattern, filler); } }, null, src, minValues, maxValues); } public Matrix mean(Matrix src, final Pattern pattern) { return tilingProcess(new RankMorphologyProcessor(src.dimCount(), pattern) { @Override public Matrix process(List> src) { return parent().mean(src.get(0), pattern); } }, null, src); } public Matrix functionOfSum(Matrix src, final Pattern pattern, final Func processingFunc) { return tilingProcess(new RankMorphologyProcessor(src.dimCount(), pattern) { @Override public Matrix process(List> src) { return parent().functionOfSum(src.get(0), pattern, processingFunc); } }, null, src); } public Matrix functionOfPercentilePair(Matrix src, Matrix percentileIndexes1, Matrix percentileIndexes2, final Pattern pattern, final Func processingFunc) { return tilingProcess(new RankMorphologyProcessor(src.dimCount(), pattern) { @Override public Matrix process(List> src) { return parent().functionOfPercentilePair(src.get(0), src.get(1), src.get(2), pattern, processingFunc); } }, null, src, percentileIndexes1, percentileIndexes2); } public Matrix functionOfPercentilePair(Matrix src, final double percentileIndex1, final double percentileIndex2, final Pattern pattern, final Func processingFunc) { return tilingProcess(new RankMorphologyProcessor(src.dimCount(), pattern) { @Override public Matrix process(List> src) { return parent().functionOfPercentilePair(src.get(0), percentileIndex1, percentileIndex2, pattern, processingFunc); } }, null, src); } /*Repeat.SectionEnd actual*/ // **** IN-PLACE FUNCTIONS **** /*Repeat(INCLUDE_FROM_FILE, THIS_FILE, actual) (final)?(\s+Class<[^>]*>\s+)?requiredType,\s* ==> ;; \.cast\((requiredType|UpdatablePArray\.class)\) ==> ;; public\s+(?:<[^>]*>\s*)?Matrix<[^>]*> ==> public void;; (Matrix\s*<[^>]*>\s+(?:src|baseMatrix)) ==> Matrix dest, $1;; return\s+(tilingProcess) ==> $1;; RankMorphologyProcessor ==> RankMorphologyInPlaceProcessor;; process\(List ==> process(Matrix dest, List;; return\s+parent ==> parent;; (src\.get\(0\)) ==> dest, $1;; null\,\s+(src|baseMatrix) ==> dest, $1 !! Auto-generated: NOT EDIT !! */ public void percentile(Matrix dest, Matrix src, Matrix percentileIndexes, final Pattern pattern) { tilingProcess(new RankMorphologyInPlaceProcessor(src.dimCount(), pattern) { @Override public void process(Matrix dest, List> src) { parent().percentile(dest, src.get(0), src.get(1), pattern); } }, dest, src, percentileIndexes); } public void percentile(Matrix dest, Matrix src, final double percentileIndex, final Pattern pattern) { tilingProcess(new RankMorphologyInPlaceProcessor(src.dimCount(), pattern) { @Override public void process(Matrix dest, List> src) { parent().percentile(dest, src.get(0), percentileIndex, pattern); } }, dest, src); } public void rank(Matrix dest, Matrix baseMatrix, Matrix rankedMatrix, final Pattern pattern) { tilingProcess(new RankMorphologyInPlaceProcessor(baseMatrix.dimCount(), pattern) { @Override public void process(Matrix dest, List> src) { parent().rank(dest, src.get(0), src.get(1), pattern); } }, dest, baseMatrix, rankedMatrix); } public void meanBetweenPercentiles(Matrix dest, Matrix src, Matrix fromPercentileIndexes, Matrix toPercentileIndexes, final Pattern pattern, final double filler) { tilingProcess(new RankMorphologyInPlaceProcessor(src.dimCount(), pattern) { @Override public void process(Matrix dest, List> src) { parent().meanBetweenPercentiles(dest, src.get(0), src.get(1), src.get(2), pattern, filler); } }, dest, src, fromPercentileIndexes, toPercentileIndexes); } public void meanBetweenPercentiles(Matrix dest, Matrix src, final double fromPercentileIndex, final double toPercentileIndex, final Pattern pattern, final double filler) { // important to call the same method of the parent, which will create a constant matrix with increased sizes tilingProcess(new RankMorphologyInPlaceProcessor(src.dimCount(), pattern) { @Override public void process(Matrix dest, List> src) { parent().meanBetweenPercentiles(dest, src.get(0), fromPercentileIndex, toPercentileIndex, pattern, filler); } }, dest, src); } public void meanBetweenValues(Matrix dest, Matrix src, Matrix minValues, Matrix maxValues, final Pattern pattern, final double filler) { tilingProcess(new RankMorphologyInPlaceProcessor(src.dimCount(), pattern) { @Override public void process(Matrix dest, List> src) { parent().meanBetweenValues(dest, src.get(0), src.get(1), src.get(2), pattern, filler); } }, dest, src, minValues, maxValues); } public void mean(Matrix dest, Matrix src, final Pattern pattern) { tilingProcess(new RankMorphologyInPlaceProcessor(src.dimCount(), pattern) { @Override public void process(Matrix dest, List> src) { parent().mean(dest, src.get(0), pattern); } }, dest, src); } public void functionOfSum(Matrix dest, Matrix src, final Pattern pattern, final Func processingFunc) { tilingProcess(new RankMorphologyInPlaceProcessor(src.dimCount(), pattern) { @Override public void process(Matrix dest, List> src) { parent().functionOfSum(dest, src.get(0), pattern, processingFunc); } }, dest, src); } public void functionOfPercentilePair(Matrix dest, Matrix src, Matrix percentileIndexes1, Matrix percentileIndexes2, final Pattern pattern, final Func processingFunc) { tilingProcess(new RankMorphologyInPlaceProcessor(src.dimCount(), pattern) { @Override public void process(Matrix dest, List> src) { parent().functionOfPercentilePair(dest, src.get(0), src.get(1), src.get(2), pattern, processingFunc); } }, dest, src, percentileIndexes1, percentileIndexes2); } public void functionOfPercentilePair(Matrix dest, Matrix src, final double percentileIndex1, final double percentileIndex2, final Pattern pattern, final Func processingFunc) { tilingProcess(new RankMorphologyInPlaceProcessor(src.dimCount(), pattern) { @Override public void process(Matrix dest, List> src) { parent().functionOfPercentilePair(dest, src.get(0), percentileIndex1, percentileIndex2, pattern, processingFunc); } }, dest, src); } /*Repeat.IncludeEnd*/ private Matrix tilingProcess(ApertureProcessor processor, Matrix dest, // maybe null Matrix src) { return tilingProcess(processor, dest, Matrices.several(PArray.class, src)); } private Matrix tilingProcess(ApertureProcessor processor, Matrix dest, // maybe null Matrix src, Matrix additional) { return tilingProcess(processor, dest, Matrices.several(PArray.class, src, additional)); } private Matrix tilingProcess(ApertureProcessor processor, Matrix dest, // maybe null Matrix src, Matrix additional1, Matrix additional2) { return tilingProcess(processor, dest, Matrices.several(PArray.class, src, additional1, additional2)); } private Matrix tilingProcess(ApertureProcessor processor, Matrix dest, // maybe null List> src) { Map> destMatrices = new LinkedHashMap<>(); Map> srcMatrices = new LinkedHashMap<>(); destMatrices.put(0, dest); for (int i = 0, n = src.size(); i < n; i++) { srcMatrices.put(i, src.get(i)); } tiler.tile(processor).process(destMatrices, srcMatrices); return destMatrices.get(0).cast(UpdatablePArray.class); } private abstract class RankMorphologyProcessor extends AbstractArrayProcessorWithContextSwitching implements ApertureProcessor, ArrayProcessorWithContextSwitching { private final IRectangularArea dependenceAperture; private final IRectangularArea emptyAperture; private RankMorphologyProcessor(int dimCount, Pattern pattern) { super(null); // will be replaced by the tiler this.dependenceAperture = DependenceApertureBuilder.SUM_MAX_0.getAperture(dimCount, pattern, false); this.emptyAperture = IRectangularArea.valueOf(IPoint.origin(dimCount), IPoint.origin(dimCount)); } public RankMorphology parent() { // parent with the correct sub-task context return parent.context(this.context()); } public void process(Map> dest, Map> src) { assert src.size() <= 3; assert dest.size() == 1; List> srcMatrices = new ArrayList<>(); for (int i = 0; i < 3; i++) { Matrix m = src.get(i); if (m != null) { srcMatrices.add(src.get(i).cast(PArray.class)); } } assert srcMatrices.size() == src.size() : "not all arguments specified"; dest.put(0, process(srcMatrices)); } public abstract Matrix process(List> src); public IRectangularArea dependenceAperture(Integer srcMatrixKey) { return srcMatrixKey == 0 ? dependenceAperture : emptyAperture; } } private abstract class RankMorphologyInPlaceProcessor extends AbstractArrayProcessorWithContextSwitching implements ApertureProcessor, ArrayProcessorWithContextSwitching { private final IRectangularArea dependenceAperture; private final IRectangularArea emptyAperture; private RankMorphologyInPlaceProcessor(int dimCount, Pattern pattern) { super(null); // will be replaced by the tiler this.dependenceAperture = DependenceApertureBuilder.SUM_MAX_0.getAperture(dimCount, pattern, false); this.emptyAperture = IRectangularArea.valueOf(IPoint.origin(dimCount), IPoint.origin(dimCount)); } public RankMorphology parent() { // parent with the correct sub-task context return parent.context(this.context()); } public void process(Map> dest, Map> src) { assert src.size() <= 3; assert dest.size() == 1; List> srcMatrices = new ArrayList<>(); for (int i = 0; i < 3; i++) { Matrix m = src.get(i); if (m != null) { srcMatrices.add(src.get(i).cast(PArray.class)); } } assert srcMatrices.size() == src.size() : "not all arguments specified"; process(dest.get(0).cast(UpdatablePArray.class), srcMatrices); } public abstract void process(Matrix dest, List> src); public IRectangularArea dependenceAperture(Integer srcMatrixKey) { return srcMatrixKey == 0 ? dependenceAperture : emptyAperture; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy