ImageDev

- Getting Started
- ImageDev Python
- ImageDev C#
- ImageDev C++
- Licensing Information
- Redistributable Files
- Processing
- Image Manipulation
- - Synthetic Images
  - - RandomImage2d
    - RandomImage3d
    - RandomGaussianImage2d
    - RandomGaussianImage3d
    - RadialFunctionImage2d
    - RadialFunctionImage3d
    - OrientedLinesImage2d
    - OrientedLinesImage3d
    - RandomSphereImage3d
    - BoxGridImage2d
    - BoxGridImage3d
    - WedgeMaskImage3d
    - PointSpreadFunctionImage3d
  - Image Editing
  - - ConvertImage
    - ResetImage
    - CopyImage
    - PasteImage2d
    - PasteImage3d
    - CropImage2d
    - CropImage3d
    - SampleImage2d
    - SampleImage3d
    - InterlaceFrames2d
    - DeinterlaceFrames2d
  - Stack Operations
  - - SequenceConcatenation
    - SequenceToMultispectral
    - SequenceToVolume
    - VolumeToSequence
    - MultispectralToSequence
    - GetSliceFromVolume3d
    - SetSliceToVolume3d
    - GetObliqueSliceFromVolume3d
    - ImageStackProjection3d
    - VolumeProjection3d
- Geometry And Matching
- - Geometric Transforms
  - - Shearing3d
    - TranslateImage2d
    - TranslateImage3d
    - Flip2d
    - Flip3d
    - FlipImage2d
    - FlipImage3d
    - TransposeImage2d
    - TransposeImage3d
    - SwapQuadrants
    - Rotate2d
    - Rotate3d
    - RotationGenerator3d
    - Resize2d
    - Resize3d
    - RescaleByFactor
    - RescaleImageByFactor
    - ResampleAffine2d
    - ResampleAffine3d
    - ResampleElastic2d
    - SurfaceUnfolding3d
  - Pattern Recognition
  - - BinaryCorrelation2d
    - CrossCorrelation2d
    - CorrelationByDifference2d
    - CorrelationBySignChange2d
  - Registration
  - - ImagePrealignment3d
    - AffineRegistration
    - ElasticRegistration2d
- Arithmetic And Logic
- - Arithmetical Operations
  - - AbsoluteValue
    - AbsoluteMaximumWithImage
    - ArithmeticOperationWithImage
    - ArithmeticOperationWithValue
    - BlendWithImage
    - BlendWithValue
    - DirectionalBlending2d
    - CombineByMask
    - ImageFormula
    - EigenDecomposition2d
    - EigenDecomposition3d
  - Logical Operations
  - - MaskImage
    - LogicalOperationWithImage
    - LogicalOperationWithValue
    - LogicalNot
    - InvertImage
    - BitShift
