IPSDK  4_1_0_2
IPSDK : Image Processing Software Development Kit
Modules
Shape Analysis and Measurement

modules containing shape measures More...

Modules

 Formula
 Formula measures associated to a formula string.
 
 Geometry
 modules containing shape measures based on geometry
 
 Intensity
 modules containing shape measures based on intensity
 

Detailed Description

modules containing shape measures

This page presents some material to get start with shape analysis and measurement framework :

Introduction

Shape analysis framework allows to compute measures on a collection of shapes (also named blobs, connected components, particles, ...). It allows for example to measure indicators such as :

It is associated to following algorithms :

A high level representation of this processing is given by following figure :

shapeAnalysis1.png

Shape analysis processing will usually takes on input :

On output each cupple measure/shape will be associated to a measurement result. This result is usually a single value (floating point, interger or boolean), but can also be a collection of values or even a custom result type.

These measure results can be individually accessed via some extraction function such as ipsdk::shape::analysis::extractValueResults or written to a 'csv' file using ipsdk::shape::analysis::saveCsvMeasureFile. For more informations on shape analysis measure results, please see Measure result.

Getting started with shape analysis

Usual case

The most classical case of usage for shape analysis framework is a case where user provide as input :

Note that classical case of usage for shape analysis and measurement can uses package algorithm Label Analysis 2d and Label Analysis 3d. These algorithms simply allow to mask to user the shape extraction step and can replace Shape Analysis 2d and Shape Analysis 3d.

In the following we will supposed that these inputs are available.

Here is a code sample in 2d case :

Python code Example

# opening of input image
inGreyImg = PyIPSDK.loadTiffImageFile(inputGreyImgPath)
# read of input shape collection
inShape2dColl, bResRead = PyIPSDK.readFromXmlFile(inputShape2dCollPath)
unitTestMonitor.checkEqual(bResRead.getResult(), True)
# definition of proceeded measure
inMeasureInfoSet2d = PyIPSDK.createMeasureInfoSet2d()
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "PolygonArea2dMsr")
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "MeanMsr")
# shape analysis computation
outMeasureSet = shapeanalysis.shapeAnalysis2d(inGreyImg, inShape2dColl, inMeasureInfoSet2d)
# save results to csv format
PyIPSDK.saveCsvMeasureFile(csvOutputPath, outMeasureSet)
# retrieve measure results
outArea2dMsr = outMeasureSet.getMeasure("PolygonArea2dMsr")
outMeanMsr = outMeasureSet.getMeasure("MeanMsr")
# retrieve associated measure values
outArea2dValues = PyIPSDK.extractReal64Results(outArea2dMsr)
outMeanValues = PyIPSDK.extractReal64Results(outMeanMsr)
print("First label area 2d measurement equal " + str(outArea2dValues[1]))
print("First label mean intensity measurement equal " + str(outMeanValues[1]))

C++ code Example

// opening grey level input image
ImagePtr pInGreyImg2d = loadTiffImageFile(inputGreyImgPath);
// read entity shape 2d collection used for processing
Shape2dCollPtr pShape2dColl = boost::make_shared<Shape2dColl>();
IPSDK_REQUIRE(readFromXmlFile(inputShape2dCollPath, *pShape2dColl) == true);
// define a measure info set
MeasureInfoSetPtr pMeasureInfoSet = MeasureInfoSet::create2dInstance();
createMeasureInfo(pMeasureInfoSet, "PolygonArea2dMsr");
createMeasureInfo(pMeasureInfoSet, "MeanMsr");
// compute measure on extracted data
MeasureSetPtr pOutMeasureSet = shapeAnalysis2d(pInGreyImg2d, pShape2dColl, pMeasureInfoSet);
// complete csv dump of results
saveCsvMeasureFile(csvOutputPath, *pOutMeasureSet);
// retrieve associated results
const MeasureConstPtr& pArea2dOutMsr = pOutMeasureSet->getMeasure("PolygonArea2dMsr");
const std::vector<ipReal64>& area2dResults = extractValueResults<ipReal64>(pArea2dOutMsr);
const MeasureConstPtr& pMeanOutMsr = pOutMeasureSet->getMeasure("MeanMsr");
const std::vector<ipReal64>& meanResults = extractValueResults<ipReal64>(pMeanOutMsr);

