module #include "diplib/morphology.h"
Morphological filtering Morphological filters for smoothing, sharpening, detection and more.
Classes
-
class dip::
StructuringElement - Represents the shape and size of a structuring element.
Functions
-
void dip::
Dilation(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::StringArray const& boundaryCondition = {}) - Applies the dilation.
-
void dip::
Erosion(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::StringArray const& boundaryCondition = {}) - Applies the erosion with a standard structuring element.
-
void dip::
Closing(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::StringArray const& boundaryCondition = {}) - Applies the closing with a standard structuring element.
-
void dip::
Opening(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::StringArray const& boundaryCondition = {}) - Applies the opening with a standard structuring element.
-
void dip::
Tophat(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::String const& edgeType = S::TEXTURE, dip::String const& polarity = S::WHITE, dip::StringArray const& boundaryCondition = {}) - The Top-hat operator and its variants
-
void dip::
MorphologicalThreshold(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::String const& edgeType = S::TEXTURE, dip::StringArray const& boundaryCondition = {}) - A morphological smoothing filter
-
void dip::
MorphologicalGist(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::String const& edgeType = S::TEXTURE, dip::StringArray const& boundaryCondition = {}) - Morphological gist operator and its variants
-
void dip::
MorphologicalRange(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::String const& edgeType = S::TEXTURE, dip::StringArray const& boundaryCondition = {}) - A morphological edge detector
-
void dip::
MorphologicalGradientMagnitude(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::StringArray const& boundaryCondition = {}) - The morphological version of the gradient magnitude
-
void dip::
Lee(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::String const& edgeType = S::TEXTURE, dip::String const& sign = S::UNSIGNED, dip::StringArray const& boundaryCondition = {}) - A morphological edge detector
-
void dip::
MorphologicalSmoothing(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::String const& polarity = S::AVERAGE, dip::StringArray const& boundaryCondition = {}) - A morphological smoothing filter
-
void dip::
MorphologicalSharpening(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::StringArray const& boundaryCondition = {}) - A morphological sharpening filter
-
void dip::
MultiScaleMorphologicalGradient(dip::Image const& in, dip::Image& out, dip::uint upperSize = 9, dip::uint lowerSize = 3, dip::String const& filterShape = S::ELLIPTIC, dip::StringArray const& boundaryCondition = {}) - A morphological edge detector
-
void dip::
MorphologicalLaplace(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::StringArray const& boundaryCondition = {}) - The morphological version of the Laplace operator
-
void dip::
RankFilter(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::uint rank = 2, dip::String const& order = S::INCREASING, dip::StringArray const& boundaryCondition = {}) - Applies the rank-order filter.
-
void dip::
RankMinClosing(dip::Image const& in, dip::Image& out, dip::StructuringElement se = {}, dip::uint rank = 2, dip::StringArray const& boundaryCondition = {}) - Applies the rank-min closing, a closing that is somewhat robust to noise.
-
void dip::
RankMaxOpening(dip::Image const& in, dip::Image& out, dip::StructuringElement se = {}, dip::uint rank = 2, dip::StringArray const& boundaryCondition = {}) - Applies the rank-max opening, an opening that is somewhat robust to noise.
-
void dip::
StochasticWatershed(dip::Image const& in, dip::Image& out, dip::uint nSeeds = 100, dip::uint nIterations = 50, dip::dfloat noise = 0, dip::String const& seeds = S::HEXAGONAL) - Like above, using a default-initialized
dip::Random
object. -
void dip::
UpperSkeleton2D(dip::Image const& in, dip::Image const& mask, dip::Image& out, dip::String const& endPixelCondition = S::NATURAL) - Grey-value skeleton (2D only).
-
void dip::
MorphologicalReconstruction(dip::Image const& marker, dip::Image const& in, dip::Image& out, dip::uint connectivity = 0, dip::String const& direction = S::DILATION) - Reconstruction by dilation or erosion, also known as inf-reconstruction and sup-reconstruction
-
void dip::
LimitedMorphologicalReconstruction(dip::Image const& marker, dip::Image const& in, dip::Image& out, dip::dfloat maxDistance = 20, dip::uint connectivity = 0, dip::String const& direction = S::DILATION) - Reconstruction by dilation or erosion, but with a limited reach.
-
void dip::
HMinima(dip::Image const& in, dip::Image& out, dip::dfloat h, dip::uint connectivity = 0) - Computes the H-Minima filtered image
-
void dip::
HMaxima(dip::Image const& in, dip::Image& out, dip::dfloat h, dip::uint connectivity = 0) - Computes the H-Maxima filtered image
-
void dip::
ImposeMinima(dip::Image const& in, dip::Image const& marker, dip::Image& out, dip::uint connectivity = 0) - Impose minima.
-
void dip::
Leveling(dip::Image const& in, dip::Image const& marker, dip::Image& out, dip::uint connectivity = 0) - The leveling of
in
imposed bymarker
. -
void dip::
AreaOpening(dip::Image const& in, dip::Image const& mask, dip::Image& out, dip::uint filterSize, dip::uint connectivity = 0, dip::String const& polarity = S::OPENING) - Computes the area opening or closing. This is a parametric opening.
-
void dip::
AreaClosing(dip::Image const& in, dip::Image const& mask, dip::Image& out, dip::uint filterSize, dip::uint connectivity = 0) - Computes the area closing, calling
dip::AreaOpening
withpolarity="closing"
. -
void dip::
VolumeOpening(dip::Image const& in, dip::Image const& mask, dip::Image& out, dip::dfloat filterSize, dip::uint connectivity = 0, dip::String const& polarity = S::OPENING) - Computes the volume opening or closing. This is a parametric opening.
-
void dip::
VolumeClosing(dip::Image const& in, dip::Image const& mask, dip::Image& out, dip::dfloat filterSize, dip::uint connectivity = 0) - Computes the area closing, calling
dip::VolumeOpening
withpolarity="closing"
. -
void dip::
PathOpening(dip::Image const& in, dip::Image const& mask, dip::Image& out, dip::uint length = 7, dip::String const& polarity = S::OPENING, dip::StringSet const& mode = {}) - Applies a path opening or closing in all possible directions
-
void dip::
DirectedPathOpening(dip::Image const& in, dip::Image const& mask, dip::Image& out, dip::IntegerArray filterParam, dip::String const& polarity = S::OPENING, dip::StringSet const& mode = {}) - Applies a path opening or closing in a specific direction.
-
void dip::
OpeningByReconstruction(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::uint connectivity = 0, dip::StringArray const& boundaryCondition = {}) - Opening by reconstruction
-
void dip::
ClosingByReconstruction(dip::Image const& in, dip::Image& out, dip::StructuringElement const& se = {}, dip::uint connectivity = 0, dip::StringArray const& boundaryCondition = {}) - Closing by reconstruction
-
void dip::
AlternatingSequentialFilter(dip::Image const& in, dip::Image& out, dip::Range const& sizes = {3,7,2}, dip::String const& shape = S::ELLIPTIC, dip::String const& mode = S::STRUCTURAL, dip::String const& polarity = S::OPENCLOSE, dip::StringArray const& boundaryCondition = {}) - Alternating sequential filters for smoothing
-
void dip::
HitAndMiss(dip::Image const& in, dip::Image& out, dip::StructuringElement const& hit, dip::StructuringElement const& miss, dip::String const& mode = S::UNCONSTRAINED, dip::StringArray const& boundaryCondition = {}) - The Hit-and-Miss transform, uses two structuring elements,
hit
must be within the structures,miss
must be without. -
void dip::
HitAndMiss(dip::Image const& in, dip::Image& out, dip::Image const& se, dip::String const& mode = S::UNCONSTRAINED, dip::StringArray const& boundaryCondition = {}) - The Hit-and-Miss transform, uses a single structuring element in the form of a small image that has “hit”, “miss” and “don’t care” values.
Function documentation
void
dip:: Dilation(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::StringArray const& boundaryCondition = {})
Applies the dilation.
se
defines the structuring element, see dip::StructuringElement
for options and details.
boundaryCondition
determines the boundary conditions. See dip::BoundaryCondition
.
The default value, and most meaningful one, is "add min"
, but any value can be used.
For the rectangular, diamond, fast line and periodic line structuring elements, no boundary condition
causes the filter to not read outside the image bounds. This is equivalent to "add min"
.
in
must be a scalar image, and not complex-valued. In particular, in
can be binary; this function
is more efficient than dip::BinaryDilation
.
void
dip:: Erosion(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::StringArray const& boundaryCondition = {})
Applies the erosion with a standard structuring element.
se
defines the structuring element. See dip::Dilation
for details and warnings.
boundaryCondition
determines the boundary conditions. See dip::BoundaryCondition
.
The default value, and most meaningful one, is "add max"
, but any value can be used.
For the rectangular, diamond, fast line and periodic line structuring elements, no boundary condition
causes the filter to not read outside the image bounds. This is equivalent to "add max"
.
in
must be a scalar image, and not complex-valued. In particular, in
can be binary; this function
is more efficient than dip::BinaryErosion
.
void
dip:: Closing(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::StringArray const& boundaryCondition = {})
Applies the closing with a standard structuring element.
se
defines the structuring element. See dip::Dilation
for details and warnings.
boundaryCondition
determines the boundary conditions. See dip::BoundaryCondition
.
Meaningful values for the closing are "add max"
and "add min"
, but any value can
be used. The default empty array causes the function to use "add min"
with the dilation
and "add max"
with the erosion, equivalent to ignoring what’s outside the image.
For the rectangular, diamond, fast line and periodic line structuring elements, no boundary condition
causes the filter to not read outside the image bounds.
in
must be a scalar image, and not complex-valued. In particular, in
can be binary; this function
is more efficient than dip::BinaryClosing
.
void
dip:: Opening(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::StringArray const& boundaryCondition = {})
Applies the opening with a standard structuring element.
se
defines the structuring element. See dip::Dilation
for details and warnings.
boundaryCondition
determines the boundary conditions. See dip::BoundaryCondition
.
Meaningful values for the opening are "add max"
and "add min"
, but any value can
be used. The default empty array causes the function to use "add min"
with the dilation
and "add max"
with the erosion, equivalent to ignoring what’s outside the image.
For the rectangular, diamond, fast line and periodic line structuring elements, no boundary condition
causes the filter to not read outside the image bounds.
in
must be a scalar image, and not complex-valued. In particular, in
can be binary; this function
is more efficient than dip::BinaryOpening
.
void
dip:: Tophat(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::String const& edgeType = S::TEXTURE,
dip::String const& polarity = S::WHITE,
dip::StringArray const& boundaryCondition = {})
The Top-hat operator and its variants
The top-hat is the difference between a morphological operation and the original image,
comparable to a high-pass filter. The flags edgeType
and polarity
define which
operation is applied.
edgeType
can be one of:
"texture"
: response is limited to edges in texture (i.e. scales smaller than the structuring element)."object"
: response is limited to object edges (i.e. scales larger than the structuring element)."both"
or"dynamic"
: all edges produce equal response.
polarity
can be either "white"
to indicate objects are brighter than the background, or "black"
to
indicate objects are darker than the background.
The standard top-hat is defined as the Opening( in ) - in
. This is the operation obtained
with the default values.
se
defines the structuring element, and boundaryCondition
the boundary conditions.
See dip::Dilation
for a description of these parameters.
void
dip:: MorphologicalThreshold(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::String const& edgeType = S::TEXTURE,
dip::StringArray const& boundaryCondition = {})
A morphological smoothing filter
Implements a morphological smoothing based on the average of two complementary morphological operations.
These can be chosen through the edgeType
parameter.
edgeType
can be one of:
"texture"
: response is limited to edges in texture (i.e. scales smaller than the structuring element)."object"
: response is limited to object edges (i.e. scales larger than the structuring element)."both"
or"dynamic"
: all edges produce equal response.
se
defines the structuring element, and boundaryCondition
the boundary conditions.
See dip::Dilation
for a description of these parameters.
void
dip:: MorphologicalGist(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::String const& edgeType = S::TEXTURE,
dip::StringArray const& boundaryCondition = {})
Morphological gist operator and its variants
Similar to the top-hat operator, it computes the difference between the average of two complementary morphological operators and the original image.
The flags edgeType
defines which operation is applied:
"texture"
: response is limited to edges in texture (i.e. scales smaller than the structuring element)."object"
: response is limited to object edges (i.e. scales larger than the structuring element)."both"
or"dynamic"
: all edges produce equal response.
se
defines the structuring element, and boundaryCondition
the boundary conditions.
See dip::Dilation
for a description of these parameters.
void
dip:: MorphologicalRange(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::String const& edgeType = S::TEXTURE,
dip::StringArray const& boundaryCondition = {})
A morphological edge detector
Implements a morphological edge detector based on the difference of two complementary morphological
operations. These can be chosen through the edgeType
parameter.
edgeType
can be one of:
"texture"
: response is limited to edges in texture (i.e. scales smaller than the structuring element)."object"
: response is limited to object edges (i.e. scales larger than the structuring element)."both"
or"dynamic"
: all edges produce equal response.
se
defines the structuring element, and boundaryCondition
the boundary conditions.
See dip::Dilation
for a description of these parameters.
void
dip:: MorphologicalGradientMagnitude(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::StringArray const& boundaryCondition = {})
The morphological version of the gradient magnitude
The morphological gradient magnitude is defined as Dilation( in ) - Erosion( in )
.
This function is implemented by a call to dip::MorphologicalRange
with edgeType
set to "both"
.
void
dip:: Lee(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::String const& edgeType = S::TEXTURE,
dip::String const& sign = S::UNSIGNED,
dip::StringArray const& boundaryCondition = {})
A morphological edge detector
Implements a morphological edge detector based on the minimum of two complementary morphological
operations. These can be chosen through the edgeType
parameter.
edgeType
can be one of:
"texture"
: response is limited to edges in texture (i.e. scales smaller than the structuring element)."object"
: response is limited to object edges (i.e. scales larger than the structuring element)."both"
or"dynamic"
: all edges produce equal response.
If sign
is "unsigned"
, Lee
computes the absolute edge strength. sign
can also be "signed"
to compute the signed edge strength.
se
defines the structuring element, and boundaryCondition
the boundary conditions.
See dip::Dilation
for a description of these parameters.
void
dip:: MorphologicalSmoothing(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::String const& polarity = S::AVERAGE,
dip::StringArray const& boundaryCondition = {})
A morphological smoothing filter
Implements a morphological smoothing based on the sequence of an opening and a closing. Their order
can be chosen through the polarity
parameter.
polarity
can be one of:
"open-close"
: applies the opening first, then the closing."close-open"
: applies the closing first, then the opening."average"
: computes the average of the result of the first two modes.
se
defines the structuring element, and boundaryCondition
the boundary conditions.
See dip::Dilation
for a description of these parameters..
void
dip:: MorphologicalSharpening(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::StringArray const& boundaryCondition = {})
A morphological sharpening filter
Implements a morphological sharpening based on selecting per pixel the result of the dilation or erosion, whichever is closest to the input image.
se
defines the structuring element, and boundaryCondition
the boundary conditions.
See dip::Dilation
for a description of these parameters..
void
dip:: MultiScaleMorphologicalGradient(dip::Image const& in,
dip::Image& out,
dip::uint upperSize = 9,
dip::uint lowerSize = 3,
dip::String const& filterShape = S::ELLIPTIC,
dip::StringArray const& boundaryCondition = {})
A morphological edge detector
This function computes the average morphological gradient over a range of scales bounded by upperSize
and lowerSize
. The morphological gradient is computed as the difference of the dilation and erosion
of the input image at a particular scale, eroded by an erosion of one size smaller. At the lowest scale,
the diameter of the structuring element is 2 * lowerSize + 1
.
filterShape
can be either "rectangular"
, "elliptic"
, and "diamond"
, as described in
dip::StructuringElement
.
boundaryCondition
determines the boundary conditions. See dip::BoundaryCondition
.
The default empty array causes the function to use "add min"
with the dilation
and "add max"
with the erosion, equivalent to ignoring what’s outside the image.
void
dip:: MorphologicalLaplace(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::StringArray const& boundaryCondition = {})
The morphological version of the Laplace operator
This function computes:
out = ( Dilation( in ) + Erosion( in ) ) / 2 - in;
se
defines the structuring element, and boundaryCondition
the boundary conditions.
See dip::Dilation
for a description of these parameters.
void
dip:: RankFilter(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::uint rank = 2,
dip::String const& order = S::INCREASING,
dip::StringArray const& boundaryCondition = {})
Applies the rank-order filter.
se
defines the structuring element. rank
determines which of the sorted values within
the SE should be written to the output. A rank of 1 leads to an erosion, and a rank equal
to the number of pixels within the SE leads to a dilation. If order
is "decreasing"
(instead
of the default "increasing"
), then rank
is interpreted in the opposite direction, it
counts elements starting at the largest value. In this case, a rank of 1 is equal to a dilation.
Thus, a small non-zero rank with increasing order leads to an approximation to the dilation that is less sensitive to noise, and a small non-zero rank with decreasing order leads to an approximation of the erosion.
See also dip::PercentileFilter
, which does the same thing but uses a percentile instead of
a rank as input argument.
boundary
determines the boundary conditions. See dip::BoundaryCondition
.
The default value is the most meaningful one, but any value can be used. By default it is
"add max"
if rank
is lower than half of the pixels in the SE, or "add min"
otherwise.
void
dip:: RankMinClosing(dip::Image const& in,
dip::Image& out,
dip::StructuringElement se = {},
dip::uint rank = 2,
dip::StringArray const& boundaryCondition = {})
Applies the rank-min closing, a closing that is somewhat robust to noise.
se
defines the structuring element. rank
determines how many pixels in the SE
are ignored. That is, if the SE has n
pixels, then a rank filter with rank equal
to n - rank
is applied instead of a dilation.
This function uses the definition of Soille:
which is identical to
boundary
determines the boundary conditions. See dip::BoundaryCondition
.
The default empty array causes the function to use "add min"
with the rank filter,
and "add max"
with the erosion, equivalent to ignoring what’s outside the image.
void
dip:: RankMaxOpening(dip::Image const& in,
dip::Image& out,
dip::StructuringElement se = {},
dip::uint rank = 2,
dip::StringArray const& boundaryCondition = {})
Applies the rank-max opening, an opening that is somewhat robust to noise.
se
defines the structuring element. rank
determines how many pixels in the SE
are ignored. That is, a rank filter with rank equal rank + 1
is applied instead of an
erosion.
This function uses the definition of Soille (ref!):
which is identical to
boundary
determines the boundary conditions. See dip::BoundaryCondition
.
The default empty array causes the function to use "add min"
with the dilation,
and "add max"
with the rank filter, equivalent to ignoring what’s outside the image.
void
dip:: UpperSkeleton2D(dip::Image const& in,
dip::Image const& mask,
dip::Image& out,
dip::String const& endPixelCondition = S::NATURAL)
Grey-value skeleton (2D only).
This algorithm finds ridges in the image by, starting at the lowest values, setting values to the minimum possible value for the given data type if that doesn’t change the topology of the higher-valued pixels. It uses Hilditch conditions to preserve topology. The unmodified pixels are the grey-value equivalent to a binary skeleton. Note that the minimum possible value is minus infinity for floating-point types.
The mask
image optionally restricts the region of the image processed. Pixels not selected by the mask will
retain their original value.
The endPixelCondition
parameter determines what is considered an “end pixel” in the skeleton, and thus affects
how many branches are generated. It is one of the following strings:
"natural"
: “natural” end pixel condition of this algorithm."one neighbor"
: Keep endpoint if it has one neighbor."two neighbors"
: Keep endpoint if it has two neighbors."three neighbors"
: Keep endpoint if it has three neighbors.
To generate skeletons without end pixels (the equivalent of "loose ends away"
in dip::EuclideanSkeleton
),
use dip::Watershed
instead.
in
must be a real-valued, scalar image. out
will have the same type.
void
dip:: MorphologicalReconstruction(dip::Image const& marker,
dip::Image const& in,
dip::Image& out,
dip::uint connectivity = 0,
dip::String const& direction = S::DILATION)
Reconstruction by dilation or erosion, also known as inf-reconstruction and sup-reconstruction
This function has the same effect as iteratively dilating (eroding) the image marker
such that it remains lower
(higher) than in
everywhere, until stability. However, this is implemented with a much more efficiently.
direction
indicates which of the two operations to apply ("dilation"
or "erosion"
).
out
will have the data type of in
, and marker
will be cast to that same type (with clamping to the target
range, see dip::Convert
).
See Connectivity for information on the connectivity parameter.
The algorithm implemented is a hybrid between the method proposed by Vincent (a forward raster scan, followed by a backward raster scan, followed by a LIFO queue propagation method), and that proposed by Robinson and Whelan (a priority queue method). We implement the forward and backward scan, and follow it by a priority queue propagation. The priority queue method has the advantage of visiting each pixels exactly once.
For binary images, this function calls dip::BinaryPropagation
, which uses the same algorithm but is specialized
for the binary case (e.g. using a stack instead of a priority queue).
This functions is used by dip::LimitedMorphologicalReconstruction
, dip::HMinima
, dip::HMaxima
,
dip::Leveling
, dip::OpeningByReconstruction
, dip::ClosingByReconstruction
void
dip:: LimitedMorphologicalReconstruction(dip::Image const& marker,
dip::Image const& in,
dip::Image& out,
dip::dfloat maxDistance = 20,
dip::uint connectivity = 0,
dip::String const& direction = S::DILATION)
Reconstruction by dilation or erosion, but with a limited reach.
Performs the same function as dip::MorphologicalReconstruction
, but limiting the
reach of the operation to maxDistance
pixels. This is an Euclidean distance, and
determines the zone of influence of each value in marker
. The limited reach is
accomplished by updating in
, rather than counting propagation steps.
See dip::MorphologicalReconstruction
for the meaning of the rest of the parameters,
and more information about the algorithm.
void
dip:: HMinima(dip::Image const& in,
dip::Image& out,
dip::dfloat h,
dip::uint connectivity = 0)
Computes the H-Minima filtered image
The H-Minima filtered image has all local minima with a depth less than h
removed:
HMinima = dip::MorphologicalReconstruction( in + h, in, connectivity, "erosion" );
void
dip:: HMaxima(dip::Image const& in,
dip::Image& out,
dip::dfloat h,
dip::uint connectivity = 0)
Computes the H-Maxima filtered image
The H-Maxima filtered image has all local maxima with a height less than h
removed:
HMaxima = dip::MorphologicalReconstruction( in - h, in, connectivity, "dilation" );
void
dip:: ImposeMinima(dip::Image const& in,
dip::Image const& marker,
dip::Image& out,
dip::uint connectivity = 0)
Impose minima.
Regions in marker
will be the only local minima in in
: dip::Minima( dip::ImposeMinima( a, b )) == b
, for any a
.
The image in
will be modified such that the regions marked by marker
obtain the lowest possible value for the
given data type, and any other local minima in in
are filled in to become plateaus. Minimum imposition is typically
applied in conjunction with the watershed to reduce the number of regions created. The function dip::SeededWatershed
has a similar result, but obtained in a different way, to applying dip::Watershed
to the output of ImposeMinima
.
void
dip:: Leveling(dip::Image const& in,
dip::Image const& marker,
dip::Image& out,
dip::uint connectivity = 0)
The leveling of in
imposed by marker
.
The leveling introduces flat zones in the image, in such a way that, if , then and , with the leveling of , and , any two locations within the image. That is, for any edge remaining in , there exists an edge of equal or larger magnitude in .
The leveling can be obtained by initializing to the marker
image and iteratively applying
until idempotence ( doesn’t change any further). However, here it is implemented more efficiently
using dip::MorphologicalReconstruction
.
The marker
image can be a smoothed version of in
, then the leveling yields a similar simplification as
the smoothing, but preserving sharp edges.
void
dip:: AreaOpening(dip::Image const& in,
dip::Image const& mask,
dip::Image& out,
dip::uint filterSize,
dip::uint connectivity = 0,
dip::String const& polarity = S::OPENING)
Computes the area opening or closing. This is a parametric opening.
The area opening removes all local maxima that have an area smaller than the given parameter filterSize
,
and is equivalent to the supremum of openings with all possible connected flat structuring elements of that area.
The output has all maxima being connected components with a size of at least filterSize
. The area closing is the
dual operation.
Note that we refer to “area” here as the number of pixels, which readily extends to any number of dimensions.
in
must be scalar and real-valued or binary.
mask
restricts the image regions used for the operation.
connectivity
determines what a connected component is. See Connectivity for information on the
connectivity parameter.
polarity
can be "opening"
(the default) or "closing"
, to compute the area opening or area closing, respectively.
We use a union-find implementation similar to that described my Meijster and Wilkinson (2002), and is based on
the algorithm for our fast watershed ("fast"
mode to dip::Watershed
). For binary images, this function calls
dip::BinaryAreaOpening
or dip::BinaryAreaClosing
.
void
dip:: VolumeOpening(dip::Image const& in,
dip::Image const& mask,
dip::Image& out,
dip::dfloat filterSize,
dip::uint connectivity = 0,
dip::String const& polarity = S::OPENING)
Computes the volume opening or closing. This is a parametric opening.
The volume opening removes all local maxima that have a volume smaller than the given parameter filterSize
. The
“volume” is the integral over the pixel values, offset by the graylevel at which the maximum is cut.
The volume closing is the dual operation.
Comparing to the area opening, which removes peaks by the area of their support, this function removes peaks by
the volume being removed. The difference of the opening with the input image, in the case of the area opening,
is a series of peaks, each of which less than filterSize
pixels, surrounded by zero-valued pixels.
In the case of the volume opening, these peaks all have an integral (sum of pixel values) of less than filterSize
.
in
must be scalar and real-valued. Binary images are not allowed.
mask
restricts the image regions used for the operation.
connectivity
determines what a connected component is. See Connectivity for information on the
connectivity parameter.
polarity
can be "opening"
(the default) or "closing"
, to compute the area opening or area closing, respectively.
We use a union-find implementation similar to that described my Meijster and Wilkinson (2002), and is based on
the algorithm for our fast watershed ("fast"
mode to dip::Watershed
).
void
dip:: PathOpening(dip::Image const& in,
dip::Image const& mask,
dip::Image& out,
dip::uint length = 7,
dip::String const& polarity = S::OPENING,
dip::StringSet const& mode = {})
Applies a path opening or closing in all possible directions
length
is the length of the path. All filterParam
arguments to dip::DirectedPathOpening
that yield a
length of length
pixels and represent unique directions are generated, and the directed path opening or closing
is computed for each of them. The supremum (when polarity
is "opening"
) or infimum (when it is "closing"
) is
computed over all results. See dip::DirectedPathOpening
for a description of the algorithm and the parameters.
void
dip:: DirectedPathOpening(dip::Image const& in,
dip::Image const& mask,
dip::Image& out,
dip::IntegerArray filterParam,
dip::String const& polarity = S::OPENING,
dip::StringSet const& mode = {})
Applies a path opening or closing in a specific direction.
The path opening is an opening over all possible paths of a specific length and general direction. A path direction represents a 90 degree cone within which paths are generated. The paths are formed by single pixel steps in one of three directions (in 2D): the main direction, or 45 degrees to the left or right. That is, if the main direction is [1,0] (to the right), then [1,-1] and [1,1] (diagonal up or down) are also possible steps. This leads to a number of different paths that is exponential in its lengths. However, the opening over all these paths can be computed in time, with the path length.
The direction description above can be generalized to any number of dimensions by realizing that the main direction can be specified by any of the neighbors of a central pixel, and then the other allowed steps are the neighbor pixels that are also neighbor to the pixel that represents the main direction. In 3D, this leads to 6 or 8 alternate steps.
There are 4 possible path directions in 2D, and 13 in 3D. Both length and direction are specified through
the filterParam
argument, see below. Note that the path length is given by the number of pixels in the path,
not the Euclidean length of the path.
The polarity
parameter can be "opening"
(the default) or "closing"
, to compute the path opening and path
closing, respectively.
When mode
contains "constrained"
, the path construction described above is modified such that, after every alternate
step, a step in the main direction must be taken. This constraint avoids a zig-zag line that causes the path
opening to yield much shorter lines for the diagonal directions if the lines in the image are thicker than one pixel.
See the paper by Luengo referenced below. It also reduces the cone size from 90 degrees to 45 degrees, making the
algorithm more directionally-selective. The constrained mode increases computation time a little, but is highly
recommended when using the path opening in a granulometry. The alternate flag is "unconstrained"
, which is the
default and does not need to be given.
Path openings can be sensitive to noise. If mode
contains "robust"
, a robust path opening or closing is
obtained. A robust path opening is computed by dilating the image with a 2x2 rectangular structuring element,
applying the path opening, then taking the infimum of the result and the input (Merveille, 2018). For a path
closing, the erosion and the supremum are used instead.
void
dip:: OpeningByReconstruction(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::uint connectivity = 0,
dip::StringArray const& boundaryCondition = {})
Opening by reconstruction
Applies a structural erosion followed by a reconstruction by dilation.
See dip::Erosion
and dip::MorphologicalReconstruction
for a description of the parameters.
void
dip:: ClosingByReconstruction(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& se = {},
dip::uint connectivity = 0,
dip::StringArray const& boundaryCondition = {})
Closing by reconstruction
Applies a structural dilation followed by a reconstruction by erosion.
See dip::Dilation
and dip::MorphologicalReconstruction
for a description of the parameters.
void
dip:: AlternatingSequentialFilter(dip::Image const& in,
dip::Image& out,
dip::Range const& sizes = {3,7,2},
dip::String const& shape = S::ELLIPTIC,
dip::String const& mode = S::STRUCTURAL,
dip::String const& polarity = S::OPENCLOSE,
dip::StringArray const& boundaryCondition = {})
Alternating sequential filters for smoothing
Applies alternating sequential filters to in
, using structuring element sizes given by the range sizes
.
Alternating sequential filters are two morphological filters opening and closing, applied in sequence, from
a small size to a larger size. This provides an effective smoothing that is less biased than applying an
opening and closing of a single size (as in dip::MorphologicalSmoothing
).
polarity
can be "open-close"
or "close-open"
, and determines which of the operations is applied first.
For example, if sizes
is {3,7,2}
and polarity
is "open-close"
, the following operations are applied:
dip::Opening( in, out, { 3, shape } ); dip::Closing( out, out, { 3, shape } ); dip::Opening( out, out, { 5, shape } ); dip::Closing( out, out, { 5, shape } ); dip::Opening( out, out, { 7, shape } ); dip::Closing( out, out, { 7, shape } );
mode
is one of:
"structural"
: uses structural openings and closings (seedip::Opening
)."reconstruction"
: uses openings and closings by reconstruction (seedip::OpeningByReconstruction
)."area"
: uses area openings and closings (seedip::AreaOpening
) –shape
is ignored.
void
dip:: HitAndMiss(dip::Image const& in,
dip::Image& out,
dip::StructuringElement const& hit,
dip::StructuringElement const& miss,
dip::String const& mode = S::UNCONSTRAINED,
dip::StringArray const& boundaryCondition = {})
The Hit-and-Miss transform, uses two structuring elements, hit
must be within the structures,
miss
must be without.
For a binary image, the result is the intersection of the erosion of the image with hit
and the erosion of the
inverted image with miss
.
For a grey-value image, there are two definitions of the operator. If mode
is "unconstrained"
, the output is
the difference of the erosion with hit
and the dilation with miss
, with any negative values clipped to 0.
If mode
is "constrained"
, a more restrictive definition is applied (conditions evaluated pixel-wise):
- If
in == erosion(in,hit) && dilation(in,miss) < in
:out = in - dilation(in,miss)
. - If
in == dilation(in,miss) && erosion(in,hit) > in
:out = erosion(in,hit) - in
. - Otherwise:
out = 0
.
Note that the two structuring elements must be disjoint. If one pixel is set in both structuring elements, the output will be all zeros.
See also dip::SupGenerating
for a function specific to binary images.
void
dip:: HitAndMiss(dip::Image const& in,
dip::Image& out,
dip::Image const& se,
dip::String const& mode = S::UNCONSTRAINED,
dip::StringArray const& boundaryCondition = {})
The Hit-and-Miss transform, uses a single structuring element in the form of a small image that has “hit”, “miss” and “don’t care” values.
The hit
SE is se == 1
, the miss
SE is se == 0
. “Don’t care” values are any other value.
See the description for the other dip::HitAndMiss
function for a description of the other parameters.