Labeled regions module
Label connected components and process labeled images.
Labeled images are of any unsigned integer type.
Classes
-
class dip::
LabelMap - Represents a set of labels (object IDs), and maps them to new ones.
Functions
-
auto dip::
Label(dip::Image const& binary, dip::Image& out, dip::uint connectivity = 0, dip::uint minSize = 0, dip::uint maxSize = 0, dip::StringArray boundaryCondition = {}, dip::String const& mode = S::ALL) -> dip::uint - Labels the connected components in a binary image
-
auto dip::
ListObjectLabels(dip::Image const& label, dip::Image const& mask = {}, dip::String const& background = S::EXCLUDE, dip::String const& region = "") -> std::vector<LabelType> - Gets a list of object labels in the labeled image. A labeled image must be of an unsigned type.
-
void dip::
Relabel(dip::Image const& label, dip::Image& out) - Re-assigns labels to objects in a labeled image, such that all labels are consecutive.
-
void dip::
Relabel(dip::Image const& label, dip::Image& out, dip::Graph const& graph) - Re-assigns labels to objects in a labeled image, such that regions joined by an edge in
graph
obtain the same label. -
void dip::
SmallObjectsRemove(dip::Image const& in, dip::Image& out, dip::uint threshold, dip::uint connectivity = 0) - Removes small objects from a labeled or binary image.
-
void dip::
GrowRegions(dip::Image const& label, dip::Image const& mask, dip::Image& out, dip::sint connectivity = -1, dip::uint iterations = 0) - Grow (dilate) labeled regions uniformly.
-
void dip::
GrowRegionsWeighted(dip::Image const& label, dip::Image const& grey, dip::Image const& mask, dip::Image& out, dip::dfloat distance = infinity) - Grow labeled regions with a speed function given by a grey-value image.
-
void dip::
SplitRegions(dip::Image const& label, dip::Image& out, dip::uint connectivity = 0) - Ensures a gap between regions with unequal labels.
-
void dip::
MakeRegionsConvex2D(dip::Image const& label, dip::Image& out, dip::String const& mode = S::FILLED) - Make each object a single, convex shape.
-
auto dip::
GetLabelBoundingBox(dip::Image const& label, dip::LabelType objectID) -> dip::RangeArray - Returns the bounding box for all pixels with label
objectID
in the labeled or binary imagelabel
. -
auto dip::
RegionAdjacencyGraph(dip::Image const& labels, dip::String const& mode = "touching") -> dip::Graph - Construct a graph for the given labeled image.
-
auto dip::
RegionAdjacencyGraph(dip::Image const& labels, dip::Measurement::IteratorFeature const& featureValues, dip::String const& mode = "touching") -> dip::Graph - Construct a graph for the given labeled image.
Operators
-
auto dip::
operator&(dip::LabelMap lhs, dip::LabelMap const& rhs) -> dip::LabelMap - Combines two maps using logical AND. See
operator&=
. -
auto dip::
operator|(dip::LabelMap lhs, dip::LabelMap const& rhs) -> dip::LabelMap - Combines two maps using logical OR. See
operator|=
. -
auto dip::
operator^(dip::LabelMap lhs, dip::LabelMap const& rhs) -> dip::LabelMap - Combines two maps using logical XOR. See
operator^=
. -
auto dip::
operator~(dip::LabelMap rhs) -> dip::LabelMap - Applies logical NOT to the map. See
dip::LabelMap::Negate
.
Function documentation
dip::uint
dip:: Label(dip::Image const& binary,
dip::Image& out,
dip::uint connectivity = 0,
dip::uint minSize = 0,
dip::uint maxSize = 0,
dip::StringArray boundaryCondition = {},
dip::String const& mode = S::ALL)
#include "diplib/regions.h"
Labels the connected components in a binary image
The output is an unsigned integer image. Each object (respecting the connectivity, see Connectivity) in the input image receives a unique number. This number ranges from 1 to the number of objects in the image. The pixels in the output image corresponding to a given object are set to this number (label). The remaining pixels in the output image are set to 0.
The minSize
and maxSize
set limits on the size of the objects: Objects smaller than minSize
or larger than maxSize
do not receive a label and the corresponding pixels in the output
image are set to zero. Setting either to zero disables the corresponding check. Setting both
to zero causes all objects to be labeled, irrespective of size.
The boundaryCondition
array contains a boundary condition string per image dimension, or one
string to be used for all dimensions. Valid strings are:
""
and"mirror"
: the default behavior, causing the labeling to simply stop at the edges."periodic"
: imposing a periodic boundary condition, such that objects touching opposite edges of the image are considered the same object."remove"
: causing objects that touch the image edge to be removed.
boundaryCondition
can also be an empty array, using the default behavior for all dimensions.
mode
can be "all"
(default) or "largest"
. If set to "largest"
, only the largest object
is retained, and will have a label of 1.
Returns the number of connected components found. The returned value is thus the maximum value in the output image.
std::vector<LabelType>
dip:: ListObjectLabels(dip::Image const& label,
dip::Image const& mask = {},
dip::String const& background = S::EXCLUDE,
dip::String const& region = "")
#include "diplib/regions.h"
Gets a list of object labels in the labeled image. A labeled image must be of an unsigned type.
If background
is "include"
, the label ID 0 will be included in the result if present in the image.
Otherwise, background
is "exclude"
, and the label ID 0 will be ignored.
If region
is "edges"
, only the labels of objects touching the image edges will be listed. By default,
the labels of all objects are listed.
void
dip:: Relabel(dip::Image const& label,
dip::Image& out)
#include "diplib/regions.h"
Re-assigns labels to objects in a labeled image, such that all labels are consecutive.
Note that disjoint objects will remain disjoint, as this function only replaces each label ID with
a new value. The output image will have consecutive label IDs, in the range [1, N], with N the
number of unique labels in label
. Pixels with a value of 0 will remain 0 (background).
dip::GetObjectLabels
returns a list of unique labels in label
, and can be used to determine N.
void
dip:: Relabel(dip::Image const& label,
dip::Image& out,
dip::Graph const& graph)
#include "diplib/regions.h"
Re-assigns labels to objects in a labeled image, such that regions joined by an edge in graph
obtain the same label.
graph
should be obtained through dip::RegionAdjacencyGraph
and modified to obtain a useful segmentation.
For example:
dip::Image input = ... dip::Image label = dip::Watershed( dip::GradientMagnitude( input, { 2 } ), {}, 2, 1, 0, { "labels" } ); dip::MeasurementTool measurementTool; auto msr = measurementTool.Measure( label, input, { "Mean" } ); dip::Graph graph = RegionAdjacencyGraph( label, msr[ "Mean" ], "watershed" ); graph = graph.MinimumSpanningForest( { 1 } ); // make sure we don't use the unconnected vertex 0 as root. graph.RemoveLargestEdges( 100 ); dip::Relabel( label, label, graph );
void
dip:: SmallObjectsRemove(dip::Image const& in,
dip::Image& out,
dip::uint threshold,
dip::uint connectivity = 0)
#include "diplib/regions.h"
Removes small objects from a labeled or binary image.
If in
is an unsigned integer image, it is assumed to be a labeled image. The size of the objects
are measured using dip::MeasurementTool
, and the labels for the objects with fewer than threshold
pixels are removed. The connectivity
parameter is ignored. Note that if this image contains disjoint
objects (i.e. multiple connected components with the same label), it is the size of the object as a
whole that counts, not the size of individual connected components.
If in
is a binary image, dip::Label
is called with minSize
set to threshold
, and the result
is binarized again. connectivity
is passed to the labeling function.
The operation on a binary image is equivalent to an area opening with parameter threshold
(see dip::AreaOpening
). The same is not true for the labeled image case, if labeled regions
are touching or if objects are disjoint.
void
dip:: GrowRegions(dip::Image const& label,
dip::Image const& mask,
dip::Image& out,
dip::sint connectivity = -1,
dip::uint iterations = 0)
#include "diplib/regions.h"
Grow (dilate) labeled regions uniformly.
The regions in the labeled image label
are dilated iterations
steps, according to connectivity
,
and optionally constrained by mask
. If iterations
is 0, the objects are dilated until no further
change is possible.
If a mask
is given, this is the labeled equivalent to dip::BinaryPropagation
, otherwise it works as
dip::BinaryDilation
on each label. The difference between dip::GrowRegions
and dip::Dilation
(which can also be applied to a labeled image) is that here growing stops when different labels meet,
whereas in a normal dilation, the label with the larger value would grow over the one with the smaller value.
The connectivity
parameter defines the metric, that is, the shape of the structuring element
(see Connectivity). Alternating connectivity is only implemented for 2D and 3D images.
If isotropy in the dilation is very important, or if the image has anisotropic sampling density, use
dip::GrowRegionsWeighted
instead.
void
dip:: GrowRegionsWeighted(dip::Image const& label,
dip::Image const& grey,
dip::Image const& mask,
dip::Image& out,
dip::dfloat distance = infinity)
#include "diplib/regions.h"
Grow labeled regions with a speed function given by a grey-value image.
The regions in the input image label
are grown according to a grey-weighted distance
metric; the weights are given by grey
. The optional mask image mask
limits the
growing. All three images must be scalar. label
must be of an unsigned integer type,
grey
must be real-valued, and mask
must be binary.
If grey
is not forged, uniform weights are assumed. If both grey
and mask
are
not forged, regions will grow according to the Euclidean distances, see below.
out
is of the type dip::DT_LABEL
, and contains the grown regions.
This function works by first computing distances from the labeled pixels using
dip::GreyWeightedDistanceTransform
, or using dip::EuclideanDistanceTransform
if both grey
and mask
are not forged. These distances are limited by distance
.
Then it applies dip::SeededWatershed
.
This function will correctly handle anisotropic sampling densities. Pixel sizes are taken from grey
,
and if it doesn’t have pixel sizes, they are taken from label
. To ignore the sampling density and grow
isotropically, reset the pixel size (dip::Image::ResetPixelSize
) of both images. Note that
these pixel sizes influence the distances computed, and so distance
is affected by these sizes.
void
dip:: SplitRegions(dip::Image const& label,
dip::Image& out,
dip::uint connectivity = 0)
#include "diplib/regions.h"
Ensures a gap between regions with unequal labels.
In the output image, no two regions will be connected according to connectivity
. out
is of the same
type as label
, which must be an unsigned integer type, and scalar.
To create a one-pixel gap between regions, regions must shrink, and they must shrink unequally. If all regions were to shrink equally, we would create a two-pixel gap. This function chooses to be biased towards larger-valued labels: where two objects touch, the lower-valued region shrinks.
This function works by finding pixels that have a neighbor with a larger value, and setting these pixels to zero (the background label).
void
dip:: MakeRegionsConvex2D(dip::Image const& label,
dip::Image& out,
dip::String const& mode = S::FILLED)
#include "diplib/regions.h"
Make each object a single, convex shape.
For each label, it finds the convex hull and draws it into the image. Where the convex hulls of objects overlaps, the larger label prevails, meaning that the other object might not be convex any more where the larger label overlaps it.
mode
can be "filled"
(the default) or "hollow"
. With "hollow"
, the convex hull outlines are drawn
into an empty image, such that overlapping convex hulls can be visually identified. With "filled"
, the
operation is increasing (like a morphological closing), meaning that out >= label
is guaranteed.
Note that defining a convex hull in a discrete space is ambiguous, and therefore this function is not idempotent (i.e. running it a second time on its own output can produce a different result).
If the input image is binary, a single convex hull is computed and drawn. The output image will be binary also.
The image must have two dimensions, and be scalar.
dip::RangeArray
dip:: GetLabelBoundingBox(dip::Image const& label,
dip::LabelType objectID)
#include "diplib/regions.h"
Returns the bounding box for all pixels with label objectID
in the labeled or binary image label
.
label
must be a labeled image (of type unsigned integer) or binary, and must be scalar and have at least
one dimension.
In the case of a binary image, objectID
should be 1 or 0, no other values are possible in a binary image.
When no pixels with the value objectID
exist in the image, the output dip::RangeArray
will be an
empty array. Otherwise, it will have as many dip::Range
elements as dimensions are in the image.
To obtain the bounding box of all labels at once, use dip::MeasurementTool::Measure
with the
features Minimum and Maximum.
dip::Graph
dip:: RegionAdjacencyGraph(dip::Image const& labels,
dip::String const& mode = "touching")
#include "diplib/regions.h"
Construct a graph for the given labeled image.
Each region (object/label) in the image labels
is a node. Edges represent neighborhood relations between regions.
Because the dip::Graph
class uses the vertex ID as an index into an array, it is recommended that this function
be called with a labeled image where labels are more or less consecutive. If dip::Maximum( labels ).As< dip::uint >()
(i.e. the largest label ID) is much larger than dip::GetObjectLabels( labels ).size()
(i.e. the number of labels),
then the dip::Graph
object will have many unused vertices, and hence waste space. Use dip::Relabel
to modify
the labels
image to have consecutive labels.
mode
indicates how to construct the graph. It can be one of the following strings:
"touching"
: two regions are neighbors if they have at least one pixel that is 1-connected to the other region. That is, the two regions directly touch."watershed"
: two regions are neighbors if there is a background pixel that is 1-connected to the two regions. That is, the two regions are separated by a 1-pixel watershed line. Note that, in this case, two regions that directly touch will not be recognized as neighbors!
In both modes, region with ID 0 (the background) is not included in the graph. But note that there is a vertex with index 0, which will not be connected to any other vertex. To include the background, simply increment the label image by 1.
Edge weights are computed as follows: The fraction of boundary pixels for region 1 that connect to region 2 is determined. The fraction of boundary pixels for region 2 that connect to region 1 is determined. One minus the larger of these two fractions is the edge weight. Thus, edge weights have a value in the half-open interval [0,1). If one of the two regions has a very large fraction of its perimeter connected to another region, then the edge weight is very small to indicate a strong connection.
Vertex values are not assigned.
dip::Graph
dip:: RegionAdjacencyGraph(dip::Image const& labels,
dip::Measurement::IteratorFeature const& featureValues,
dip::String const& mode = "touching")
#include "diplib/regions.h"
Construct a graph for the given labeled image.
This function is similar to the one above, but edge weights are derived from the absolute difference
between featureValues
for the two regions joined by the edge. Vertex values are set to the feature value
for the region.
The input featureValues
is a view over a specific feature in a dip::Measurement
object. Only the
first value of the feature is used. For features with multiple values, select a value using the
dip::Measurement::IteratorFeature::Subset
method, or pick a column in the dip::Measurement
object
directly using dip::Measurement::FeatureValuesView
.
For the labels that do not appear in featureValues
, their vertex value will be set to 0.
dip::LabelMap
dip:: operator&(dip::LabelMap lhs,
dip::LabelMap const& rhs)
#include "diplib/label_map.h"
Combines two maps using logical AND. See operator&=
.
dip::LabelMap
dip:: operator|(dip::LabelMap lhs,
dip::LabelMap const& rhs)
#include "diplib/label_map.h"
Combines two maps using logical OR. See operator|=
.
dip::LabelMap
dip:: operator^(dip::LabelMap lhs,
dip::LabelMap const& rhs)
#include "diplib/label_map.h"
Combines two maps using logical XOR. See operator^=
.
dip::LabelMap
dip:: operator~(dip::LabelMap rhs)
#include "diplib/label_map.h"
Applies logical NOT to the map. See dip::LabelMap::Negate
.