In this sample user provides an input image pInGreyImg2d and an input shape 2d collection pShape2dColl and defines an input collection of measures to be proceeded pMeasureInfoSet composed of :

Once computation proceeded via call to ipsdk::imaproc::shape::analysis::shapeAnalysis2d function, user will be able to manipulate associated results :

Handling geometric calibration

Starting from previous example, we can add a geometrical calibration which will allows to convert geometric measurement from image gauge to user gauge.

Here is a code sample in 2d case :

Python code Example

# opening of input image
inGreyImg = PyIPSDK.loadTiffImageFile(inputGreyImgPath)
# read of input shape collection
inShape2dColl, bResRead = PyIPSDK.readFromXmlFile(inputShape2dCollPath)
unitTestMonitor.checkEqual(bResRead.getResult(), True)
# defined a geometric calibration
geometricCalibration = PyIPSDK.createGeometricCalibration2d(0.01, 0.02, "mm");
# definition of proceeded measure
inMeasureInfoSet2d = PyIPSDK.createMeasureInfoSet2d(geometricCalibration)
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "PolygonArea2dMsr")
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "Perimeter2dMsr")
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "MeanMsr")
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "InertiaOrientation2dMsr")
# shape analysis computation
outMeasureSet = shapeanalysis.shapeAnalysis2d(inGreyImg, inShape2dColl, inMeasureInfoSet2d)
# save results to csv format
PyIPSDK.saveCsvMeasureFile(csvOutputPath, outMeasureSet)
# retrieve measure results
outArea2dMsr = outMeasureSet.getMeasure("PolygonArea2dMsr")
outPerimeter2dMsr = outMeasureSet.getMeasure("Perimeter2dMsr")
outMeanMsr = outMeasureSet.getMeasure("MeanMsr")
outInertiaOrientation2dMsr = outMeasureSet.getMeasure("InertiaOrientation2dMsr")
# retrieve associated measure values
outArea2dValues = PyIPSDK.extractReal64Results(outArea2dMsr)
outPerimeter2dValues = PyIPSDK.extractReal64Results(outPerimeter2dMsr)
outMeanValues = PyIPSDK.extractReal64Results(outMeanMsr)
outInertiaOrientation2dValues = PyIPSDK.extractReal64Results(outInertiaOrientation2dMsr)
print("First label area 2d measurement equal " + str(outArea2dValues[1]))
print("First label perimeter 2d measurement equal " + str(outPerimeter2dValues[1]))
print("First label mean intensity measurement equal " + str(outMeanValues[1]))
print("First label orientation (based on inertia) measurement equal " + str(outInertiaOrientation2dValues[1]))

C++ code Example

// opening grey level input image
ImagePtr pInGreyImg2d = loadTiffImageFile(inputGreyImgPath);
// read entity shape 2d collection used for processing
Shape2dCollPtr pShape2dColl = boost::make_shared<Shape2dColl>();
IPSDK_REQUIRE(readFromXmlFile(inputShape2dCollPath, *pShape2dColl) == true);
// defined a geometric calibration
GeometricCalibrationPtr pGeometricCalibration = createGeometricCalibration2d(0.01f, 0.02f, "mm");
// define a measure info set
MeasureInfoSetPtr pMeasureInfoSet = MeasureInfoSet::create2dInstance(pGeometricCalibration);
createMeasureInfo(pMeasureInfoSet, "PolygonArea2dMsr");
createMeasureInfo(pMeasureInfoSet, "Perimeter2dMsr");
createMeasureInfo(pMeasureInfoSet, "MeanMsr");
createMeasureInfo(pMeasureInfoSet, "InertiaOrientation2dMsr");
// compute measure on extracted data
MeasureSetPtr pOutMeasureSet = shapeAnalysis2d(pInGreyImg2d, pShape2dColl, pMeasureInfoSet);
// complete csv dump of results
saveCsvMeasureFile(csvOutputPath, *pOutMeasureSet);
// retrieve associated results
const MeasureConstPtr& pArea2dOutMsr = pOutMeasureSet->getMeasure("PolygonArea2dMsr");
const std::vector<ipReal64>& area2dResults = extractValueResults<ipReal64>(pArea2dOutMsr);
const MeasureConstPtr& pPerimeter2dOutMsr = pOutMeasureSet->getMeasure("Perimeter2dMsr");
const std::vector<ipReal64>& perimeter2dResults = extractValueResults<ipReal64>(pPerimeter2dOutMsr);
const MeasureConstPtr& pMeanOutMsr = pOutMeasureSet->getMeasure("MeanMsr");
const std::vector<ipReal64>& meanResults = extractValueResults<ipReal64>(pMeanOutMsr);
const MeasureConstPtr& pInertiaOrientation2dOutMsr = pOutMeasureSet->getMeasure("InertiaOrientation2dMsr");
const std::vector<ipReal64>& InertiaOrientation2dResults = extractValueResults<ipReal64>(pInertiaOrientation2dOutMsr);

