DGtal  1.4.2
Tutorial "Image -> Region -> Grid curve -> Length estimation"
Author(s) of this documentation:
Tristan Roussillon

In this example, we show how to retrieve the contour of a connected subset of an image and estimate its perimeter.

Extracting a digital set from an image

Let us assume that the following image has been loaded into an image object:

S gray level image

First of all, we implicitely extract a digital set from an image, using a simple threshold on gray level values:

//predicate from the image
Binarizer b(1, 135);
PointFunctorPredicate<Image,Binarizer> predicate(image, b);
Aim: A small functor with an operator () that compares one value to an interval.
Note
The explicit construction of the digital set is not necessary.
Since the domain of the image is known (methods lowerBound() and upperBound()), it is indeed enough to have a predicate that indicates, for each point of the domain, whether it belongs to the digital set or not.

This predicate returns true for each dark pixel of the following image:

S binary image

Extracting the contours of a digital set

The extraction of the contour is performed in a cellular space (with 0-, 1-, and 2-cells), given an adjacency (0-, 1-, 2-adjacency). See Cellular grid space and topology, unoriented and oriented cells, incidence for the basic concepts of cellular topology.

Z2i::KSpace ks; //Khalimsky space
ks.init( image.domain().lowerBound(), image.domain().upperBound(), true );
SurfelAdjacency<2> sAdj( true ); //adjacency
KhalimskySpaceND< 2, Integer > KSpace
Definition: StdDefs.h:77

Then, the contour of each connected component can be retrieved as follows:

//extraction of all the contours
std::vector< std::vector< Z2i::SCell > > contours;
::extractAll2DSCellContours( contours, ks, sAdj, predicate );
static void extractAll2DSCellContours(std::vector< std::vector< SCell > > &aVectSCellContour2D, const KSpace &aKSpace, const SurfelAdjacency< KSpace::dimension > &aSurfelAdj, const PointPredicate &pp)

Grid curve instantiation

The GridCurve object is merely built from one retrieved contour, which is stored as a vector of signed 1-cells:

//init grid curve from the first retrieved contour
c.initFromSCellsVector( contours.at(1) );
GridCurve< K2 > Curve
Definition: StdDefs.h:116

Length estimation

Now, we want to get a perimeter estimation of the grid curve c. Several length estimators have been implemented in DGtal, but we are using in what follows the one based on a greedy segmentation of the curve into digital straight segments (DSS).

Since the DSS recognition algoritm deals with digital points, we get the points range of the grid curve c.

//range of points
Range r = c.getPointsRange();
ConstRangeAdapter< typename Storage::const_iterator, functors::SCellToPoint< KSpace >, Point > PointsRange
Definition: GridCurve.h:421

The DSS segmentation looks like this:

DSS segmentation

Then, we initialize the DSS length estimator from the points range and get the estimated length.

//length estimation based on a DSS segmentation
DSSLengthEstimator< Range::ConstCirculator > DSSlength;
trace.info() << "Length: " << DSSlength.eval(r.c(), r.c(), 1.) << std::endl;
std::ostream & info()
Trace trace
Definition: Common.h:153

You should see in the standard output:

Length: 723.238

Required includes

You should include these common files:

#include "DGtal/base/Common.h"
#include "DGtal/helpers/StdDefs.h"
#include "ConfigExamples.h"

For loading the image and extracting a digital set by thresholding:

#include "DGtal/base/BasicFunctors.h"
#include "DGtal/kernel/BasicPointPredicates.h"
#include "DGtal/io/readers/PGMReader.h"
#include "DGtal/images/ImageContainerBySTLVector.h"

For extracting the contours of the digital set:

#include "DGtal/topology/helpers/Surfaces.h"

And finally, for estimating the length of the retrieved contours, you should include this:

#include "DGtal/geometry/curves/estimation/DSSLengthEstimator.h"