Reputation: 21
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
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 itGetFirstIrregularROIOfImage()
just returns the first found, irregular ROI of an imageGetROIMean()
is the actual exampleThe 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()
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:
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 imageMyAddOvalROIToMask()
is the manual mask creation for oval ROIsimage 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