- Image Filtering
- - Grayscale Transforms
  - - RescaleIntensity
    - StackRescaleIntensity
    - MatchContrast
    - HistogramEqualization
    - Clahe2d
    - Clahe3d
    - AdaptiveHistogramEqualization
    - ApplyGrayscaleLut
    - BackgroundImage2d
    - RadialBackgroundImage2d
    - ShadingCorrection
    - Exponential
    - Logarithm
    - Square
    - SquareRoot
    - RingArtifactRemoval3d
    - BeamHardeningCorrection3d
  - Color Transforms
  - - ColorToLightness
    - GetColorChannel
    - ColorToGrayscale
    - GrayscaleToColor
    - ColorSpaceConversion
    - ColorAntialiasing2d
    - BayerToRgb2d
    - DecorrelationStretch2d
    - BlendAlphaChannelWithImage
    - BlendAlphaChannelWithValue
  - Smoothing And Denoising
  - - BoxFilter2d
    - BoxFilter3d
    - MedianFilter2d
    - MedianFilter3d
    - GaussianFilter2d
    - GaussianFilter3d
    - ExponentialFilter2d
    - RecursiveExponentialFilter2d
    - RecursiveExponentialFilter3d
    - NonLocalMeansFilter2d
    - NonLocalMeansFilter3d
    - CurvatureDrivenDiffusion
    - BilateralFilter2d
    - BilateralFilter3d
    - MajorityFilter2d
    - MajorityFilter3d
    - SigmaFilter2d
    - SigmaFilter3d
    - Despeckle2d
    - Despeckle3d
    - NagaoFilter2d
    - NagaoFilter3d
    - SnnFilter2d
    - SnnFilter3d
    - FlowInpainting
  - Sharpening
  - - Deblurring2d
    - Delineate2d
    - Delineate3d
    - UnsharpMasking2d
    - UnsharpMasking3d
    - Shade2d
    - RichardsonLucyDeconvolution
  - Texture Filters
  - - MeanFilter2d
    - MeanFilter3d
    - VarianceFilter2d
    - VarianceFilter3d
    - SkewnessFilter2d
    - SkewnessFilter3d
    - KurtosisFilter2d
    - KurtosisFilter3d
    - ContrastFilter2d
    - ContrastFilter3d
    - VariationFilter2d
    - VariationFilter3d
    - EnergyFilter2d
    - EnergyFilter3d
    - EntropyFilter2d
    - EntropyFilter3d
    - AutocorrelationFilter
    - LocalAutocorrelationFilter2d
    - ImageCurvature2d
    - ImageCurvature3d
    - StructureEnhancementFilter2d
    - StructureEnhancementFilter3d
    - ScaleSpaceLogFilter2d
    - ScaleSpaceLogFilter3d
  - Frequency Domain
  - - ComplexFft
    - ComplexFftInverse
    - ComplexCenteredFft
    - ComplexCenteredFftInverse
    - CartesianToPolar2d
    - PolarToCartesian2d
    - ConvolutionWithImage
    - ConvolutionWithImage2d
    - RadialFrequencyFilter2d
    - GaborFiltering2d
- Edge Detection
- - Gradient
  - - GradientOperator2d
    - GradientOperator3d
    - VectorToMagnitude2d
    - VectorToMagnitude3d
    - GradientVector2d
    - GradientVector3d
    - GradientMagnitude2d
    - GradientMagnitude3d
    - MorphologicalGradient2d
    - MorphologicalGradient3d
    - RadialGradientCentered2d
    - RadialGradientCentered3d
    - RadialGradientContour2d
    - RadialGradientContour3d
    - RadialGradientLabel2d
    - RadialGradientLabel3d
  - Laplacian
  - - DobFilter2d
    - DobFilter3d
    - MorphologicalLaplacian
    - RecursiveLaplacian2d
    - RecursiveLaplacian3d
  - Other Derivatives
  - - GaussianDerivative2d
    - GaussianDerivative3d
    - GaussianHessianMatrix2d
    - GaussianHessianMatrix3d
    - GaussianGradientTensor2d
    - GaussianGradientTensor3d
  - Edge Marking
  - - ImageLocalMaxima2d
    - ImageLocalMaxima3d
    - RidgeDetection
    - ZeroCrossings2d
    - DijkstraShortestPath2d
    - EigenvaluesToStructureness2d
    - EigenvaluesToStructureness3d
    - TensorVoting2d
    - CannyEdgeDetector2d
    - CannyEdgeDetector3d
- Image Segmentation
- - Binarization
  - - Thresholding
    - ThresholdingByCriterion
    - AutoThresholdingBright
    - AutoThresholdingDark
    - ColorThresholding
    - TopHat
    - FeatureAdaptiveThresholding
    - AdaptiveThresholding2d
    - AdaptiveThresholding3d
    - HysteresisThresholding
  - Labeling
  - - Labeling2d
    - Labeling3d
    - ReorderLabels
    - AssignLabel
    - AddObjectToLabel
    - GroupCloseLabelsl2d
  - Feature Selection
  - - KillBorder2d
    - KillBorder3d
    - RemoveSmallSpots
    - ObjectBoundaries
    - BinarySmoothing2d
    - BinarySmoothing3d
    - LabelInterfaces
  - Separating And Filling
  - - FillHoles2d
    - FillHoles3d
    - RemoveSmallHoles
    - FillImageBorder3d
    - ExpandLabelBoundaries
    - SeparateObjects
    - HExtremaWatershed
    - SeparateObjectsByBlock
    - HExtremaWatershedByBlock
    - ConvexHull2d
  - Region Growing
  - - MarkerBasedWatershed2d
    - MarkerBasedWatershed3d
    - MarkerBasedWatershedByBlock
    - MarkerBasedWatershedBasinsByBlock
    - ExpandLabelsOnBackground
    - FloodFillThreshold2d
    - FloodFillThreshold3d
    - Waterpixel
  - Computational Geometry
  - - PolylineResampler2d
    - PolylineResampler3d
    - PolylineExtrusion3d
    - SurfaceFitting3d
