如何使用dm脚本从循环ROI获取信息?

时间:2016-10-27 15:47:28

标签: image-processing mask roi dm-script

在图像中制作圆形ROI后,如何使用脚本从该图像区域获取信息(平均值,标准偏差,方差)?

我可以将ciruclar ROI中的位置与原始图像相关联吗?

1 个答案:

答案 0 :(得分:1)

遗憾的是,这项任务不像人们希望的那样简单明了。

虽然脚本支持一种方便的快捷方式,可以将图像操作限制为矩形ROI(使用img[]表示法),但对于不规则的ROI,没有类似的内容。

在这种情况下,必须手动创建ROI的二进制掩码并手动执行所需操作。本文底部的示例脚本显示了如何计算不规则ROI的平均值。

  • CreateImageWithROI()创建一个包含两个投资回报率的测试图片
  • GetFirstIrregularROIOfImage()只返回图片的第一个找到的,不规则的投资回报率
  • GetROIMean()是实际的例子

命令ROIAddToMask()用于创建掩码。请注意,还有一个类似的命令可以同时执行图像显示的所有 ROI的操作:ImageDisplayAccumulateROIsToMask()

Irregular masking

到目前为止,这么好。

  

然而,事实证明新引入的循环ROI 尚未正确支持掩码创建命令(使用GMS 3.1测试)。

相反,他们总是使用ROI的边界矩形:

Creating mask from ROIs

因此有必要甚至退一步并阅读ROI的坐标以手动创建遮罩。获取投资回报率的边界框,并使用icolirow表达式为椭圆创建蒙版。在下面的示例中:

  • GetFirstOvalROIOfImage()只返回图像的第一个找到的椭圆形ROI
  • MyAddOvalROIToMask()是椭圆形投资回报率的手动模板创建

Final example

示例代码:

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 )