Home Image-Pro General Discussions

Dynamic angle change measurement

Hi,
How can I measure the 'change of angles' of a moving object? I am able to measure the change of diameter or surface area of deformable moving object but for the contact angle, I cannot do it. I will highly appreciate any help. If you need any more info please let me know.

Thanks
Abrar

Best Answer

  • Answer ✓
    Hi Abrar,

    Since the Relative measurements are based on selected objects you must have objects selected before running the macro. Or activate macro recording before object selection and record all steps. You can also add an interactive step asking user to select objects and continue. (Check the forum how to make a command to be interactive)

    Yuri

Answers

  • 2017-04-12-150901

    Abrar --

    Would it be possible for you to post a series of images that illustrate the challenge that you face?

    If you can do that I'm sure that someone on the forum can help you achieve your goal.

    -- Matt
  • Abrar,

    There is "Direction" measurement available that reports orientation (angle) of the object. Check if it will work for you.

    Yuri

  • Hi @mbatchelor and @YuriG
    here are some images of contact angle measurement that I measured manually. But I want to measure them for each frame of the video using count options. Thanks in advance.
     

  • 2017-04-12-171030

    Abrar --

    Thank you for your example images.  They assist in understanding your challenge.

    I must leave my desk for an appointment but I will look at this early tomorrow (THU) AM (HOUSTON TEXAS TIME) and reply.

    Thanks again.

    -- Matt

  • Abrar,

    Every point of the contour has different angle, so you have to detect specific points on the edge and determine the angle.
    One of the ways would be to use Sculpture filter, which is also called "Phase filter" based on the Sobel detection, which assigns intensity to the pixels corresponded to the orientation of the edge gradient, so you can measure intensity of the result pixel and report orientation of the edge. The screenshot below illustrates this. I binarized image first and applied Sculpture filter, the right image is pseudo-colored to show that every pixel on the sphere boundary has different intensity.



    Another way is to detect specific points on the outline, for example by using 2 horizontal lines with fixed distance between them and then calculate angle based on the start/end points of these lines.
    On the screenshot below, these are L1 and L2 lines, these lines are created using the "Snap" tool, so they start/end exactly on the edge of the object. Then the derived CCD5 line between line start points is created and the angle AB6 is created between lines CCD5 and L1:


    These measurements can be automated by a macro.

    Yuri
  • 2017-04-13-100528

    Yuri --

    The information you provided looks great.

    The second section is pretty close to the way I was going to suggest going.

    I hope this is helpful to Abrar.

    -- Matt
  • Hi @YuriG and @mbatchelor , Thanks a lot for the answer. But as a beginner I have a question, what do you mean by 'deriveed CCD5 line' and 'angle AB6'? I couldnot make any. I will highly appreciate if you can explain them a bit.

    Thanks
    Abrar

  • edited April 2017
    Hi Abrar,

    I was talking about Relative group on the Measure tab:



    You can create some measurements manually (e.g. L1 and L2), select them and create derived (relative) measurements based on the selected features, it can be Starting Point, Center-to-center distance, Angle between lines, etc. Using these tools you can create the Angle measurement you want based on the L1 and L2 lines in several steps.

    Yuri

  • Hi ,
    I did what you said but while running macro I got the message like, "No objects are selected. Please select 2 or more objects and try again." Where am i doing mistakes ?

    Thanks
    Abrar

  • Hi @YuriG
    I am able to run the macros and thanks to you but I am still facing problems measuring angles. Because angles lines are not moving with the selected objects. For your understanding I have attached two samples. (I used 'snap to straight edge tool ' to draw lines.)
    During Macro recording:

    Implementation of macro in new figure:


    Thanks in advance.
  • Abrar,

    The steps that create Angle measurements I described assume that the lines L1 and L2 are created at the right locations. The steps of creating L1 and L2 is a different task, which you should define. 
    As I see your images have different location of the drop, so you have to figure out how to put the lines with given vertical offset to the right places. You may either try to align all images, so the base line is always the same and then write a macro that draws L1 and L2 at the right Y positions (you can use Snap feature drawing lines, Auto Adjust Template, to snap the line to drop edges) or just draw L1 and L2 manually on every image.

    Yuri

  • Hello @YuriG and @mbatchelor

    Based on Abrar's uploaded image, we need to select 4 points to draw the lines L1 and L2. What we can do is, we can fix two values of 'Y' for writing the macro and select 4 values of 'X' based on the maximum intensity for that frame. Later, we can draw a derived line from the starting points of L1 and L2, followed by drawing a derived angle. We can run a loop for all the frames using this same code. But I am unable to find the syntax to define the X coordinate of the point as a variable. Can you please help?

    Thanks in advance!

    Viraj

  • Hi Viraj,

    The approach I described with Relative measurements and Snap features assumed that the Y positions of L1 and L2 lines are always the same, only the end-points (X coordinates) are adjusted on every image. 
    You may try to align all your images (Align tool) and put them into a sequence where all the images will have the same Y position of the base line (corresponded to Y coordinate of L1), then you just load the same template that includes L1, L2 lines and all derived angles on every frame and execute Auto-Adjust Template.

    Another way, more complicated, which you asked, is to create a macro that will generate all the lines from user-defined XY positions. In that case you will need to record a macro that creates all the lines and derived features (from the beginning, starting from L1) and then replace recorded coordinates of lines by variables. From something like this:

            With Measure.MeasurementsCommands.Add(CreateMeasurements)
                .MeasurementType = McMeasurements.enumMMSTypes.mmtsLine
                .Points = New System.Collections.Generic.List(Of System.Drawing.PointF)
                .Points.Add(New System.Drawing.PointF(332.2533F,965.4481F))
                .Points.Add(New System.Drawing.PointF(876.7312F,961.9689F))
                .FeatureName = "L1"
                .SnapFeature = True
                .SnapOptions.SnapToImage = McMMOptions.mcmmSnapMethods.mcmmSnapWholeLine
                .SnapOptions.SnapRadius = 16
                .SnapOptions.CaliperMatchLength = 7
                .SnapOptions.CaliperWidth = 3
                .Run(doc1, meas1)
            End With
    
            With Measure.MeasurementsCommands.AutoAdjust(CreateMeasurements)
                .Run(doc1)
            End With
     
    to this:

            'define external variable
            Dim pStart1 As System.Drawing.PointF
            Dim pEnd1 As System.Drawing.PointF
    
            '...
    
            With Measure.MeasurementsCommands.Add(CreateMeasurements)
                .MeasurementType = McMeasurements.enumMMSTypes.mmtsLine
                .Points = New System.Collections.Generic.List(Of System.Drawing.PointF)
                .Points.Add(New System.Drawing.PointF(pStart1.x,pStart1.y))
                .Points.Add(New System.Drawing.PointF(pEnd1.x,pEnd1.Y))
                .FeatureName = "L1"
                .SnapFeature = True
                .SnapOptions.SnapToImage = McMMOptions.mcmmSnapMethods.mcmmSnapWholeLine
                .SnapOptions.SnapRadius = 16
                .SnapOptions.CaliperMatchLength = 7
                .SnapOptions.CaliperWidth = 3
                .Run(doc1, meas1)
            End With
    
            With Measure.MeasurementsCommands.AutoAdjust(CreateMeasurements)
                .Run(doc1)
            End With
    

    and control coordinate variables (pStart1, pEnd1,...) by your macro.

    Yuri
  • YuriG said:
    Hi Viraj,

    The approach I described with Relative measurements and Snap features assumed that the Y positions of L1 and L2 lines are always the same, only the end-points (X coordinates) are adjusted on every image. 
    You may try to align all your images (Align tool) and put them into a sequence where all the images will have the same Y position of the base line (corresponded to Y coordinate of L1), then you just load the same template that includes L1, L2 lines and all derived angles on every frame and execute Auto-Adjust Template.

    Another way, more complicated, which you asked, is to create a macro that will generate all the lines from user-defined XY positions. In that case you will need to record a macro that creates all the lines and derived features (from the beginning, starting from L1) and then replace recorded coordinates of lines by variables. From something like this:

            With Measure.MeasurementsCommands.Add(CreateMeasurements)
                .MeasurementType = McMeasurements.enumMMSTypes.mmtsLine
                .Points = New System.Collections.Generic.List(Of System.Drawing.PointF)
                .Points.Add(New System.Drawing.PointF(332.2533F,965.4481F))
                .Points.Add(New System.Drawing.PointF(876.7312F,961.9689F))
                .FeatureName = "L1"
                .SnapFeature = True
                .SnapOptions.SnapToImage = McMMOptions.mcmmSnapMethods.mcmmSnapWholeLine
                .SnapOptions.SnapRadius = 16
                .SnapOptions.CaliperMatchLength = 7
                .SnapOptions.CaliperWidth = 3
                .Run(doc1, meas1)
            End With
    
            With Measure.MeasurementsCommands.AutoAdjust(CreateMeasurements)
                .Run(doc1)
            End With
     
    to this:

            'define external variable
            Dim pStart1 As System.Drawing.PointF
            Dim pEnd1 As System.Drawing.PointF
    
            '...
    
            With Measure.MeasurementsCommands.Add(CreateMeasurements)
                .MeasurementType = McMeasurements.enumMMSTypes.mmtsLine
                .Points = New System.Collections.Generic.List(Of System.Drawing.PointF)
                .Points.Add(New System.Drawing.PointF(pStart1.x,pStart1.y))
                .Points.Add(New System.Drawing.PointF(pEnd1.x,pEnd1.Y))
                .FeatureName = "L1"
                .SnapFeature = True
                .SnapOptions.SnapToImage = McMMOptions.mcmmSnapMethods.mcmmSnapWholeLine
                .SnapOptions.SnapRadius = 16
                .SnapOptions.CaliperMatchLength = 7
                .SnapOptions.CaliperWidth = 3
                .Run(doc1, meas1)
            End With
    
            With Measure.MeasurementsCommands.AutoAdjust(CreateMeasurements)
                .Run(doc1)
            End With
    

    and control coordinate variables (pStart1, pEnd1,...) by your macro.

    Yuri
    Hello @YuriG

    In reference to the first solution which you mention, my images are already aligned. Therefore, the Y coordinates of the point is fixed. Can you please explain me how to define a variable X coordinate using Relative measurements and Snap features and how to execute Auto-Adjust Template

    Thank you very much
  • Hi Viraj,

    I will explain how to use templates doing you measurements.

    1. Create template measurements that include L1, L2 and all derived features and angles.
           a) Switch on Template mode option in the Snap drop-down:

           b) Activate the Snap mode (Adjust line length) and draw L1 and L2 lines on the correct Y position, but make them wider then the widest object on any frame. Note, that they will not "Snap" to edges when you release the mouse, because the Template mode is active.

           c) Add all derived measurements based on L1, L2 (they will also look incorrect, but that's not important for now).

    2. Save the template to IQM file using the Save button in the measurements Data Table. This template will be used on all frames.
    3. Select the frame you need, cleanup all the measurements and load the IQM file (saved on step 2).
    4. Click the Auto-Adjust Template menu item, the lines will be "snapped" to the object edges and all the measurements adjusted accordingly:

    6. Collect measurement values, including AB6 angle to to Data Collector.
    5. Repeat steps 3 to 6 for all frames, it will give you the angle measurements for all the phases. These steps can be automated by a macro, every step is macro recordable (just activate macro recording and do the steps).

    Yuri
  • 2017-05-26-155842

    Viraj --

    Please see the following for a suggested method to handle your challenge.

    The measurements generated by this procedure could be used to get the data that you have shown is of interest.

    This type of procedure could be used on ROIS across an image or on IMAGES in a SEQUENCE.

    The spacing of the MASK LINES could be reduced to make this more accurate and the procedure could also be automated.

    I hope this information is helpful.

    -- Matt

    *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
    ORIGINAL IMAGE (created from a MOVIE of an OIL DROP)



    ORIGINAL IMAGE + MASK with HORIZONTAL LINES + MASK with VERTICAL LINES


    H MASK MINUS ORIGINAL IMAGE and V MASK MINUS ORIGINAL IMAGE


    ROI on HMASK over OIL DROP + BRIGHT THRESHOLD + COUNT


    ROI on VMASK over OIL DROP + BRIGHT THRESHOLD + COUNT


  • YuriG said:
    Hi Viraj,

    I will explain how to use templates doing you measurements.

    1. Create template measurements that include L1, L2 and all derived features and angles.
           a) Switch on Template mode option in the Snap drop-down:

           b) Activate the Snap mode (Adjust line length) and draw L1 and L2 lines on the correct Y position, but make them wider then the widest object on any frame. Note, that they will not "Snap" to edges when you release the mouse, because the Template mode is active.

           c) Add all derived measurements based on L1, L2 (they will also look incorrect, but that's not important for now).

    2. Save the template to IQM file using the Save button in the measurements Data Table. This template will be used on all frames.
    3. Select the frame you need, cleanup all the measurements and load the IQM file (saved on step 2).
    4. Click the Auto-Adjust Template menu item, the lines will be "snapped" to the object edges and all the measurements adjusted accordingly:

    6. Collect measurement values, including AB6 angle to to Data Collector.
    5. Repeat steps 3 to 6 for all frames, it will give you the angle measurements for all the phases. These steps can be automated by a macro, every step is macro recordable (just activate macro recording and do the steps).

    Yuri
    Hello @YuriG

    I used your method and I think I am getting the results as required. All thanks to you!

    I tried to automate the process using a Macro which I think works fine. The thing is I have to Click on the Run icon for every frame:


    Is there anyway to write a macro instead of clicking on the 'Run' icon for every frame as I have more than 54000 frames, all in all.

    Thank you again!

    Regards
    Viraj
  • Hi Viraj,

    You can use a macro that loops through all frames of the image and calls the macro on every frame, (the macro should place measurements on the image, execute AutoAdjust and export measurements to Data Collector).

    Here is the example of such macro:

        Public Sub MeasureAllFrames
            If ThisApplication.ActiveImage Is Nothing Then Exit Sub
            'go through all frames of the image
            For i As Integer=0 To ThisApplication.ActiveImage.FrameCount-1
                'activate frame
                ThisApplication.ActiveImage.ActiveFrameIndex=i
    
                'call your macro that measures active image
                'Call MyMacro
    
            Next
        End Sub

    Yuri
  • Hello @YuriG 

    I tried copy-pasting your code in my script but I get the following error:


    Can you tell me where exactly to put this code in my Macro which was created by following the procedure you mentioned in your previous comment!

    Thanks and Regards
    Viraj

  • Viraj,

    It's hard to tell without seeing what you have there. Be sure that you don't miss anything.
    Also, this is just a sample macro, you should create your own macro that would call your functions.

    Yuri
  • YuriG said:
    Viraj,

    It's hard to tell without seeing what you have there. Be sure that you don't miss anything.
    Also, this is just a sample macro, you should create your own macro that would call your functions.

    Yuri
    Imports MediaCy.Viewers.Image
    Imports MediaCy.Addins.Measurements
    Public Module Module3000
    
    
        Public Function NewMacro3000() As SimpleScript
            NewMacro3000 = New SimpleScript
            Dim window1, doc1
    
            With Application.WindowCommands.Active(NewMacro3000)
                .Run(window1)
            End With
    
            With View.ImageViewCommands.Options(NewMacro3000)
                .ActiveFrameIndex = 1
                .Run(window1)
            End With
    
            With Application.RibbonCommands.SelectRibbonTab(NewMacro3000)
                .TabName = "Measure"
                .Run()
            End With
    
            With Application.DocumentCommands.Active(NewMacro3000)
                .Run(doc1)
            End With
    
            With Measure.MeasurementsCommands.DeleteAll(NewMacro3000)
                .Run(doc1)
            End With
    
            With Measure.MeasurementsCommands.Open(NewMacro3000)
                .FileName = "D:\xyz.iqm"
                .FilterIndex = 1
                .Run(doc1)
            End With
    
            With Measure.MeasurementsCommands.AutoAdjust(NewMacro3000)
                .Run(doc1)
            End With
    
            With Measure.Measurements.TableCommands.SendToExcel(NewMacro3000)
                .UseStatistics = False
                .Run(doc1)
            End With
    
        End Function
    
    End Module
    
    
    The above is my Macro. Now is it possible to find a solution?
  • Where is the line where you have error?
  • edited May 2017
    YuriG said:
    Where is the line where you have error?
    H@YuriG,

    This is my original macro. I need to run this for all the frames instead of one using the script which you told.

    Thanks 
    Viraj
  • Viraj,

    Just paste my macro below your's and call NewMacro3000 in the loop.

    Yuri
  • Hello @YuriG

    I pasted the following script in between the last two lines, 'End Function' and 'End Module' of my Macro:

            Public Sub MeasureAllFrames
            If ThisApplication.ActiveImage Is Nothing Then Exit Sub
            'go through all frames of the image
            For i As Integer=0 To ThisApplication.ActiveImage.FrameCount-1
                'activate frame
                ThisApplication.ActiveImage.ActiveFrameIndex=i
    
                'call your macro that measures active image
                Call NewMacro3000
    
            Next
        End Sub
    
    
    Still the Macro runs for Frame number 2 only.
    
    
    Thanks 
    Viraj
  • Your macro itself contains a command that sets active frame.
    With View.ImageViewCommands.Options(NewMacro3000)
                .ActiveFrameIndex = 1
                .Run(window1)
            End With
    

    Remove this command from your macro.

    Yuri
  • Hello @YuriG

    Still it is capturing for only one frame. I am really stuck!

    Thanks
    Viraj
  • Hi @YuriG

    Thank you very much. It is working I think. I will let you know about the progress if the results are correct. Thanks again.

    Best Regards
    Viraj
Sign In or Register to comment.