- Mathematical Morphology
- - Erosion And Dilation
  - - Erosion2d
    - Erosion3d
    - Dilation2d
    - Dilation3d
    - ErosionDisk2d
    - ErosionDisk3d
    - ErosionBall3d
    - DilationDisk2d
    - DilationDisk3d
    - DilationBall3d
    - ErosionLine2d
    - ErosionLine3d
    - DilationLine2d
    - DilationLine3d
    - ErosionColor2d
    - DilationColor2d
    - SelectiveErosion2d
    - SelectiveErosion3d
    - SelectiveDilation2d
    - SelectiveDilation3d
  - Opening And Closing
  - - Opening2d
    - Opening3d
    - Closing2d
    - Closing3d
    - OpeningDisk2d
    - OpeningDisk3d
    - OpeningBall3d
    - ClosingDisk2d
    - ClosingDisk3d
    - ClosingBall3d
    - OpeningLine2d
    - OpeningLine3d
    - ClosingLine2d
    - ClosingLine3d
    - OpeningLineMaximum
    - ClosingLineMinimum
    - OpeningColor2d
    - ClosingColor2d
    - OpeningByReconstruction2d
    - OpeningByReconstruction3d
    - ClosingByReconstruction2d
    - ClosingByReconstruction3d
    - OpeningDiskByReconstruction2d
    - OpeningBallByReconstruction3d
    - ClosingDiskByReconstruction2d
    - ClosingBallByReconstruction3d
    - SelectiveOpening2d
    - SelectiveOpening3d
    - SelectiveClosing2d
    - SelectiveClosing3d
  - Hit Or Miss And Skeleton
  - - Skeleton
    - Centerline3d
    - InfluenceZones
    - Centroid2d
    - EndPoints2d
    - EndPoints3d
    - Pruning2d
    - Pruning3d
    - IsolatedPoints2d
    - IsolatedPoints3d
    - TriplePoints2d
    - InteriorPoints2d
    - ApplyMorphologicalLut2d
    - ApplyMorphologicalLut3d
  - Geodesic Transformations
  - - ReconstructionFromMarkers2d
    - ReconstructionFromMarkers3d
    - GrayscaleReconstruction2d
    - GrayscaleReconstruction3d
    - GrayscaleFillHoles2d
    - GrayscaleFillHoles3d
    - HExtrema2d
    - HExtrema3d
    - RegionalExtrema2d
    - RegionalExtrema3d
    - UltimateErosion
  - Distance Maps
  - - DistanceMap2d
    - DistanceMap3d
    - EuclideanDistanceMap3d
    - EuclideanDistanceMap2d
    - GeodesicDistanceMap
    - ClosestBoundaryPoints2d
    - ClosestBoundaryPoints3d
    - TimeMap
    - LocalThicknessMap3d
    - GeodesicPropagation2d
    - GeodesicMaxima
    - GeodesicMinima