In this sample user add following measures to input collection of measures :

User also defines a geometric calibration used during measurements with the following settings :

csvResultsBasicCalibrationSample.png

Using a calibration will products the following effects on output (with comparison to Usual case):

Please refers to Measure unit type and to Image calibration concepts in IPSDK for more informations on geometric calibration.

Working with measure parameters

In this section, we will demonstrate how to modify measure parameters to alter computation behavior of some measures.

We will use the following image and shape collection to illustrate this case :

shapeAnalysis2.png

Taking a look for example to documentation of measure Area2d, user can see that this measure can be parametered using an object of type ipsdk::imaproc::shape::analysis::HolesBasicPolicyMsrParams. This parameter allows in case of this measure to define whether computation should :

Here is a code sample in 2d case :

Python code Example

# read of input shape collection
inShape2dColl, bResRead = PyIPSDK.readFromXmlFile(inputShape2dCollPath)
unitTestMonitor.checkEqual(bResRead.getResult(), True)
# definition of proceeded measure
inMeasureInfoSet2d = PyIPSDK.createMeasureInfoSet2d()
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "AreaMinusHoles", "PolygonArea2dMsr", shapeanalysis.createHolesBasicPolicyMsrParams(True))
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "AreaWithHoles", "PolygonArea2dMsr", shapeanalysis.createHolesBasicPolicyMsrParams(False))
# shape analysis computation
outMeasureSet = shapeanalysis.shapeAnalysis2d(inMeasureInfoSet2d, inShape2dColl)
# save results to csv format
PyIPSDK.saveCsvMeasureFile(csvOutputPath, outMeasureSet)
# retrieve measure results
outAreaMinusHolesMsr = outMeasureSet.getMeasure("AreaMinusHoles")
outAreaWithHolesMsr = outMeasureSet.getMeasure("AreaWithHoles")
# retrieve associated measure values
outAreaMinusHolesValues = PyIPSDK.extractReal64Results(outAreaMinusHolesMsr)
outAreaWithHolesValues = PyIPSDK.extractReal64Results(outAreaWithHolesMsr)
print("First label area minus holes measurement equal " + str(outAreaMinusHolesValues[1]))
print("First label area with holes measurement equal " + str(outAreaWithHolesValues[1]))

C++ code Example

// read entity shape 2d collection used for processing
Shape2dCollPtr pShape2dColl = boost::make_shared<Shape2dColl>();
IPSDK_REQUIRE(readFromXmlFile(inputShape2dCollPath, *pShape2dColl) == true);
// define a measure info set
MeasureInfoSetPtr pMeasureInfoSet = MeasureInfoSet::create2dInstance();
createMeasureInfo(pMeasureInfoSet, "AreaMinusHoles", "PolygonArea2dMsr", createHolesBasicPolicyMsrParams(true));
createMeasureInfo(pMeasureInfoSet, "AreaWithHoles", "PolygonArea2dMsr", createHolesBasicPolicyMsrParams(false));
// compute measure on extracted data
MeasureSetPtr pOutMeasureSet = shapeAnalysis2d(pMeasureInfoSet, pShape2dColl, ShapeAnalysis2dOptParams());
// complete csv dump of results
saveCsvMeasureFile(csvOutputPath, *pOutMeasureSet);
// retrieve associated results
const MeasureConstPtr& pAreaMinusHolesOutMsr = pOutMeasureSet->getMeasure("AreaMinusHoles");
const std::vector<ipReal64>& areaMinusHolesResults = extractValueResults<ipReal64>(pAreaMinusHolesOutMsr);
const MeasureConstPtr& pAreaWithHolesOutMsr = pOutMeasureSet->getMeasure("AreaWithHoles");
const std::vector<ipReal64>& areaWithHolesResults = extractValueResults<ipReal64>(pAreaWithHolesOutMsr);

