Custom Analysis
This example shows how to set the attributes of a measurement and how to create a new measurement from a user defined formula.
Several native measurements of ImageDev can be customized by setting some parameters. For instance, the
orientation of the Feret diameters to be computed can be user-defined. By default, the Feret diameter
measurement contains 10 orientations with a pitch of 18 degrees.
This example shows first how to reduce these orientations to 0 and 90 degrees by selecting two diameters and resampling the distribution between 0 and 180 degrees. The setOrientation method can also be used for this purpose, especially if the expected distribution is not uniform.
Then, this example shows how to create a new measurement from a user-defined formula corresponding to a circularity factor. The validity of the formula is checked, and the new measurement is selected in the analysis.
See also
This example shows first how to reduce these orientations to 0 and 90 degrees by selecting two diameters and resampling the distribution between 0 and 180 degrees. The setOrientation method can also be used for this purpose, especially if the expected distribution is not uniform.
Then, this example shows how to create a new measurement from a user-defined formula corresponding to a circularity factor. The validity of the formula is checked, and the new measurement is selected in the analysis.
#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 ); // Change the number of Feret diameter to 2 (0 and 90 degrees) MeasurementAttributes::feret2d()->setOrientationCount( 2 ); MeasurementAttributes::feret2d()->resample(); std::cout << "FeretDiameter[0] = " + std::to_string( MeasurementAttributes::feret2d()->orientation( 0 ) ) << std::endl; std::cout << "FeretDiameter[1] = " + std::to_string( MeasurementAttributes::feret2d()->orientation( 1 ) ) << std::endl; // Create a circularity factor between 0 and 1 std::string myFormula( "4*Pi*" + NativeMeasurements::area2d->name() + "/" + NativeMeasurements::polygonePerimeter2d->name() + "**2" ); if ( !checkMeasurementFormula( myFormula ) ) // Raise an exception if the formula is not valid throw imagedev::Exception( "Invalid formula: " + myFormula ); const auto* myCircularity = AnalysisMsr::registerCustomMeasurement( "MyCircularity", myFormula, "A circularity factor between 0 and 1." ); // Define the analysis features to be computed AnalysisMsr::Ptr analysis = std::make_shared< AnalysisMsr >(); analysis->select( NativeMeasurements::feretDiameter2d ); analysis->select( myCircularity ); // Launch the feature extraction on the segmented image labelAnalysis( imageLab, imageInput, analysis ); // Export the analysis in a dataframe and save it in a csv file auto dataframe = analysis->toDataFrame(); writeView( dataframe, "T04_04_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_05_CustomAnalysis 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; namespace T04_05_CustomAnalysis { 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 ); // Change the number of Feret diameter to 2 (0 and 90 degrees) MeasurementAttributes.feret2d().orientationCount = 2; MeasurementAttributes.feret2d().Resample(); Console.WriteLine( "FeretDiameter[0] = " + MeasurementAttributes.feret2d().Orientation( 0 ) ); Console.WriteLine( "FeretDiameter[1] = " + MeasurementAttributes.feret2d().Orientation( 1 ) ); // Create a circularity factor between 0 and 1 string myFormula = "4*Pi*" + NativeMeasurements.Area2d.name + "/" + NativeMeasurements.PolygonePerimeter2d.name + "**2"; if ( !Processing.CheckMeasurementFormula( myFormula ) ) // Raise an exception if the formula is not valid throw new Exception( "Invalid formula: " + myFormula ); var myCircularity = AnalysisMsr.RegisterCustomMeasurement( "MyCircularity", myFormula, "A circularity factor between 0 and 1." ); // Define the analysis features to be computed AnalysisMsr analysis = new AnalysisMsr(); analysis.Select( NativeMeasurements.FeretDiameter2d ); analysis.Select( myCircularity ); // Launch the feature extraction on the segmented image Processing.LabelAnalysis( imageLab, imageInput, analysis ); // Export the analysis in a dataframe and save it in a csv file DataFrameView dataframe = analysis.ToDataFrame(); ViewIO.WriteView( dataframe, "T04_05_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_05_CustomAnalysis 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 try: # Initialize the ImageDev library if not done if not imagedev.is_initialized(): imagedev.init() # 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) # Change the number of Feret diameter to 2 (0 and 90 degrees) imagedev.MeasurementAttributes.feret2d.orientation_count = 2 imagedev.MeasurementAttributes.feret2d.resample() print(f'FeretDiameter[0] = {imagedev.MeasurementAttributes.feret2d.orientation(0)}') print(f'FeretDiameter[1] = {imagedev.MeasurementAttributes.feret2d.orientation(1)}') # Create a circularity factor between 0 and 1 my_formula = '4*Pi*' + imagedev.native_measurements.Area2d.name + '/' + \ imagedev.native_measurements.PolygonePerimeter2d.name + '**2' if not imagedev.check_measurement_formula(my_formula): # Raise an exception if the formula is not valid raise Exception('Invalid formula ' + my_formula) my_circularity = imagedev.AnalysisMsr.register_custom_measurement('MyCircularity', my_formula, 'A circularity factor between 0 and 1.') # Define the analysis features to be computed analysis = imagedev.AnalysisMsr() analysis.select(imagedev.native_measurements.FeretDiameter2d) analysis.select(my_circularity) # Launch the feature extraction on the segmented image imagedev.label_analysis(image_lab, image_input, analysis) # Print the analysis in the standard output print(analysis.to_data_frame()) print("This example ran successfully.") except Exception as error: # Print potential exception in the standard output print("T04_05_CustomAnalysis exception: " + str(error)) # ImageDev library finalization imagedev.finish()
See also