- Image Analysis
- - Image Measurements
  - - BinaryAnalysis
    - Area2d
    - Area3d
    - IntensityIntegral2d
    - IntensityIntegral3d
    - ObjectCount
    - DistanceMean2d
    - EulerNumber2d
    - EulerNumber3d
    - FractalDimension
    - CurvatureIntegrals3d
  - Image Statistics
  - - IntensityExtrema
    - IntensityStatistics
    - IntensityMaskedStatistics
    - IntensityHistogram
    - IntensityBinHistogram
    - AutoThresholdingValue
    - CompareImage
    - CompareValue
    - SimilarityMetricValue
    - SsimValue2d
    - SsimValue3d
    - RegionSimilarity
    - RadialIntensityProfile2d
    - RadialIntensityProfile3d
    - CylindricalIntensityProfile3d
    - RadialAutocorrelationProfile
    - Cooccurrence2d
    - MeasureGaussianNoise
    - LocalMaxima2d
    - LocalMaxima3d
    - PeakExtractor
    - LocalDensityMap2d
    - LocalDensityMap3d
    - SegmentationMetrics
  - Individual Measurements
  - - VolumeFractionByLabel
    - LabelCountByRegion
    - VolumeFractionByRegion
    - LabelAnalysis
    - LabelFiltering
    - LabelFilteringAnalysis
    - FilterAnalysis
    - MeasurementToImage
    - FilterByMeasurement
    - SieveLabeling
  - Moments And Orientations
  - - MomentsOfInertia2d
    - MomentsOfInertia3d
    - InertiaMoment2d
    - Eccentricity2d
    - OrientationMapFourier3d
    - OrientationMatchingFourier3d
  - Morphometry
  - - ObjectVolume
    - TotalImageVolume
    - ObjectBoundaryArea
    - TotalImageBoundaryArea
    - AverageObjectAreaPerSlice3d
    - AverageObjectCountPerSlice3d
    - ObjectImageRatio
    - ObjectSpecificSurface
    - ObjectSurfaceDensity
    - PorosityPercentage3d
    - FragmentationIndex
    - StructureModelIndex3d
    - AverageObjectThickness3d
    - AverageSpaceThickness3d
    - ObjectLinearDensity3d
    - DegreeOfAnisotropy
  - Propagation
  - - AxisPropagationBinary3d
    - AxisPropagationBinaryWithSeeds3d
    - AxisPropagationLabel3d
    - AxisPropagationLabelWithSeeds3d
    - AxisPropagationDistance3d
    - EstimateShortestPath3d
    - PercolationThreshold3d
    - AxisConnectivity3d
    - CentroidPathTortuosity3d
- Machine Learning
- - Classification
  - - AutoSegmentation3Phases
    - AutoIntensityClassification
    - SupervisedTextureClassification2d
    - SupervisedTextureClassification3d
    - TextureClassificationCreate
    - TextureClassificationTrain
    - TextureClassificationApply
  - Deep learning
  - - OnnxPredictionFiltering2d
    - OnnxPredictionFiltering3d
    - OnnxPredictionSegmentation2d
    - OnnxPredictionSegmentation3d
    - OnnxPredictionTwoOutputs2d
    - OnnxPredictionTwoOutputs3d
- Business Application
- - Dental
  - - DentalWallSegmentation3d
    - DentalMeshExtraction3d
    - DentalUnfolding3d
- IO
- - Image Data
  - - ReadVipImage
    - WriteVipImage
  - Algebraic Data
  - - ReadArrayXd
    - ReadArrayXi64
    - WriteArrayXd
    - WriteArrayXi64
  - Model
  - - ReadOnnxModel
- CUDA
- - Geometry And Matching
  - - CudaCrossCorrelation2d
    - CudaTemplateMatching3d
  - Image Filtering
  - - CudaBoxFilter2d
    - CudaMedianFilter2d
    - CudaGaussianFilter3d
    - CudaAdaptiveManifoldNlmFilter
  - Mathematical Morphology
  - - CudaErosion2d
    - CudaDilation2d
    - CudaOpening2d
    - CudaClosing2d
- Utilities
- Initialization
- Processing
- Syntax Check
- Visualization
- Data Object
- Image Data
- Kernels
- - MorphologicalKernel2d
  - MorphologicalKernel3d
  - MorphologicalLut2d
  - MorphologicalLut3d
- Model
- - TextureClassificationModel
  - OnnxModel