In this example, we defined two measures from area 2d measure :

csvResultsWorkingWithParametersSample.png

Handling color measurements

Shape analysis framework allows to deal with input color image (see Color models).

We will use the following image and shape collection to illustrate this case :

shapeAnalysis2.png

In this example, we define two measures :

Here is a code sample in 2d case :

Python code Example

# opening of input image
inColorImg = PyIPSDK.loadTiffImageFile(inputColorImgPath)
# read of input shape collection
inShape2dColl, bResRead = PyIPSDK.readFromXmlFile(inputShape2dCollPath)
unitTestMonitor.checkEqual(bResRead.getResult(), True)
# definition of proceeded measure
inMeasureInfoSet2d = PyIPSDK.createMeasureInfoSet2d()
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "PolygonArea2dMsr")
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "MeanMsr")
# shape analysis computation
outMeasureSet = shapeanalysis.shapeAnalysis2d(inColorImg, inShape2dColl, inMeasureInfoSet2d)
# save results to csv format
PyIPSDK.saveCsvMeasureFile(csvOutputPath, outMeasureSet)
# retrieve measure results
outArea2dMsr = outMeasureSet.getMeasure("PolygonArea2dMsr")
outMeanMsr = outMeasureSet.getMeasure("MeanMsr")
# retrieve associated measure values
outArea2dValues = PyIPSDK.extractReal64Results(outArea2dMsr)
outMeanValuesRed = PyIPSDK.extractReal64Results(outMeanMsr, 0)
outMeanValuesGreen = PyIPSDK.extractReal64Results(outMeanMsr, 1)
outMeanValuesBlue = PyIPSDK.extractReal64Results(outMeanMsr, 2)
print("First label area measurement equal " + str(outArea2dValues[1]))
print("First label mean intensity along red channel measurement equal " + str(outMeanValuesRed[1]))
print("First label mean intensity along green channel measurement equal " + str(outMeanValuesGreen[1]))
print("First label mean intensity along blue channel measurement equal " + str(outMeanValuesBlue[1]))

C++ code Example

// opening color input image
ImagePtr pInColorImg2d = loadTiffImageFile(inputColorImgPath);
// read entity shape 2d collection used for processing
Shape2dCollPtr pShape2dColl = boost::make_shared<Shape2dColl>();
IPSDK_REQUIRE(readFromXmlFile(inputShape2dCollPath, *pShape2dColl) == true);
// define a measure info set
MeasureInfoSetPtr pMeasureInfoSet = MeasureInfoSet::create2dInstance();
createMeasureInfo(pMeasureInfoSet, "PolygonArea2dMsr");
createMeasureInfo(pMeasureInfoSet, "MeanMsr");
// compute measure on extracted data
MeasureSetPtr pOutMeasureSet = shapeAnalysis2d(pInColorImg2d, pShape2dColl, pMeasureInfoSet);
// complete csv dump of results
saveCsvMeasureFile(csvOutputPath, *pOutMeasureSet);
// retrieve associated results
const MeasureConstPtr& pArea2dOutMsr = pOutMeasureSet->getMeasure("PolygonArea2dMsr");
const std::vector<ipReal64>& area2dResults = extractValueResults<ipReal64>(pArea2dOutMsr);
const MeasureConstPtr& pMeanOutMsr = pOutMeasureSet->getMeasure("MeanMsr");
const std::vector<ipReal64>& meanResultsRed = extractValueResults<ipReal64>(pMeanOutMsr, 0);
const std::vector<ipReal64>& meanResultsGreen = extractValueResults<ipReal64>(pMeanOutMsr, 1);
const std::vector<ipReal64>& meanResultsBlue = extractValueResults<ipReal64>(pMeanOutMsr, 2);

