Home Image-Pro Automation (Macros, Apps, Reports)

Data Collector

Hi,
I need to define a couple of user measurements in DC.
I tried using the NEW command (Datacollector->Types->New) but it seems that only a limited logical and aritmetric functions can be used (according to the Microsoft documentation).
Both my new measurements require the Square Root math function (Sqr(Region_Area) & Sqr(Feretmax^2 + Feretmin^2)).
any suggestion about how to face this requirement?
Thank you 
ciao
Maurizio

Answers

  • Hi Maurizio,

    Data Collector's formula is limited to basic logical and arithmetical operations, it doesn't support SQRT. 

    Complex formula can be implemented in user-defined measurements (right in Count/Size), you can check the example projects UserMearurements  and UserMeasurements2. Or you can give me the exact formula you want to implement and I will make the sample project for that.

    Regards,

    Yuri

  • Hi Yuri,
    I had a look of UserMeasurements2 App.
    Now is clear how to create the new measurements but not how and where insert the code in my App
    A couple of questions:
    1. the new measurements must be created and added to the types list any time I load the count/size option file (with the selected measurements) ?
    2. Can the user measurements be collected in the Data Collector?

    The formulas I need to create are the following:
    Sqr(Region_Area) // Sqrt of Area
    Sqr(Feretmax^2 + Feretmin^2)). // Sqrt of Minimum Feret Diameter^2 + Maximum Feret Diameter^2
    thank you
    Maurizio
  • Hi Maurizio,

    I've attached the project that will calculate these measurements automatically. 
    Measurement registration is done in Project_Load event, so as soon as you load the project the measurements will be registered and added to the Selected measurements list:
        Public Sub ThisProject_Loading() Handles ThisProject.Loading
            'automatically register measurement at Project Load
            Register()
        End Sub
    The measurement calculation is done in the _meas.ComputeValue handler. Feret Sum is calculated as following:

    
        Private Sub _meas_ComputeValue(ByVal MeasurementObject As MediaCy.IQL.Features.IMcMeasure, ByVal ParentOperator As Object, ByRef vValue As Object) Handles _meas.ComputeValue
            Dim myRegions As McRegions=ParentOperator
            Dim om As McOMGlobal=ThisApplication.Engine.McObjects.GlobalTools
            With om
                'get array of values
                Dim Feretmax As Object=myRegions.mRgnMaxCaliper.value
                Dim Feretmin As Object=myRegions.mRgnMinCaliper.value
                Dim outValues As New System.Collections.ArrayList()'allocate output array
                For i As Integer=0 To myRegions.Count-1
                    'calculate output value as
                    'Sqrt of Minimum Feret Diameter^2 + Maximum Feret Diameter^2
                    Dim v As Double=System.Math.Sqrt(Feretmax(i)*Feretmax(i)+Feretmin(i)*Feretmin(i))
                    outValues.Add(v)
                Next
                vValue= outValues.ToArray() 'return result as array
            End With
        End Sub
    
    All new custom measurements will be handled in the same way as normal, build in measurements, they support macro recording and can be added to the selected measurements list like this:

        Public Function AddCutomMeasuresToMeadTable() As SimpleScript
            AddCutomMeasuresToMeadTable = New SimpleScript
            Dim doc1
    
            With Application.DocumentCommands.Active(AddCutomMeasuresToMeadTable)
                .Run(doc1)
            End With
    
            With Measure.MeasurementsCommands.Options(AddCutomMeasuresToMeadTable)
                .SelMeasurements = New MeasCollection()
                    .SelMeasurements.Add( New MeasEntry("mRgnUserAreaSqrt"))
                    .SelMeasurements.Add( New MeasEntry("mRgnUserFeretSum"))
                .Segmentation.FilterRanges = New System.Collections.Generic.List(Of MeasFilterEntry)
                    .Segmentation.FilterRanges.Add( New MeasFilterEntry("mRgnUserFeretSum",-1.7E+308R,1.7E+308R))
                    .Segmentation.FilterRanges.Add( New MeasFilterEntry("mRgnUserAreaSqrt",-1.7E+308R,1.7E+308R))
                .Run(doc1)
            End With
    
        End Function
    

    Or to the Data Collector,  I just recorded that macro clicking the Sync button in the Data Collector when Measurement table is selected:

        Public Function AddCustomMeasuresToDataCollector() As SimpleScript
            AddCustomMeasuresToDataCollector = New SimpleScript
    
            With Measure.Data.Collector.MeasurementsCommands.Sync(AddCustomMeasuresToDataCollector)
                .ProviderName = "Measurements"
                .Run()
            End With
    
        End Function
    

    Please test it and let me know if you have questions.

    Regards,

    Yuri

  • Dear Yuri,
    Thank you for your exhaustive explanation.
    I have implemented your code in my App.
    The code has been grouped in a separate module named AddUserMeas.
    The AddUserMeas code 
    Public Module AddUserMeas
    
    'Example project demonstrating user-defined measurements in interpreted projects.
    'The project shows adding a simple event-based user defined measurement.
    '
    'The extended samples of user-defined measurements see "UserMeasurement" demo project.
    '
        'registration variable to register the measurement when project is loaded
        'and unregister when project is auloaded
        Public myregMeas As New UserMeasurementWithRegistration
        Public Sub Register()
            myregMeas.RegisterExampleUserMeasurements()
        End Sub
        Public Sub Unregister()
            myregMeas.UnregisterExampleUserMeasurements()
        End Sub
    End Module
    
    'registration class for user measurement
    Public Class UserMeasurementWithRegistration
        'measurement name
        Public measName As String="mRgnUserDiametro"
        Public measNameArea As String="mRgnSqrArea"
        'user measure variable that receives events
        Public WithEvents _meas As McUserMeasureClass
    
        'add measurement to the list of selected measurements in Count/Size
        Private Sub AddMeasurementToSelected(measName1 As String)
            With MediaCy.Addins.Measurements.McMeasurements.ThisAddin.Options
                If Not .SelMeasurements.ContainsMeas(measName1) Then
                    .SelMeasurements.Add(New MeasEntry(measName1))
                End If
            End With
        End Sub
    
        'register measurement
        Public Sub RegisterExampleUserMeasurements()
            With ThisApplication
                'Only register measurements if they are not already registered
                If .GetRegisteredUserMeasurement(measName) Is Nothing Then
                    'create measurement object and attach events
                    .RegisterUserMeasurement( measName, RegisterAndSync, mcmpaChildOfRegions)
                    AddMeasurementToSelected(measName)
                End If
                If .GetRegisteredUserMeasurement(measNameArea) Is Nothing Then
                    'create measurement object and attach events
                    .RegisterUserMeasurement(measNameArea, RegisterAndSync, mcmpaChildOfRegions)
                    AddMeasurementToSelected(measNameArea)
                End If
    
            End With
        End Sub 'RegisterExampleUserMeasurements
    
        Public Sub UnregisterExampleUserMeasurements()
            With ThisApplication
                'Only register measurements if they are not already registered
                If .GetRegisteredUserMeasurement(measName) IsNot Nothing Then
                    'create measurement object and attach events
                    .RegisterUserMeasurement( measName, Nothing, mcmpaChildOfRegions)
                    Unregister
                End If
            End With
        End Sub 'UnregisterExampleUserMeasurements
    
        'create new measurement instance and connect events
        Public Function RegisterAndSync() As McUserMeasureClass
            Unregister()
            'event handlers are added here
            _meas = New McUserMeasureClass()
            Return _meas
        End Function
    
        'disconnect events
        Public Sub Unregister()
            _meas=Nothing
        End Sub
    Public Function AddCutomMeasuresToMeadTable() As Boolean
        'AddCutomMeasuresToMeadTable = New SimpleScript
        Dim doc1
    
        With Application.DocumentCommands.Active(Nothing)
            .Run(doc1)
        End With
    
        With Measure.MeasurementsCommands.Options(Nothing)
            .SelMeasurements = New MeasCollection()
                .SelMeasurements.Add( New MeasEntry("mRgnUserAreaSqrt"))
                .SelMeasurements.Add( New MeasEntry("mRgnUserDiagonale"))
            .Segmentation.FilterRanges = New System.Collections.Generic.List(Of MeasFilterEntry)
            .Segmentation.FilterRanges.Add( New MeasFilterEntry("mRgnUserDiagonale",-1.7E+308R,1.7E+308R))
            .Segmentation.FilterRanges.Add( New MeasFilterEntry("mRgnUserAreaSqrt",-1.7E+308R,1.7E+308R))
            .Run(doc1)
        End With
        Return True
        End Function
    
    
    #Region "Measurement events"
        Private Sub _meas_GetDisplayName(ByVal MeasurementObject As MediaCy.IQL.Features.IMcMeasure, ByRef MName As String) Handles _meas.GetDisplayName
            'set measurement name
            MName="Diagonale"
        End Sub
    
        Private Sub _meas_GetDescription(ByVal MeasurementObject As MediaCy.IQL.Features.IMcMeasure, ByRef Desc As String) Handles _meas.GetDescription
            'set measurement description
            Desc="User Diagonale measurement defined as [Sqrt(Feretmax^2 + Feretmin^2)]"
        End Sub
    
        Private Sub _meas_GetAttributes(ByVal MeasurementObject As MediaCy.IQL.Features.IMcMeasure, ByVal AttributeId As MediaCy.IQL.Features.mcMeasurementAttributeID, ByRef Attributes As Object) Handles _meas.GetAttributes
            'Select Case AttributeId
            'Case MediaCy.IQL.Features.mcMeasurementAttributeID.mcmaidIllustration
                   'get illustration from app resources
            '       Dim resources As MediaCy.Addins.Scripting.AppResourceManager = New MediaCy.Addins.Scripting.AppResourceManager("AnsaldoGPT2_Project>AnsaldoGPT2_App")
            '       Attributes = Mediacy.Controls.Common.Vb.McImageUtils.BitmatToStdPicture(resources.GetObject("pictureBox1.Image"))
            'End Select
            'other attributes are default
        End Sub
    
        Private Sub _meas_ComputeValue(ByVal MeasurementObject As MediaCy.IQL.Features.IMcMeasure, ByVal ParentOperator As Object, ByRef vValue As Object) Handles _meas.ComputeValue
            Dim myRegions As McRegions=ParentOperator
            Dim om As McOMGlobal=ThisApplication.Engine.McObjects.GlobalTools
            With om
                'get array of values
                Dim Feretmax As Object=myRegions.mRgnMaxCaliper.value
                Dim Feretmin As Object=myRegions.mRgnMinCaliper.value
                Dim outValues As New System.Collections.ArrayList()'allocate output array
                For i As Integer=0 To myRegions.Count-1
                    'calculate output value as
                    'Sqrt of Minimum Feret Diameter^2 + Maximum Feret Diameter^2
                    Dim v As Double=System.Math.Sqrt(Feretmax(i)*Feretmax(i)+Feretmin(i)*Feretmin(i))
                    outValues.Add(v)
                Next
                vValue= outValues.ToArray() 'return result as array
            End With
        End Sub
    #End Region
    End Class
    
    It works fine.
    The 2 new measurements are added to the types list (selected meaurements)
    The problem now is the following
    when an option file (with a list of measurements) is loaede the 2 new measurements desapear (andthis is correct). I need to add the new measurements after the file is loaded, is there any solution?
    The reason is simple, during the App execution several option files are loaded but only in  few cases I need the new measurements.
    
    Another question
    The Sub _meas_ComputeValue calculates only one meaurement (eg diameter), where should I insert the code to calculate the 2nd one?
    Thank for your patience Ciao Maurizio

  • Hi Maurizio,

    Good that it works directly! 

    Regarding the options file: you just have to save a new options file with these measurements. Load old options file, add these 2 measurements and then save the options file under the same name.

    My project contains 2 classes: UserMeasurementWithRegistration1 and UserMeasurementWithRegistration2, one class per measure, each class contains own _meas_Compute sub, so you should also have 2 of them.

    Regards,

    Yuri

  • edited December 2015
    Hi Maurizio,

    I looked again on your code and have some more comments:

    1. You have AddCutomMeasuresToMeadTable sub inside UserMeasurementWithRegistration class. You should not put any your macros inside this class. The best way is to add another Module2.vb to the project where you have your own public functions. Also AddCutomMeasuresToMeadTable should not be necessary at all if you use Options file that would add these measurements.
    I would just recommend to take the complete Module1.vb from my project to yours (you can rename the file if you already have Module1.vb).

    2. I see that you call the measurement "
    Diagonale". Is the purpose of this measurement to calculate diagonal length of rectangular objects? In that case "Caliper Max"(mRgnMaxCaliper) measurement should already provide this measurement.   
    If you want to calculate rectangle diagonal yourself you should use Width (mRgnWidth) and Length (mRgnLength) measurements that return Feret length along the minor and major axes of the object (two sides of rectangle).

    Regards,

    Yuri

Sign In or Register to comment.