Jefferson Bettini
Jefferson Bettini

Reputation: 21

How can I get information from circular ROI using dm script?

After making a circular ROI in an image, how can I get the information (average, standar deviation, variance) from that image region using script?

Can I link the position in the ciruclar ROI with original image?

Upvotes: 1

Views: 382

Answers (1)

BmyGuest
BmyGuest

Reputation: 2949

This task is unfortunately not as straight forward and easy as one would hope.

While scripting supports a convenient shortcut to restrict image operations to rectangular ROIs ( using the img[] notation ), there is nothing like that for irregular ROIs.

In such a case, one has to manually create a binary mask of a ROI and perform the wanted operations manually. The example script at the bottom of this post shows how the average value of an irregular ROI may be computed.

  • CreateImageWithROI() Creates a test image with two ROIs on it
  • GetFirstIrregularROIOfImage() just returns the first found, irregular ROI of an image
  • GetROIMean() is the actual example

The command ROIAddToMask() is used to create the mask. Note, that there is also a similar command which would perform the action with all ROIs of an image display at once: ImageDisplayAccumulateROIsToMask()

Irregular masking

So far, so good.

However, it turns out that the newly introduced Circular ROIs do not yet support the mask-creation commands correctly (Tested with GMS 3.1).

Instead, they always use the bounding rectangle of the ROI:

Creating mask from ROIs

It is therefore necessary to go even one step back and read the ROI's coordinates to create a mask from it manually. Get the ROI's bounding-box and create a mask using an icol and irow expression for an ellipse. In the example below:

  • GetFirstOvalROIOfImage() just returns the first found, oval ROI of an image
  • MyAddOvalROIToMask() is the manual mask creation for oval ROIs

Final example


Example code:

image CreateImageWithROI()
{
    // Create and show image
    number sx = 256, sy = 256
    image img := RealImage( "Image", 4, sx, sy )
    img = sin( 0.1 * iradius ) * cos( 7 * itheta )
    img.ShowImage()
    
    // Create an irregular, closed ROI
    ROI myIrRoi = NewROI()
    myIrRoi.ROIAddVertex( 0.3 * sx, 0.1 * sy )
    myIrRoi.ROIAddVertex( 0.7 * sx, 0.2 * sy )
    myIrRoi.ROIAddVertex( 0.5 * sx, 0.6 * sy )
    myIrRoi.ROIAddVertex( 0.1 * sx, 0.8 * sy )
    myIrRoi.ROISetIsClosed(1)
    myIRRoi.ROISetVolatile(0)
    
    // Create an oval ROI
    ROI myOvalROI = NewROI()
    myOvalROI.ROISetOval( 0.7 * sy, 0.7 * sx, 0.9 * sy, 0.8 * sx )
    myOvalROI.ROISetVolatile(0)
    
    // AddROIs
    imageDisplay disp = img.ImageGetImageDisplay( 0 )
    disp.ImageDisplayAddROI( myIRRoi )
    disp.ImageDisplayAddROI( myOvalROI )
    
    return img
}

ROI GetFirstIrregularROIOfImage( image img )
{
    if ( img.ImageIsValid() ) 
    {
        if ( 0 != img.ImageCountImageDisplays() ) 
        {
            imageDisplay disp = img.ImageGetImageDisplay( 0 )
            number nRois = disp.ImageDisplayCountROIs()
            for ( number i = 0; i < nRois; i++ )
            {
                ROI testROI = disp.ImageDisplayGetRoi( i )
                number isIrregularClosed = 1
                isIrregularClosed *= testROI.ROIIsClosed();
                isIrregularClosed *= !testROI.ROIIsOval();
                isIrregularClosed *= !testROI.ROIIsRectangle();
                isIrregularClosed *= ( 2 < testROI.ROICountVertices());
                if ( isIrregularClosed )
                    return testROI
            }
        }
    }   
    Throw( "No irregular ROI found" )
}

ROI GetFirstOvalROIOfImage( image img )
{
    if ( img.ImageIsValid() ) 
    {
        if ( 0 != img.ImageCountImageDisplays() ) 
        {
            imageDisplay disp = img.ImageGetImageDisplay( 0 )
            number nRois = disp.ImageDisplayCountROIs()
            for ( number i = 0; i < nRois; i++ )
            {
                ROI testROI = disp.ImageDisplayGetRoi( i )
                if ( testROI.ROIIsOval() )
                    return testROI
            }
        }
    }   
    Throw( "No oval ROI found" )
}

void MyAddOvalROIToMask( image img, ROI ovalROI )
{
    number top, left, bottom, right
    ovalROI.ROIGetOval( top, left, bottom, right )
    number sx = ( right - left )
    number sy = ( bottom - top )
    number cx = sx/2    // Used as both center x coordiante and x radius!
    number cy = sy/2    // Used as both center y coordiante and y radius!
    
    // Create mask of just the rect area
    image maskCut := RealImage( "", 4, sx, sy )
    maskCut = ( ((cx-icol)/cx)**2 + ((cy-irow)/cy)**2 <= 1 ) ? 1 : 0
    
    // Apply mask to image
    img[top, left, bottom, right] = maskCut
}

number GetROIMean( image img, ROI theRoi )
{
    if ( !img.ImageIsValid() ) Throw( "Invalid image in GetROIMean()" )
    if ( !theRoi.ROIIsValid() ) Throw( "Invalid roi in GetROIMean()" )
    
    // Create a binary mask of "img" size using the ROI's coordinates
    image mask = img * 0;   // image of same size as "img" with 0 values
    number sx, sy
    img.GetSize( sx, sy )
    
    // Oval ROIs are not supported by the command correctly
    // Hence check and compute mask manually..
    if ( theROI.ROIIsOval() )
        MyAddOvalROIToMask( mask, theROI )
    else
        theROI.ROIAddToMask( mask, 0, 0, sx, sy )
    
    if ( TwoButtonDialog( "Show mask?", "Yes", "No" ) )
        mask.ShowImage()
    
    // Do meanValue as sums of masked points
    number maskedPoints = sum( mask )
    number maskedSum
    if ( 0 < maskedPoints ) 
        maskedSum = sum( mask * img ) / maskedPoints 
    else
        maskedSum = sum( img )
    
    return maskedSum 
}

Result( "\n Testing irregular and oval ROIs on image.\n" )
image testImg := CreateImageWithROI()
ROI   testROIir  = GetFirstIrregularROIOfImage( testImg )
number ROIirMean = GetROIMean( testImg, testROIir )
Result( "\n Mean value (irregular ROI): "+ ROIirMean )

ROI   testROIoval  = GetFirstOvalROIOfImage( testImg )
number ROIovalMean = GetROIMean( testImg, testROIoval )
Result( "\n Mean value (oval ROI)     : "+ ROIovalMean )

Upvotes: 0

Related Questions