- Global Measurements
- - Image Measurements
  - - Area2dMsr
    - Area3dMsr
    - IntensityIntegral2dMsr
    - IntensityIntegral3dMsr
    - ObjectCountMsr
    - DistanceMeanMsr
    - Euler2dMsr
    - Euler3dMsr
    - FractalMsr
    - CurvatureIntegralsMsr
  - Image Statistics
  - - IntensityExtremaMsr
    - StatisticsMsr
    - IntensityHistogramMsr
    - IntensityBinHistogramMsr
    - CompareMsr
    - SimilarityMetricValueMsr
    - SsimValueMsr
    - RegionSimilarityMsr
    - SegmentationMetricsObjectMsr
    - SegmentationMetricsImageMsr
    - CylindricalIntensityProfileMsr
    - RadialIntensityProfileMsr
    - CorrelationMsr
    - CoocurrrenceMsr
    - GaussianNoiseMsr
    - LocalMaximaMsr
    - PeakExtractorMsr
  - Individual Measurements
  - - VolumeFractionByLabelMsr
    - LabelCountByRegionMsr
    - VolumeFractionByRegionMsr
  - Moments And Orientations
  - - MomentsOfInertia2dMsr
    - MomentsOfInertia3dMsr
    - MeanInertiaMomentMsr
    - Eccentricity2dMsr
    - LocalOrientation3dMsr
  - Morphometry
  - - ObjectVolumeMsr
    - ImageVolumeMsr
    - ObjectBoundaryAreaMsr
    - ImageBoundaryAreaMsr
    - AverageObjectAreaPerSliceMsr
    - AverageObjectCountPerSliceMsr
    - ObjectImageRatioMsr
    - ObjectSpecificSurfaceMsr
    - ObjectSurfaceDensityMsr
    - PorosityPercentageMsr
    - FragmentationMsr
    - StructureModelIndexMsr
    - AverageObjectThicknessMsr
    - AverageSpaceThicknessMsr
    - ObjectLinearDensityMsr
    - AnisotropyDegreeMsr
  - Propagation
  - - AxisPropagationBinary3dMsr
    - AxisPropagationLabel3dMsr
    - AxisPropagationDistance3dMsr
    - PercolationThreshold3dMsr
    - CentroidTortuosity3dMsr
  - Geometry And Matching
  - - CrossCorrelation2dMsr
  - Edge Detection
  - - CannyEdgeDetectorMsr
  - Image Segmentation
  - - AutoThresholdingMsr
    - AutoSegmentation3PhasesMsr
  - Mathematical Morphology
  - - ApplyMorphologicalLutMsr
- Analysis Measurements
- - AnalysisMsr
  - Measurement
  - Native Measurements
  - - Geometry
    - Feret
    - Intensity
    - Histogram
    - Inertia
    - Locate
    - Segment
    - Cooccurrence
  - CustomMeasurement
  - MeasurementAttributes
  - - Quantile
    - Histogram
    - Feret2d
    - Feret3d
    - NeighborCount
    - Cooccurrence
    - Breadth3d
  - MeasurementGroup
- Measurement Information
- - FieldInformation
  - CustomMeasurementInfo
- CUDA
- - CudaContext
- User Guide
- First Steps
- - Hello ImageDev
  - Initialize ImageDev
- Image Management
- - Create 2D Image
  - Create 3D Image
  - Data Transfer
- Standard Processing
- - Denoising
  - Thresholding
- Image Analysis
- - Global Analysis
  - Label Analysis
  - Measurement Browsing
  - Measurement Group
  - Custom Analysis
- Advanced Processing
- - Algorithm Tracking
- Typical Use Cases
- - Particle Analysis
  - Pore Analysis

# Measurement Browsing

This example shows how to automatically parse the content of a label analysis and export it in a csv file.
First, a grayscale image is opened and segmented to generate a label image containing 8 objects.
Then, an analysis is performed with three measurements selected. It computes for each object its area, a shape factor, and a set of oriented diameters. The FeretDiameter measurement generates by default an array of 10 diameters corresponding to different orientations with a pitch of 18 degrees.
A first loop shows how to introspect the analysis to get the name of each selected measurement and deploy the array of diameters. A second loop shows how to introspect the analysis to print the measurement results for each object and deploys the diameter distribution. This step demonstrates the ability to browse the content of an analysis without making assumptions about the measurements that have been selected within.

Label | Area2d(mm^2) | InverseCircularity2d() | FeretDiameter2d[0](mm) | FeretDiameter2d[1](mm)
1 | 1058.00 | 1.23 | 35.00 | 38.73
2 | 1361.00 | 3.70 | 47.00 | 49.31
3 | 1086.00 | 1.26 | 38.00 | 35.54
4 | 293.00 | 1.81 | 20.00 | 18.40

In practice, the analysis can be directly converted to a spreadsheet structure with the toDataFrame method. It generates an IOLink DataFrameView object. In Python, this object can be directly printed in the standard output.

Index [label] | Area2d | InverseCircularity2d | ... | FeretDiameter2d[direction=9]
0 | 1058 | 1.2297213077545166 | ... | 38.72925567626953
1 | 1361 | 3.698363780975342 | ... | 49.00188064575195
2 | 1086 | 1.2601970434188843 | ... | 42.93851089477539
3 | 293 | 1.8089686632156372 | ... | 22.111291885375977

Finally, IOFormat allows the export of a DataFrameView object in a csv file that can be visualized as an Excel table. This method is more straightforward for exporting an analysis. The previous one gives you more freedom to customize the export for your needs.

    #include <ImageDev/ImageDev.h>
    #include <ioformat/IOFormat.h>
    #include <string.h>

    using namespace imagedev;
    using namespace ioformat;
    using namespace iolink;

    int
    main( int argc, char* argv[] )
    {
        int status = 0;

        try
        {
            // ImageDev library initialization if not done
            if ( isInitialized() == false )
                imagedev::init();

            // Open a grayscale image from a tif file
            auto imageInput = readImage( std::string( IMAGEDEVDATA_IMAGES_FOLDER ) + "objects.tif" );

            // Threshold and label the binary input
            auto imageBin = thresholdingByCriterion( imageInput,
                                                     ThresholdingByCriterion::ComparisonCriterion::GREATER_THAN_OR_EQUAL_TO,
                                                     40 );
            auto imageLab = labeling2d( imageBin, Labeling2d::LABEL_8_BIT, Labeling2d::CONNECTIVITY_8 );

            // Calibrate this image to match 1 pixel to 1.4 mm
            Vector3d spacing{ 1.4, 1.4, 1 };
            imageLab->setSpatialSpacing( spacing );
            imageLab->setSpatialUnit( "mm" );

            // Define the analysis features to be computed
            AnalysisMsr::Ptr analysis = std::make_shared< AnalysisMsr >();
            analysis->select( NativeMeasurements::area2d );
            analysis->select( NativeMeasurements::inverseCircularity2d );
            analysis->select( NativeMeasurements::feretDiameter2d );

            // Launch the feature extraction on the segmented image
            labelAnalysis( imageLab, imageInput, analysis );

            // Print the analysis table header
            std::string lineToPrint( "Label\t" );
            for ( const auto& measure : analysis->getMeasurements() )
            {
                // Build and print the table header
                if ( measure->shape().size() == 1 )
                    // The measurement is a scalar value
                    lineToPrint += measure->name() + "(" + measure->information().physicalUnit() + ")\t";
                else if ( measure->shape().size() == 2 )
                    // The measurement is an array, loop on it
                    for ( size_t j = 0; j < measure->shape()[1]; ++j )
                        lineToPrint += measure->name() + "[" + std::to_string( j ) + "](" +
                                       measure->information().physicalUnit() + ")\t";
            }
            std::cout << lineToPrint << std::endl;

            VectorXu64 index;
            // Print all measurement results for each label
            for ( int i = 0; i < analysis->labelCount(); ++i )
            {
                lineToPrint = std::to_string( i + 1 ) + "\t";
                for ( const auto& measure : analysis->getMeasurements() )
                {
                    index = measure->shape();
                    index[0] = i;
                    if ( measure->shape().size() == 1 )
                        // The measurement is a scalar value
                        lineToPrint += std::to_string( measure->toDouble( index ) ) + "\t";
                    else if ( measure->shape().size() == 2 )
                        // The measurement is an array, loop on it
                        for ( size_t j = 0; j < measure->shape()[1]; ++j )
                        {
                            index[1] = j;
                            lineToPrint += std::to_string( measure->toDouble( index ) ) + "\t";
                        }
                }
                std::cout << lineToPrint << std::endl;
            }

            // Export the analysis in a dataframe and save it in a csv file
            auto dataframe = analysis->toDataFrame();
            writeView( dataframe, "T04_03_analysis.csv" );

            std::cout << "This example ran successfully." << std::endl;
        }
        catch ( const imagedev::Exception& error )
        {
            // Print potential exception in the standard output
            std::cerr << "T04_03_MeasurementBrowsing exception: " << error.what() << std::endl;
            status = -1;
        }

        // ImageDev library finalization
        imagedev::finish();

        // Check if we must ask for an enter key to close the program
        if ( !( ( argc == 2 ) && strcmp( argv[1], "--no-stop-at-end" ) == 0 ) )
            std::cout << "Press Enter key to close this window." << std::endl, getchar();

        return status;
    }

    ﻿using System;
    using ImageDev;
    using IOLink;
    using IOFormat;
    using System.Linq;

    namespace T04_03_MeasurementBrowsing
    {
        class Program
        {
            static void Main( string[] args )
            {
                int status = 0;

                try
                {
                    // Initialize the ImageDev library if not done
                    if ( Initialization.IsInitialized() == false )
                        Initialization.Init();

                    // Open a grayscale image from a tif file
                    ImageView imageInput = ViewIO.ReadImage( "Data/images/objects.tif" );

                    // Threshold and label the binary input
                    var imageBin = Processing.ThresholdingByCriterion(
                        imageInput, ThresholdingByCriterion.ComparisonCriterion.GREATER_THAN_OR_EQUAL_TO, 40 );
                    var imageLab = Processing.Labeling2d( imageBin );

                    // Calibrate this image to match 1 pixel to 1.4 mm
                    Vector3d spacing = new Vector3d( 1.4, 1.4, 1 );
                    imageLab.SpatialSpacing = spacing;
                    imageLab.SpatialUnit = "mm";

                    // Define the analysis features to be computed
                    AnalysisMsr analysis = new AnalysisMsr();
                    analysis.Select( NativeMeasurements.Area2d );
                    analysis.Select( NativeMeasurements.InverseCircularity2d );
                    analysis.Select( NativeMeasurements.FeretDiameter2d );

                    // Launch the feature extraction on the segmented image
                    Processing.LabelAnalysis( imageLab, imageInput, analysis );

                    // Print the analysis table header
                    string lineToPrint = "Label\t";
                    foreach ( var measure in analysis.Measurements() )
                    {
                        // Build and print the table header
                        if ( measure.Shape().Length == 1 )
                            // The measurement is a scalar value
                            lineToPrint += measure.Name() + "(" + measure.information.physicalUnit + ")\t";
                        else if ( measure.Shape().Length == 2 )
                            // The measurement is an array, loop on it
                            for ( int j = 0; j < measure.Shape()[1]; ++j )
                                lineToPrint += measure.Name() + "[" + j + "](" + measure.information.physicalUnit + ")\t";
                    }
                    Console.WriteLine( lineToPrint );

                    int[] index;
                    // Print all measurement results for each label
                    for ( int i = 0; i < analysis.LabelCount(); ++i )
                    {
                        lineToPrint = ( i + 1 ) + "\t";
                        foreach ( var measure in analysis.Measurements() )
                        {
                            index = measure.Shape();
                            index[0] = i;
                            if ( measure.Shape().Length == 1 )
                                // The measurement is a scalar value
                                lineToPrint +=
                                    measure.ToDouble( index.Select( item => ( long )item ).ToArray() ).ToString() + "\t";
                            else if ( measure.Shape().Length == 2 )
                                // The measurement is an array, loop on it
                                for ( int j = 0; j < measure.Shape()[1]; ++j )
                                {
                                    index[1] = j;
                                    lineToPrint +=
                                        measure.ToDouble( index.Select( item => ( long )item ).ToArray() ).ToString() +
                                        "\t";
                                }
                        }
                        Console.WriteLine( lineToPrint );
                    }

                    // Export the analysis in a dataframe and save it in a csv file
                    DataFrameView dataframe = analysis.ToDataFrame();
                    ViewIO.WriteView( dataframe, "T04_03_analysis.csv" );

                    // Notify the garbage collector that the created images can be freed
                    imageInput.Dispose();
                    imageBin.Dispose();
                    imageLab.Dispose();

                    Console.WriteLine( "This example ran successfully." );
                }
                catch ( Exception error )
                {
                    // Print potential exception in the standard output
                    System.Console.WriteLine( "T04_03_MeasurementBrowsing exception: " + error.ToString() );
                    status = -1;
                }

                // ImageDev library finalization
                Initialization.Finish();

                // Check if we must ask for an enter key to close the program
                if ( !( ( args.Length >= 1 ) && ( args[0] == "--no-stop-at-end" ) ) )
                {
                    System.Console.WriteLine( "Press Enter key to close this window." );
                    System.Console.ReadKey();
                }

                System.Environment.Exit( status );
            }
        }
    }

    import imagedev
    import imagedev_data
    import ioformat
    import iolink

    try:
        # Open a grayscale image from a tif file
        image_input = ioformat.read_image(imagedev_data.get_image_path('objects.tif'))

        # Threshold and label the binary input
        image_bin = imagedev.thresholding_by_criterion(image_input, comparison_value=40)
        image_lab = imagedev.labeling_2d(image_bin, imagedev.Labeling2d.LabelType.LABEL_8_BIT)

        # Calibrate this image to match 1 pixel to 1.4 mm
        image_lab.spatial_spacing = iolink.Vector3d(1.4, 1.4, 1)
        image_lab.spatial_unit = 'mm'

        # Define the analysis features to be computed
        analysis = imagedev.AnalysisMsr()
        analysis.select(imagedev.native_measurements.Area2d)
        analysis.select(imagedev.native_measurements.InverseCircularity2d)
        analysis.select(imagedev.native_measurements.FeretDiameter2d)

        # Launch the feature extraction on the segmented image
        imagedev.label_analysis(image_lab, image_input, analysis)

        # Print the analysis table header
        line_to_print = 'Label\t'
        for measure in analysis.measurements:
            # Build and print the table header
            if len(measure.shape) == 1:
                # The measurement is a scalar value
                line_to_print += measure.name + '(' + measure.information.physical_unit + ')\t'
            elif len(measure.shape) == 2:
                # The measurement is an array, loop on it
                for j in range(0, measure.shape[1]):
                    line_to_print += measure.name + '[' + str(j) + '](' + measure.information.physical_unit + ')\t'
        print(line_to_print)

        # Print all measurement results for each label
        for i in range(0, analysis.label_count):
            line_to_print = str(i + 1) + '\t\t'
            for measure in analysis.measurements:
                if len(measure.shape) == 1:
                    # The measurement is a scalar value
                    line_to_print += '{:.2f}'.format(measure.value(i)) + '\t\t'
                elif len(measure.shape) == 2:
                    # The measurement is an array, loop on it
                    for j in range(0, measure.shape[1]):
                        line_to_print += '{:.2f}'.format(measure.value(i, j)) + '\t\t\t\t'
            print(line_to_print)

        # Export the analysis in a dataframe and save it in a csv file
        dataframe = analysis.to_data_frame()
        print(dataframe)
        ioformat.write_view(dataframe, 'T04_03_analysis.csv')

        print("This example ran successfully.")
    except Exception as error:
        # Print potential exception in the standard output
        print("T04_03_MeasurementBrowsing exception: " + str(error))

See also

- LabelAnalysis
- AnalysisMsr
- Measurement
- FieldInformation
- Geometry
- Feret

© 2025 Thermo Fisher Scientific Inc. All rights reserved.