1

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

我可以将循环 ROI 中的位置与原始图像联系起来吗?

4

1 回答 1

1

不幸的是,这项任务并不像人们希望的那样直接和容易。

虽然脚本支持将图像操作限制为矩形 ROI 的便捷快捷方式(使用img[]符号),但对于不规则的 ROI 则没有类似的东西。

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

  • CreateImageWithROI() 创建一个带有两个 ROI 的测试图像
  • GetFirstIrregularROIOfImage()只返回第一个找到的、不规则的图像 ROI
  • GetROIMean()是实际的例子

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

不规则掩蔽

到现在为止还挺好。

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

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

从 ROI 创建掩码

因此,甚至有必要后退一步并读取 ROI 的坐标以手动创建蒙版。获取 ROI 的边界框并使用椭圆的icoland表达式创建蒙版。irow在下面的示例中:

  • GetFirstOvalROIOfImage()只返回图像的第一个找到的椭圆形 ROI
  • MyAddOvalROIToMask()是椭圆形 ​​ROI 的手动蒙版创建

最后一个例子


示例代码:

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 )
于 2016-10-28T07:42:05.570 回答