The following results illustrate the fact that an intensity measure result is spanned according to input image color plans while a geometric measure is not.

csvResultsBasicColorSample.png

Advanced usage of shape analysis framework

This section described advanced usage of shape analysis framework, please be sure to have a look to IPSDKIPLShapeAnalysisGettingStarted section before to read it.

Working with preprocessed images

Sometimes it can be interesting to work with preprocessed images rather that provided input image to compute measure results. This is for example the case if some gradient information are needed to make a separation between classes of shapes.

We will use the following image and shape collection to illustrate this case :

shapeAnalysis4.png

In this image we can distinguish three class of shapes (homogeneous, vertically tiled and horizontally tiled).

In this example, we will use measure configuration to measure a mean intensity over each shape on :

Here is a code sample in 2d case :

Python code Example

# opening of input image
inGreyImg = PyIPSDK.loadTiffImageFile(inputGreyImgPath)
# read of input shape collection
inShape2dColl, bResRead = PyIPSDK.readFromXmlFile(inputShape2dCollPath)
unitTestMonitor.checkEqual(bResRead.getResult(), True)
# definition of proceeded measure
gradSigma = 1.5
inMeasureInfoSet2d = PyIPSDK.createMeasureInfoSet2d()
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "MeanInputMsr", "MeanMsr")
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "SumSquareGradXMsr", "SumSquareMsr", shapeanalysis.createXGaussGradMsrCfg2d(gradSigma))
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "SumSquareGradYMsr", "SumSquareMsr", shapeanalysis.createYGaussGradMsrCfg2d(gradSigma))
# shape analysis computation
outMeasureSet = shapeanalysis.shapeAnalysis2d(inGreyImg, inShape2dColl, inMeasureInfoSet2d)
# save results to csv format
PyIPSDK.saveCsvMeasureFile(csvOutputPath, outMeasureSet)
# retrieve measure results
outMeanMsr = outMeasureSet.getMeasure("MeanInputMsr")
outSumSquareGradXMsr = outMeasureSet.getMeasure("SumSquareGradXMsr")
outSumSquareGradYMsr = outMeasureSet.getMeasure("SumSquareGradYMsr")
# retrieve associated measure values
outMeanValues = PyIPSDK.extractReal64Results(outMeanMsr)
outSumSquareGradXValues = PyIPSDK.extractReal64Results(outSumSquareGradXMsr)
outSumSquareGradYValues = PyIPSDK.extractReal64Results(outSumSquareGradYMsr)
print("First label mean intensity measurement equal " + str(outMeanValues[1]))
print("First label x gradient sum of squares measurement equal " + str(outSumSquareGradXValues[1]))
print("First label y gradient sum of squares measurement equal " + str(outSumSquareGradYValues[1]))

C++ code Example

// opening input image
ImagePtr pInGreyImg2d = loadTiffImageFile(inputGreyImgPath);
// read entity shape 2d collection used for processing
Shape2dCollPtr pShape2dColl = boost::make_shared<Shape2dColl>();
IPSDK_REQUIRE(readFromXmlFile(inputShape2dCollPath, *pShape2dColl) == true);
// define a measure info set
const ipReal32 gradSigma = 1.5f;
MeasureInfoSetPtr pMeasureInfoSet = MeasureInfoSet::create2dInstance();
createMeasureInfo(pMeasureInfoSet, "MeanInputMsr", "MeanMsr");
createMeasureInfo(pMeasureInfoSet, "SumSquareGradXMsr", "SumSquareMsr", createXGaussGradMsrCfg2d(gradSigma));
createMeasureInfo(pMeasureInfoSet, "SumSquareGradYMsr", "SumSquareMsr", createYGaussGradMsrCfg2d(gradSigma));
// compute measure on extracted data
MeasureSetPtr pOutMeasureSet = shapeAnalysis2d(pInGreyImg2d, pShape2dColl, pMeasureInfoSet);
// complete csv dump of results
saveCsvMeasureFile(csvOutputPath, *pOutMeasureSet);
// retrieve associated results
const MeasureConstPtr& pMeanInputOutMsr = pOutMeasureSet->getMeasure("MeanInputMsr");
const std::vector<ipReal64>& meanInputResults = extractValueResults<ipReal64>(pMeanInputOutMsr);
const MeasureConstPtr& pSumSquareGradXOutMsr = pOutMeasureSet->getMeasure("SumSquareGradXMsr");
const std::vector<ipReal64>& sumSquareGradXResults = extractValueResults<ipReal64>(pSumSquareGradXOutMsr);
const MeasureConstPtr& pSumSquareGradYOutMsr = pOutMeasureSet->getMeasure("SumSquareGradYMsr");
const std::vector<ipReal64>& sumSquareGradYResults = extractValueResults<ipReal64>(pSumSquareGradYOutMsr);

The following results illustrate the fact that shape analysis framework preprocessing capabilities can be used to bring additional informations on measured shapes. In this case, statistics on gradient values along x and y axis can be used to distinguish several shape classes :

csvResultsAdvancedPreProcessorSample.png

Handling multiple inputs

In some cases it can be interesting to use multiple shape collections or multiple images as input of shape analysis processing.

This happens for example in case where we want use two images with different resolution representing the same shapes (with multi modal acquisitions for example).

We will use the following image and shape collection to illustrate this case :

shapeAnalysis5.png

These two images combined allow to distinguish between 4 classes of objects while first one only allows to distinguish 3 classes (see Working with preprocessed images)

The two input images have different resolution and will so be associated to different shape collections.

Note
Note that shape analysis framework impose a constant number of shapes into input shape collections

In this example, we will use measure configuration to measure a mean intensity over each shape on :

Here is a code sample in 2d case :

Python code Example

# opening of input images
inGreyImg1 = PyIPSDK.loadTiffImageFile(inputGreyImgPath1)
inGreyImg2 = PyIPSDK.loadTiffImageFile(inputGreyImgPath2)
# read of input shape collection
inShape2dColl1, bResRead1 = PyIPSDK.readFromXmlFile(inputShape2dCollPath1)
unitTestMonitor.checkEqual(bResRead1.getResult(), True)
inShape2dColl2, bResRead2 = PyIPSDK.readFromXmlFile(inputShape2dCollPath2)
unitTestMonitor.checkEqual(bResRead2.getResult(), True)
# definition of proceeded measure
gradSigma = 1.5
inMeasureInfoSet2d = PyIPSDK.createMeasureInfoSet2d()
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "MeanInput1Msr", "MeanMsr")
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "SumSquareGradX1Msr", "SumSquareMsr", shapeanalysis.createXGaussGradMsrCfg2d(gradSigma))
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "SumSquareGradY1Msr", "SumSquareMsr", shapeanalysis.createYGaussGradMsrCfg2d(gradSigma))
PyIPSDK.createMeasureInfo(inMeasureInfoSet2d, "MeanInput2Msr", "MeanMsr", PyIPSDK.createMeasureConfig(PyIPSDK.eMsrInputImageId.eMIII_Image2,
PyIPSDK.eMsrInputShapeCollId.eMISCI_ShapeColl2))
# shape analysis computation
outMeasureSet = shapeanalysis.shapeAnalysis2d(inMeasureInfoSet2d,
inShape2dColl1,
InOptGreyMsrImg1=inGreyImg1,
InOptLabelsShape2=inShape2dColl2,
InOptGreyMsrImg2=inGreyImg2)
# save results to csv format
PyIPSDK.saveCsvMeasureFile(csvOutputPath, outMeasureSet)
# retrieve measure results
outMean1Msr = outMeasureSet.getMeasure("MeanInput1Msr")
outSumSquareGradX1Msr = outMeasureSet.getMeasure("SumSquareGradX1Msr")
outSumSquareGradY1Msr = outMeasureSet.getMeasure("SumSquareGradY1Msr")
outMean2Msr = outMeasureSet.getMeasure("MeanInput2Msr")
# retrieve associated measure values
outMean1Values = PyIPSDK.extractReal64Results(outMean1Msr)
outSumSquareGradX1Values = PyIPSDK.extractReal64Results(outSumSquareGradX1Msr)
outSumSquareGradY1Values = PyIPSDK.extractReal64Results(outSumSquareGradY1Msr)
outMean2Values = PyIPSDK.extractReal64Results(outMean2Msr)
print("First label mean intensity measurement in first image equal " + str(outMean1Values[1]))
print("First label x gradient sum of squares in first image measurement equal " + str(outSumSquareGradX1Values[1]))
print("First label y gradient sum of squares in first image measurement equal " + str(outSumSquareGradY1Values[1]))
print("First label mean intensity measurement in second image equal " + str(outMean2Values[1]))

C++ code Example

// opening input images
ImagePtr pInGreyImg2d1 = loadTiffImageFile(inputGreyImgPath1);
ImagePtr pInGreyImg2d2 = loadTiffImageFile(inputGreyImgPath2);
// read entity shape 2d collection used for processing
Shape2dCollPtr pShape2dColl1 = boost::make_shared<Shape2dColl>();
IPSDK_REQUIRE(readFromXmlFile(inputShape2dCollPath1, *pShape2dColl1) == true);
Shape2dCollPtr pShape2dColl2 = boost::make_shared<Shape2dColl>();
IPSDK_REQUIRE(readFromXmlFile(inputShape2dCollPath2, *pShape2dColl2) == true);
// define a measure info set
const ipReal32 gradSigma = 1.5f;
MeasureInfoSetPtr pMeasureInfoSet = MeasureInfoSet::create2dInstance();
createMeasureInfo(pMeasureInfoSet, "MeanInput1Msr", "MeanMsr");
createMeasureInfo(pMeasureInfoSet, "SumSquareGradX1Msr", "SumSquareMsr", createXGaussGradMsrCfg2d(gradSigma));
createMeasureInfo(pMeasureInfoSet, "SumSquareGradY1Msr", "SumSquareMsr", createYGaussGradMsrCfg2d(gradSigma));
createMeasureInfo(pMeasureInfoSet, "MeanInput2Msr", "MeanMsr", createMeasureConfig(eMsrInputImageId::eMIII_Image2,
eMsrInputShapeCollId::eMISCI_ShapeColl2));
// compute measure on extracted data
ShapeAnalysis2dOptParams shapeAnalysis2dOptParams;
shapeAnalysis2dOptParams._pInOptGreyMsrImg1 = pInGreyImg2d1;
shapeAnalysis2dOptParams._pInOptLabelsShape2 = pShape2dColl2;
shapeAnalysis2dOptParams._pInOptGreyMsrImg2 = pInGreyImg2d2;
MeasureSetPtr pOutMeasureSet = shapeAnalysis2d(pMeasureInfoSet, pShape2dColl1, shapeAnalysis2dOptParams);
// complete csv dump of results
saveCsvMeasureFile(csvOutputPath, *pOutMeasureSet);
// retrieve associated results
const MeasureConstPtr& pMeanInput1OutMsr = pOutMeasureSet->getMeasure("MeanInput1Msr");
const std::vector<ipReal64>& meanInput1Results = extractValueResults<ipReal64>(pMeanInput1OutMsr);
const MeasureConstPtr& pSumSquareGradX1OutMsr = pOutMeasureSet->getMeasure("SumSquareGradX1Msr");
const std::vector<ipReal64>& sumSquareGradX1Results = extractValueResults<ipReal64>(pSumSquareGradX1OutMsr);
const MeasureConstPtr& pSumSquareGradY1OutMsr = pOutMeasureSet->getMeasure("SumSquareGradY1Msr");
const std::vector<ipReal64>& sumSquareGradY1Results = extractValueResults<ipReal64>(pSumSquareGradY1OutMsr);
const MeasureConstPtr& pMeanInput2OutMsr = pOutMeasureSet->getMeasure("MeanInput2Msr");
const std::vector<ipReal64>& meanInput2Results = extractValueResults<ipReal64>(pMeanInput2OutMsr);

The following results illustrate the usage of multiple input images and shape collections to bring additional informations on measured shapes. In this case, statistics on gradient values along x and y axis mixed with information of second input image can be used to distinguish four shape classes :

csvResultsAdvancedMultipleInputsSample.png