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

net.algart.matrices.morphology.Morphology 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.functions.Func;
import net.algart.math.patterns.Pattern;
import net.algart.math.patterns.UniformGridPattern;

/**
 * 

Mathematical morphology over {@link Matrix n-dimensional matrices} with a random * n-dimensional structuring element (shape), represented by {@link Pattern} class. * 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. * In 2-dimensional case, these operations can be used for processing grayscale digital images. * Please see Wikipedia * about the "Mathematical morphology" concept.

* *

Basic operations, defined by this interface, are {@link #dilation(Matrix, Pattern) dilation} * and {@link #erosion(Matrix, Pattern) erosion}. Other operations are combinations * of the basic ones and, probably, some arithmetic elementwise operations.

* *

This package provides the following basic methods for creating objects, implementing this interface:

* *
    *
  • {@link BasicMorphology#getInstance(ArrayContext)};
  • *
  • {@link BasicMorphology#getInstance(ArrayContext, long)};
  • *
  • {@link ContinuedMorphology#getInstance(Morphology, Matrix.ContinuationMode)};
  • *
* *

and also the methods creating {@link RankMorphology} objects — see comments to that interface.

* *

The classes, implementing this interface, are immutable and thread-safe: * there are no ways to modify settings of the created instance.

* * @author Daniel Alievsky */ public interface Morphology extends ArrayProcessorWithContextSwitching { /** *

Subtraction mode for some methods of {@link Morphology} interface.

* *

The following morphology methods:

* *
    *
  • {@link Morphology#dilation(Matrix, Pattern, Morphology.SubtractionMode)},
  • *
  • {@link Morphology#erosion(Matrix, Pattern, Morphology.SubtractionMode)},
  • *
  • {@link Morphology#dilationErosion(Matrix, Pattern, Pattern, Morphology.SubtractionMode)},
  • *
  • {@link Morphology#erosionDilation(Matrix, Pattern, Pattern, Morphology.SubtractionMode)},
  • *
  • {@link Morphology#closing(Matrix, Pattern, Morphology.SubtractionMode)},
  • *
  • {@link Morphology#opening(Matrix, Pattern, Morphology.SubtractionMode)},
  • *
* *

vary their behavior depending on the last argument of this type. * The usual behavior, corresponding to names of the methods, obtains when this argument is {@link #NONE}. * However, if this argument is {@link #SUBTRACT_RESULT_FROM_SRC} or {@link #SUBTRACT_SRC_FROM_RESULT}, * every method, after calculating the result R by usual rules, * automatically performs elementwise subtraction * either the result R from the source matrix A (the 1st argument), * or the source matrix A from the result R. * Namely:

* *
    *
  • if the last argument is {@link #SUBTRACT_RESULT_FROM_SRC}, every of the listed methods returns * the elementwise positive difference max(0,A-R);
  • *
  • if the last argument is {@link #SUBTRACT_SRC_FROM_RESULT}, every of the listed methods returns * the elementwise positive difference max(0,R-A);
  • *
  • if the last argument is {@link #NONE}, no additional subtractions are performed: the method * just returns R.
  • *
* *

Note that the byte and short elements are considered to be unsigned integers * while subtraction.

*/ enum SubtractionMode { /** * No subtractions are performed: standard behavior. * See {@link SubtractionMode comments to this enumeration} for more details. */ NONE() { @Override void subtract(ArrayContext context, Matrix dest, Matrix src) { // don't modify dest } }, /** * The result of calculations is subtracted from the source matrix, and the (positive) difference is returned. * See {@link SubtractionMode comments to this enumeration} for more details. */ SUBTRACT_RESULT_FROM_SRC() { @Override void subtract(ArrayContext context, Matrix dest, Matrix src) { Matrices.applyFunc(context, true, Func.POSITIVE_DIFF, dest, src, dest); } }, /** * The source matrix is subtracted from the result of calculations, and the (positive) difference is returned. * See {@link SubtractionMode comments to this enumeration} for more details. */ SUBTRACT_SRC_FROM_RESULT() { @Override void subtract(ArrayContext context, Matrix dest, Matrix src) { Matrices.applyFunc(context, true, Func.POSITIVE_DIFF, dest, dest, src); } }; abstract void subtract(ArrayContext context, Matrix dest, Matrix src); } Morphology context(ArrayContext newContext); /** * Returns true, if this class works in the default * {@link net.algart.arrays.Matrix.ContinuationMode#PSEUDO_CYCLIC * pseudo-cyclic continuation mode}. * *

More precisely, it means that when the value in some element of the processed matrix, * returned by a method of this class, depends on elements of the source matrix, lying outside its bounds, * then it is supposed that the values outside the source matrix are calculated as described in * {@link net.algart.arrays.Matrix.ContinuationMode#PSEUDO_CYCLIC}. Exactly such behavior is specified in * the comments to the basic {@link #dilation(Matrix, Pattern)} and {@link #erosion(Matrix, Pattern)} * methods as the default definition of dilation and erosion. * *

This method returns true in {@link BasicMorphology} and {@link BasicRankMorphology} implementation. * However, it usually returns false in {@link ContinuedMorphology} and * {@link ContinuedRankMorphology} classes — excepting the only degenerated case when the used * {@link ContinuedMorphology#continuationMode() continuation mode} is * {@link net.algart.arrays.Matrix.ContinuationMode#PSEUDO_CYCLIC PSEUDO_CYCLIC}. * * @return whether this class works in the pseudo-cyclic continuation mode. */ boolean isPseudoCyclic(); /** * Returns an immutable view of the passed source matrix, * such that any reading data from it calculates and returns the dilation * of the source matrix by the specified pattern. * See {@link #dilation(Matrix, Pattern)} method about the "dilation" term. * The {@link Matrix#elementType() element type} * of the created matrix is the same as the element type of the source one. * *

The result is usually "lazy", that means that this method finishes immediately and all * actual calculations are performed while getting elements of the returned matrix. * It is true for all implementations provided by this package. * However, some implementations may not support lazy dilation; * then this method will be equivalent to {@link #dilation(Matrix, Pattern)}. * *

Please note: this method does not require time (if the result is "lazy"), * but the resulting matrix can work slowly! * For example, reading all its content than work much slower than {@link #dilation(Matrix, Pattern)} * method for complex patterns. * Usually you should use it only for very little patterns, or if you know that the implementation * of this interface does not provide better algorithm for non-"lazy" * {@link #dilation(Matrix, Pattern)} method. * * @param src the source matrix. * @param pattern the pattern. * @return the "lazy" matrix containing the dilation of the source matrix by the given pattern. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix asDilation(Matrix src, Pattern pattern); /** * Returns an immutable view of the passed source matrix, * such that any reading data from it calculates and returns the erosion * of the source matrix by the specified pattern. * See {@link #erosion(Matrix, Pattern)} method about the "erosion" term. * The {@link Matrix#elementType() element type} * of the created matrix is the same as the element type of the source one. * *

The result is usually "lazy", that means that this method finishes immediately and all * actual calculations are performed while getting elements of the returned matrix. * It is true for all implementations provided by this package. * However, some implementations may not support lazy erosion; * then this method will be equivalent to {@link #erosion(Matrix, Pattern)}. * *

Please note: this method does not require time (if the result is "lazy"), * but the resulting matrix can work slowly! * For example, reading all its content than work much slower than {@link #dilation(Matrix, Pattern)} * method for complex patterns. * Usually you should use it only for very little patterns, or if you know that the implementation * of this interface does not provide better algorithm for non-"lazy" * {@link #erosion(Matrix, Pattern)} method. * * * @param src the source matrix. * @param pattern the pattern. * @return the "lazy" matrix containing the erosion of the source matrix by the given pattern. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix asErosion(Matrix src, Pattern pattern); /** * Returns a new updatable matrix, containing the dilation * of the source matrix by the specified pattern. * *

Usually dilation means the elementwise maximum from the set of matrices, * obtained by pseudo-cyclic shifting the source matrix by the vectors, * equal to all pattern points. * More precisely, let mi={@link * Matrices#asShifted(Matrix, long...) * Matrices.asShifted}(src,ip.{@link IPoint#coordinates() coordinates()}), * where ip is the point #i from all points contained in the pattern. * Then the every element of the returned matrix is the maximum from all corresponding elements * of all mi matrices. The {@link Matrix#elementType() element type} * of the created matrix is the same as the element type of the source one. * The byte and short elements are considered to be unsigned. * In a case of bit elements, the maximum is equivalent to logical OR. * *

The basic morphology implementation {@link BasicMorphology} strictly complies with this definition. * However, other implementations of this interface may use alternate definitions of the dilation term. * For example, some percentile (90% or 80%) may be used instead of strict maximum * (as in objects, returned by {@link BasicRankMorphology#getInstance(ArrayContext, double, CustomRankPrecision)} * method), * or elements outside the matrix may be supposed to be filled according some non-trivial rules * instead of pseudo-cyclic continuation * (as in {@link ContinuedMorphology} objects), * or only some region of the matrix may be processed, etc. * *

Please see * Wikipedia * to know more about the dilation. * * @param src the source matrix. * @param pattern the pattern. * @return the result of dilation of the source matrix by the given pattern. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. * @see #asDilation(Matrix, Pattern) * @see #dilation(Matrix, Matrix, Pattern, boolean) * @see #dilation(Matrix, Pattern, Morphology.SubtractionMode) */ Matrix dilation(Matrix src, Pattern pattern); /** * Returns a new updatable matrix, containing the erosion * of the source matrix by the specified pattern. * *

Usually erosion means the elementwise minimum from the set of matrices, * obtained by pseudo-cyclic shifting the source matrix by the vectors, * symmetric to all pattern points relatively the origin of coordinates. * More precisely, let mi={@link * Matrices#asShifted(Matrix, long...) * Matrices.asShifted}(src,ip.{@link IPoint#symmetric() * symmetric()}.{@link IPoint#coordinates() coordinates()}), * where ip is the point #i from all points contained in the pattern. * Then the every element of the returned matrix is the minimum from all corresponding elements * of all mi matrices. The {@link Matrix#elementType() element type} * of the created matrix is the same as the element type of the source one. * The byte and short elements are considered to be unsigned. * In a case of bit elements, the minimum is equivalent to logical AND. * *

The basic morphology implementation {@link BasicMorphology} strictly complies with this definition. * However, other implementations of this interface may use alternate definitions of the erosion term. * For example, some percentile (10% or 20%) may be used instead of strict minimum * (as in objects, returned by {@link BasicRankMorphology#getInstance(ArrayContext, double, CustomRankPrecision)} * method), * or elements outside the matrix may be supposed to be filled according some non-trivial rules * instead of pseudo-cyclic continuation * (as in {@link ContinuedMorphology} objects), * or only some region of the matrix may be processed, etc. * *

Please see * Wikipedia * to know more about the erosion. * * @param src the source matrix. * @param pattern the pattern. * @return the result of erosion of the source matrix by the given pattern. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. * @see #asDilation(Matrix, Pattern) * @see #erosion(Matrix, Matrix, Pattern, boolean) * @see #erosion(Matrix, Pattern, Morphology.SubtractionMode) */ Matrix erosion(Matrix src, Pattern pattern); /** * Extended version of {@link #dilation(Matrix, Pattern)} method: if subtractionMode argument * is not {@link SubtractionMode#NONE}, * returns the difference between the dilation and the src matrix, * according the specified mode. * *

If subtractionMode=={@link SubtractionMode#NONE}, this method is strictly equivalent * to {@link #dilation(Matrix, Pattern)}. * *

The result of this operation with * subtractionMode=={@link SubtractionMode#SUBTRACT_SRC_FROM_RESULT} * is also called the external gradient of the source matrix. * * @param src the source matrix. * @param pattern the pattern. * @param subtractionMode whether the difference of the dilation and the source matrix should be returned. * @return the result of dilation of the source matrix by the given pattern * or the difference of the dilation and the source matrix. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix dilation( Matrix src, Pattern pattern, SubtractionMode subtractionMode); /** * Extended version of {@link #erosion(Matrix, Pattern)} method: if subtractionMode argument * is not {@link SubtractionMode#NONE}, * returns the difference between the erosion and the src matrix, * according the specified mode. * *

If subtractionMode=={@link SubtractionMode#NONE}, this method is strictly equivalent * to {@link #erosion(Matrix, Pattern)}. * *

The result of this operation with * subtractionMode=={@link SubtractionMode#SUBTRACT_RESULT_FROM_SRC} * is also called the internal gradient of the source matrix. * * @param src the source matrix. * @param pattern the pattern. * @param subtractionMode whether the difference of the erosion and the source matrix should be returned. * @return the result of erosion of the source matrix by the given pattern * or the difference of the erosion and the source matrix. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix erosion( Matrix src, Pattern pattern, SubtractionMode subtractionMode); /** * Equivalent to {@link #dilation(Matrix, Pattern)} method, but the result matrix * will be placed in the dest argument. * It allows to avoid extra memory allocation if you need to perform dilation many times * from one matrix to another. * *

Moreover, if disableMemoryAllocation argument is true, this method * guarantees that no any additional memory will be allocated, even if it can optimize the algorithm speed. * In this case, this method is always executed in one pass: * it is equivalent to creating new lazy matrix by {@link #asDilation(Matrix src, Pattern pattern)} method * and further copying it into dest by {@link Matrices#copy(ArrayContext, Matrix, Matrix)} method. * It can be useful if you are sure that the pattern is small enough (usually 2-10 points), * and allocation additional work matrices can slow down the algorithm to greater extent * than using the simple one-pass algorithm. * *

If the element type of the dest matrix is not the same as the source element type * (dest.{@link Matrix#elementType() elementType()}!=src.{@link Matrix#elementType() elementType()}), * the elements are automatically cast to the necessary type. More precisely, in this case * the dest matrix, before all further calculations, is replaced with * *

     * {@link
     * Matrices#asUpdatableFuncMatrix(boolean, net.algart.math.functions.Func.Updatable, Class, Matrix)
     * Matrices.asUpdatableFuncMatrix}(true, {@link net.algart.math.functions.Func#UPDATABLE_IDENTITY
     * Func.UPDATABLE_IDENTITY}, src.updatableType(UpdatablePArray.class), dest)
     * 
* *

We do not recommend to pass matrices with different element types: it can slow down calculations. * * @param dest the target matrix. * @param src the source matrix. * @param pattern the pattern. * @param disableMemoryAllocation if false, this method may allocate additional temporary matrices * for optimizing the algorithm speed; * if true, no any work memory will be allocated. * @throws NullPointerException if one of the arguments is {@code null}. * @throws SizeMismatchException if the passed matrices have different dimensions. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ void dilation( Matrix dest, Matrix src, Pattern pattern, boolean disableMemoryAllocation); /** * Equivalent to {@link #erosion(Matrix, Pattern)} method, but the result matrix * will be placed in the dest argument. * It allows to avoid extra memory allocation if you need to perform erosion many times * from one matrix to another. * *

Moreover, if disableMemoryAllocation argument is true, this method * guarantees that no any additional memory will be allocated, even if it can optimize the algorithm speed. * In this case, this method is always executed in one pass: * it is equivalent to creating new lazy matrix by {@link #asDilation(Matrix src, Pattern pattern)} method * and further copying it into dest by {@link Matrices#copy(ArrayContext, Matrix, Matrix)} method. * It can be useful if you are sure that the pattern is small enough (usually 2-10 points), * and allocation additional work matrices can slow down the algorithm to greater extent * than using the simple one-pass algorithm. * *

If the element type of the dest matrix is not the same as the source element type * (dest.{@link Matrix#elementType() elementType()}!=src.{@link Matrix#elementType() elementType()}), * the elements are automatically cast to the necessary type. More precisely, in this case * the dest matrix, before all further calculations, is replaced with * *

     * {@link
     * Matrices#asUpdatableFuncMatrix(boolean, net.algart.math.functions.Func.Updatable, Class, Matrix)
     * Matrices.asUpdatableFuncMatrix}(true, {@link net.algart.math.functions.Func#UPDATABLE_IDENTITY
     * Func.UPDATABLE_IDENTITY}, src.updatableType(UpdatablePArray.class), dest)
     * 
* *

We do not recommend to pass matrices with different element types: it can slow down calculations. * * @param dest the target matrix. * @param src the source matrix. * @param pattern the pattern. * @param disableMemoryAllocation if false, this method may allocate additional temporary matrices * for optimizing the algorithm speed; * if true, no any work memory will be allocated. * @throws NullPointerException if one of the arguments is {@code null}. * @throws SizeMismatchException if the passed matrices have different dimensions. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ void erosion( Matrix dest, Matrix src, Pattern pattern, boolean disableMemoryAllocation); /** * Equivalent to {@link #dilation(Matrix, Matrix, Pattern, boolean) dilation(dest, src, pattern, false)}. * * @param dest the target matrix. * @param src the source matrix. * @param pattern the pattern. * @throws NullPointerException if one of the arguments is {@code null}. * @throws SizeMismatchException if the passed matrices have different dimensions. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ void dilation(Matrix dest, Matrix src, Pattern pattern); /** * Equivalent to {@link #erosion(Matrix, Matrix, Pattern, boolean) erosion(dest, src, pattern, false)}. * * @param dest the target matrix. * @param src the source matrix. * @param pattern the pattern. * @throws NullPointerException if one of the arguments is {@code null}. * @throws SizeMismatchException if the passed matrices have different dimensions. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ void erosion(Matrix dest, Matrix src, Pattern pattern); /** * Returns a new updatable matrix, containing the result of sequential * {@link #dilation(Matrix, Pattern) dilation(src, dilationPattern)} and * {@link #erosion(Matrix, Pattern) erosion(src, erosionPattern)} * of the source matrix by the specified patterns. * *

If subtractionMode is not {@link SubtractionMode#NONE}, * the behavior is little other: this method returns the difference between * the result of these two operation and the src matrix, according the specified mode. * *

When both patterns are equal, the result is the {@link #closing(Matrix, Pattern, Morphology.SubtractionMode) * closing} of the matrix. * * @param src the source matrix. * @param dilationPattern the pattern for dilation. * @param erosionPattern the pattern for erosion. * @param subtractionMode whether the difference with the source matrix should be returned. * @return the result of sequential dilation and erosion of the source matrix by the given patterns * or the difference of such result and the source matrix. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if dilationPattern.{@link Pattern#dimCount() dimCount()} or * erosionPattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix dilationErosion( Matrix src, Pattern dilationPattern, Pattern erosionPattern, SubtractionMode subtractionMode); /** * Returns a new updatable matrix, containing the result of sequential * {@link #erosion(Matrix, Pattern) erosion(src, erosionPattern)} and * {@link #dilation(Matrix, Pattern) dilation(src, dilationPattern)} * of the source matrix by the specified patterns. * *

If subtractionMode is not {@link SubtractionMode#NONE}, * the behaviour is little other: this method returns the difference between * the result of these two operation and the src matrix, according the specified mode. * *

When both patterns are equal, the result is the {@link #opening(Matrix, Pattern, Morphology.SubtractionMode) * opening} of the matrix. * * @param src the source matrix. * @param erosionPattern the pattern for erosion. * @param dilationPattern the pattern for dilation. * @param subtractionMode whether the difference with the source matrix should be returned. * @return the result of sequential erosion and dilation of the source matrix by the given patterns * or the difference of such result and the source matrix. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if dilationPattern.{@link Pattern#dimCount() dimCount()} or * erosionPattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix erosionDilation( Matrix src, Pattern erosionPattern, Pattern dilationPattern, SubtractionMode subtractionMode); /** * Returns a new updatable matrix, containing the closing * of the source matrix by the specified pattern. * *

Closing means the result of sequential performing * {@link #dilation(Matrix, Pattern) dilation} and {@link #erosion(Matrix, Pattern) erosion} of the source matrix * with the same pattern. * *

If subtractionMode is not {@link SubtractionMode#NONE}, * the behaviour is little other: this method returns the difference between * the closing and the src matrix, according the specified mode. * For example, {@link SubtractionMode#SUBTRACT_SRC_FROM_RESULT} argument * with this method allows to remove "light" background from a gray-scale image, * represented by src matrix. * *

This method is equivalent to {@link #dilationErosion(Matrix, Pattern, Pattern, Morphology.SubtractionMode) * dilationErosion(src, pattern, pattern, subtractionMode)}. * *

Please see * Wikipedia * to know more about the closing. * * @param src the source matrix. * @param pattern the pattern. * @param subtractionMode whether the difference of the closing and the source matrix should be returned. * @return the result of closing of the source matrix by the given pattern * or the difference of the closing and the source matrix. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix closing( Matrix src, Pattern pattern, SubtractionMode subtractionMode); /** * Returns a new updatable matrix, containing the opening * of the source matrix by the specified pattern. * *

Opening means the result of sequential performing * {@link #erosion(Matrix, Pattern) erosion} and {@link #dilation(Matrix, Pattern) dilation} of the source matrix * with the same pattern. * *

If subtractionMode is not {@link SubtractionMode#NONE}, * the behaviour is little other: this method returns the difference between * the opening and the src matrix, according the specified mode. * For example, {@link SubtractionMode#SUBTRACT_RESULT_FROM_SRC} argument * with this method allows to remove "dark" background from a gray-scale image, * represented by src matrix. * *

This method is equivalent to {@link #erosionDilation(Matrix, Pattern, Pattern, Morphology.SubtractionMode) * erosionDilation(src, pattern, pattern, subtractionMode)}. * *

Please see * Wikipedia * to know more about the opening. * * @param src the source matrix. * @param pattern the pattern. * @param subtractionMode whether the difference of the opening and the source matrix should be returned. * @return the result of opening of the source matrix by the given pattern * or the difference of the opening and the source matrix. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix opening( Matrix src, Pattern pattern, SubtractionMode subtractionMode); /** * Returns a new updatable matrix, containing the weak dilation * of the source matrix by the specified pattern. * *

Weak dilation of the matrix A is defined as an elementwise difference * B={@link #dilation(Matrix, Pattern) * dilation}(A)-({@link #closing(Matrix, Pattern, Morphology.SubtractionMode) closing}(A)-A). * It is obvious that, for any elements, A<=B<={@link #dilation(Matrix, Pattern) dilation}(A) * (because both differences * {@link #dilation(Matrix, Pattern) * dilation}(A)-{@link #closing(Matrix, Pattern, Morphology.SubtractionMode) closing}(A) * and {@link #closing(Matrix, Pattern, Morphology.SubtractionMode) closing}(A)-A are non-negative). * *

(In this method, the {@link #closing(Matrix, Pattern, Morphology.SubtractionMode) closing} is supposed * to be performed with the last argument {@link SubtractionMode#NONE}.) * * @param src the source matrix. * @param pattern the pattern. * @return the result of weak dilation of the source matrix by the given pattern. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix weakDilation(Matrix src, Pattern pattern); /** * Returns a new updatable matrix, containing the weak erosion * of the source matrix by the specified pattern. * *

Weak erosion of the matrix A is defined as an elementwise sum * B={@link #erosion(Matrix, Pattern) * erosion}(A)+(A-{@link #opening(Matrix, Pattern, Morphology.SubtractionMode) opening}(A)). * It is obvious that, for any elements, A>=B>={@link #erosion(Matrix, Pattern) erosion}(A) * (because both differences * {@link #opening(Matrix, Pattern, Morphology.SubtractionMode) * opening}(A)-{@link #erosion(Matrix, Pattern) erosion}(A) * and A-{@link #opening(Matrix, Pattern, Morphology.SubtractionMode) opening}(A) are non-negative). * *

(In this method, the {@link #opening(Matrix, Pattern, Morphology.SubtractionMode) opening} is supposed * to be performed with the last argument {@link SubtractionMode#NONE}.) * * @param src the source matrix. * @param pattern the pattern. * @return the result of weak dilation of the source matrix by the given pattern. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix weakErosion(Matrix src, Pattern pattern); /** * Returns the elementwise minimum between the source matrix and the result of * {@link #dilationErosion(Matrix, Pattern, Pattern, Morphology.SubtractionMode) * dilationErosion}(src, dilationPattern, erosionPattern, {@link SubtractionMode#NONE}) call. * *

Let B is the result of this method, A is the source matrix, * Q is dilationPattern, P is erosionPattern:
* B=min(A,{@link #erosion(Matrix, Pattern) * erosion}({@link #dilation(Matrix, Pattern) dilation}(A,Q),P))
for any elements. * It is obvious that (for any elements) A>=B>={@link #erosion(Matrix, Pattern) erosion}(A,P). * But if Q is a some "boundary" or "carcass" of the erosion pattern P, * then a stronger condition is true: * A>=B>={@link #opening(Matrix, Pattern, Morphology.SubtractionMode) opening}(A,P). * *

More precisely, there is the following theorem. * *

If Q is a subset of P and the Minkowski sum P⊕Q is equal to * P⊕P (see {@link Pattern#carcass} method), * then B>={@link #opening(Matrix, Pattern, Morphology.SubtractionMode) opening}(A,P). * *

Below is the proof for the binary case. * (For other element types, it's enough to consider the system of binary matrices * A>=threshold for all possible real values threshold.) * *

*

Let some point x∈{@link #opening(Matrix, Pattern, Morphology.SubtractionMode) * opening}(A,P). * It means: there is such p1∈P, * that for all p∈P we have x+p1-p∈A * (the statement A). * We already know, that x∈A (the case p=p1), * and we also need to prove, that x∈{@link #erosion(Matrix, Pattern) * erosion}({@link #dilation(Matrix, Pattern) dilation}(A,Q),P). * *

Let's suppose that it is not true. It means: there is such p2∈P, * that for all q∈Q we have x+p2-q∉A * (the statement B) * *

Let x will be the origin of coordinates: x=0. Then, let * P1=-P+p1={p1-p, * p∈P}. Note: the origin 0∈P1 * (the case p=p1). We have P1⊂A * (statement A), so, * for all q∈Q we have p2-q∉P1 * (because p2-q∉A, statement B). * In other words, p2∉P1⊕Q (dilation of P by Q, * or Minkowski sum of P and Q). * On the other hand, it's obvious that p2∈P1⊕P, * because 0∈P1 and, so, * P⊂P⊕P1=P1⊕P. * *

There is a contradiction: according to the condition, there must be * P1⊕P=P1⊕Q. The theorem is proved. *

* *

This fact allows to interpret this method, if dilationPattern * is a "boundary" of erosionPattern (usually {@link UniformGridPattern#surface()} * or a similar point set), as a "weak" analog of opening. * For binary images, it helps to remove small isolated objects, but (unlike usual opening) * to preserve thin structures. * * @param src the source matrix. * @param dilationPattern the pattern for dilation. * @param erosionPattern the pattern for erosion. * @return the elementwise minimum between the source matrix and * its sequential dilation and erosion by the given patterns. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if dilationPattern.{@link Pattern#dimCount() dimCount()} or * erosionPattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix maskedDilationErosion( Matrix src, Pattern dilationPattern, Pattern erosionPattern); /** * Returns the elementwise maximum between the source matrix and the result of * {@link #erosionDilation(Matrix, Pattern, Pattern, Morphology.SubtractionMode) * erosionDilation}(src, erosionPattern, dilationPattern, {@link SubtractionMode#NONE}) call. * *

This is an inverse method for {@link #maskedDilationErosion(Matrix, Pattern, Pattern)}. * * @param src the source matrix. * @param erosionPattern the pattern for erosion. * @param dilationPattern the pattern for dilation. * @return the elementwise maximum between the source matrix and * its sequential erosion and dilation by the given patterns. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if dilationPattern.{@link Pattern#dimCount() dimCount()} or * erosionPattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix maskedErosionDilation( Matrix src, Pattern erosionPattern, Pattern dilationPattern); /** * Returns a new updatable matrix, containing the Beucher gradient * of the source matrix by the specified pattern, that means * the elementwise difference between {@link #dilation(Matrix, Pattern) dilation} * and {@link #erosion(Matrix, Pattern) erosion} of the source matrix with the same pattern. * *

More precisely, the Beucher gradient of the matrix A is defined * as an elementwise positive difference * B=max(0,{@link #dilation(Matrix, Pattern) dilation}(A)-{@link * #erosion(Matrix, Pattern) erosion}(A)). * *

The {@link Matrix#elementType() element type} * of the created matrix is the same as the element type of the source one. * The byte and short elements are considered to be unsigned. * * @param src the source matrix. * @param pattern the pattern. * @return the Beucher gradient of the source matrix by the given pattern. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if the number of the pattern dimensions * pattern.{@link Pattern#dimCount() dimCount()} is not equal * to src.{@link Matrix#dimCount() dimCount()}. */ Matrix beucherGradient(Matrix src, Pattern pattern); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy