net.algart.matrices.morphology.Morphology Maven / Gradle / Ivy
Show all versions of algart Show documentation
/*
* 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 extends UpdatablePArray> dest, Matrix extends PArray> 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 extends UpdatablePArray> dest, Matrix extends PArray> 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 extends UpdatablePArray> dest, Matrix extends PArray> src) {
Matrices.applyFunc(context, true, Func.POSITIVE_DIFF, dest, dest, src);
}
};
abstract void subtract(ArrayContext context,
Matrix extends UpdatablePArray> dest, Matrix extends PArray> 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 extends PArray> asDilation(Matrix extends PArray> 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 extends PArray> asErosion(Matrix extends PArray> 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 extends UpdatablePArray> dilation(Matrix extends PArray> 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 extends UpdatablePArray> erosion(Matrix extends PArray> 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 extends UpdatablePArray> dilation(
Matrix extends PArray> 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 extends UpdatablePArray> erosion(
Matrix extends PArray> 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 extends UpdatablePArray> dest, Matrix extends PArray> 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 extends UpdatablePArray> dest, Matrix extends PArray> 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 extends UpdatablePArray> dest, Matrix extends PArray> 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 extends UpdatablePArray> dest, Matrix extends PArray> 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 extends UpdatablePArray> dilationErosion(
Matrix extends PArray> 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 extends UpdatablePArray> erosionDilation(
Matrix extends PArray> 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 extends UpdatablePArray> closing(
Matrix extends PArray> 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 extends UpdatablePArray> opening(
Matrix extends PArray> 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 extends UpdatablePArray> weakDilation(Matrix extends PArray> 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 extends UpdatablePArray> weakErosion(Matrix extends PArray> 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
* P
1=-P
+p1={p1-p,
* p∈P
}. Note: the origin 0∈P
1
* (the case p=p1). We have P
1⊂A
* (statement A), so,
* for all q∈Q
we have p2-q∉P
1
* (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∈P
1 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 extends UpdatablePArray> maskedDilationErosion(
Matrix extends PArray> 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 extends UpdatablePArray> maskedErosionDilation(
Matrix extends PArray> 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 extends UpdatablePArray> beucherGradient(Matrix extends PArray> src, Pattern pattern);
}