Filtering » Morphological filtering module

Morphological filters for smoothing, sharpening, detection and more.

Contents

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 by marker.
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 with polarity="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 with polarity="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:

\[ \phi_{B,\text{rank}} = \bigwedge_i \{ \phi_{B_i} | B_i \subseteq B, \text{card}(B_i) = n-\text{rank} \} \; , \]

which is identical to

\[ \phi_{B,\text{rank}} = I \vee \epsilon_{\check{B}} \xi_{B,n-\text{rank}} \; . \]

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!):

\[ \gamma_{B,\text{rank}} = \bigvee_i \{ \gamma_{B_i} | B_i \subseteq B, \text{card}(B_i) = n-\text{rank} \} \; , \]

which is identical to

\[ \gamma_{B,\text{rank}} = I \wedge \delta_{\check{B}} \xi_{B,\text{rank}+1} \; . \]

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 \(g_p > g_q\) , then \(f_p \geq g_p\) and \(g_q \geq f_q\) , with \(g\) the leveling of \(f\) , and \(p\) , \(q\) any two locations within the image. That is, for any edge remaining in \(g\) , there exists an edge of equal or larger magnitude in \(f\) .

The leveling can be obtained by initializing \(g\) to the marker image and iteratively applying

\[ g = (f \wedge \delta g) \vee \epsilon g \]

until idempotence ( \(g\) 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 \(O(n \log(n))\) time, with \(n\) 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:

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.