dip::Measurement class

Contains measurement results, as obtained through dip::MeasurementTool::Measure.

A newly constructed Measurement is raw, and will accept calls to dip::Measurement::AddFeature, dip::Measurement::SetObjectIDs, dip::Measurement::AddObjectID and dip::Measurement::AddObjectIDs. Once the object is set up with all objects and features needed, a call to Forge creates the data segment necessary to hold all those measurements. Once forged, it is no longer possible to add features or objects. As with a dip::Image, the method dip::Measurement::IsForged can be used to test if the object has been forged.

A forged Measurement can be read from in various ways, and a writable pointer to the data can be obtained. As with the dip::Image class, data pointers are always writable, even if the object is const-qualified. This simplifies the code, at the expense of opening the door to undesirable modifications to data. DIPlib will never modify the data of a const Measurement.

The columns of the Measurement table are the feature values. Since each feature can have multiple values, features represent column groups. The rows of the table are the objects.

Indexing with a feature name produces a reference to a column group. Indexing with an object ID (an integer) produces a reference to a row. Each of these references can be indexed to produce a reference to a table cell group. A cell group contains the values produced by one feature for one object. The cell group can again be indexed to obtain each of the values. For example, the following two lines are equivalent, and access the second value of the Feret feature (smallest Feret diameter) for object ID 412:

dip::dfloat width = measurement[ "Feret" ][ 412 ][ 1 ];
dip::dfloat width = measurement[ 412 ][ "Feret" ][ 1 ];

These three types of references are represented as iterators. Thus, it is also possible to iterate over all columns groups (or all rows), iterate over each of the cell groups within a column group (or within a row), and iterate over the values within a cell group:

auto colIt = measurement[ "Feret" ];
auto feretIt = colIt.FirstObject(); // iterator points at Feret value for first object
dip::dfloat sum = 0.0;
while( feretIt ) {
   sum += feretIt[ 1 ]; // read width for current object
   ++feretIt; // iterator points at Feret value for next object
}
dip::dfloat meanWidth = sum / measurement.NumberOfObjects();
auto it = measurement[ "Feret" ][ 412 ];
std::cout << "Feret values for object ID = 412:";
for( auto f : it ) {
   std::cout << ' ' << f;
}
std::cout << '\n';

A Measurement with zero object IDs will never be forged, it is possible to call Forge on it, but nothing will happen. For such an object, it is possible to index with a feature name, and iterate over the features (column groups). However, each of the columns will be empty, such that dip::Measurement::FirstObject returns an invalid iterator (evaluates to false). This means that, given a Measurement obtained from an empty image, one can iterate as usual over features and over objects, without needing to write a special test for the case of an image without objects.

Classes

struct FeatureInformation
Structure containing information about the features stored in a dip::Measurement object
class IteratorFeature
An iterator to visit all features (column groups) in the dip::Measurement table. Can also be seen as a view over a specific feature.
class IteratorObject
An iterator to visit all objects (rows) in the dip::Measurement table. Can also be seen as a view over a specific object.

Aliases

using ValueType = dip::dfloat
The type of the measurement data
using ValueIterator = dip::Measurement::ValueType*
A pointer to measurement data, which we can treat as an iterator

Functions

void AddFeature(dip::String const& name, dip::Feature::ValueInformationArray const& values)
Adds a feature to a raw Measurement object.
void EnsureFeature(dip::String const& name, dip::Feature::ValueInformationArray const& values)
Adds a feature to a raw Measurement object if it is not already there.
void SetObjectIDs(dip::UnsignedArray objectIDs)
Replaces existing objectID array with a new one. The Measurement object must be raw.
void AddObjectID(dip::uint objectID)
Adds an object ID to a raw Measurement object. It is not efficient to use this function in a loop.
void AddObjectIDs(dip::UnsignedArray const& objectIDs)
Adds object IDs to a raw Measurement object.
void Forge()
Forges the table, allocating space to hold measurement values. Will fail if there are no features defined.
auto IsForged() const -> bool
Tests if the object is forged (has data segment allocated). A table with zero objects will always appear raw (non-forged) even if Forge was called.
auto FirstObject() const -> dip::Measurement::IteratorObject
Creates an iterator (view) to the first object
auto FirstFeature() const -> dip::Measurement::IteratorFeature
Creates and iterator (view) to the first feature
auto FeatureValuesView(dip::uint startValue, dip::uint numberValues = 1) const -> dip::Measurement::IteratorFeature
Creates and iterator (view) to a subset of feature values
auto Data() const -> dip::Measurement::ValueType*
A raw pointer to the data of the table. All values for one object are contiguous. The table must be forged.
auto Stride() const -> dip::sint
The stride to use to access the next row of data in the table (next object).
auto DataSize() const -> dip::uint
The total number of data values in the table, equal to the product of NumberOfValues and NumberOfObjects.
auto FeatureExists(dip::String const& name) const -> bool
True if the feature is available in this.
auto FeatureIndex(dip::String const& name) const -> dip::uint
Finds the index into the dip::Measurement::Features array for the given feature.
auto Features() const -> std::vector<FeatureInformation> const&
Returns an array of feature names
auto NumberOfFeatures() const -> dip::uint
Returns the number of features
auto ValueIndex(dip::String const& name) const -> dip::uint
Finds the index into the dip::Measurement::Values array for the first value of the given feature.
auto Values(dip::String const& name) const -> dip::Feature::ValueInformationArray
Returns an array with names and units for each of the values for the feature. (Note: data are copied to output array, this is not a trivial function).
auto Values() const -> dip::Feature::ValueInformationArray const&
Returns an array with names and units for each of the values (for all features)
auto NumberOfValues() const -> dip::uint
Returns the total number of feature values
auto NumberOfValues(dip::String const& name) const -> dip::uint
Returns the number of values for the given feature
auto ObjectExists(dip::uint objectID) const -> bool
True if the object ID is available in this.
auto ObjectIndex(dip::uint objectID) const -> dip::uint
Finds the row index for the given object ID.
auto ObjectIndices() const -> dip::ObjectIdToIndexMap const&
Returns the map that links object IDs to row indices.
auto Objects() const -> dip::UnsignedArray const&
Returns a list of object IDs
auto NumberOfObjects() const -> dip::uint
Returns the number of objects

Operators

auto operator[](dip::uint objectID) const -> dip::Measurement::IteratorObject
Creates and iterator (view) to the given object. The table must be forged.
auto operator[](dip::String const& name) const -> dip::Measurement::IteratorFeature
Creates and iterator (view) to the given feature

Class documentation

struct FeatureInformation

Structure containing information about the features stored in a dip::Measurement object

Variables
dip::String name Name of the feature
dip::uint startColumn Column for first value of feature
dip::uint numberValues Number of vales in feature

Function documentation

dip::Measurement::IteratorFeature FeatureValuesView(dip::uint startValue, dip::uint numberValues = 1) const

Creates and iterator (view) to a subset of feature values

Example:

dip::Measurement msr = measureTool.Measure( label, grey, {"Feret"}, {} );
auto featureValues = msr.FeatureValuesView( 1, 1 ); // Select the "FeretMin" column only