限制ROI流动的方法有哪些

时间:2018-04-26 16:14:48

标签: dm-script

我想允许用户使用固定轴比率更改椭圆形ROI或注释的直径(对于圆形,比率为1:1)。此外,椭圆形应仅在中心周围打开,但不允许侧向移动。

目前,我有一个脚本可以读取ROI,并在用户偏离其中心的形状或位置时进行纠正。然而,它看起来相当烦人和令人困惑,例如当圆圈变为椭圆形然后弹回圆圈时。我希望有一些命令允许例如调整大小(选择固定轴比率)但限制(横向)移动。

非常欢迎任何建议。

2 个答案:

答案 0 :(得分:1)

此问题是more general question here的具体应用。

诀窍是每当ROI的大小发生变化时采取行动,然后将其替换为适当的限制。这是通过附加“监听器”方法来完成的 在ROI发生变化时调用。 有两种方法可以为投资回报率做到这一点:

1)将监听器附加到ROI所在的 imageDisplay

// EXAMPLE using ImageDisplay listener
// This will handle ALL ROIs on the display, so one would like to 
// "filter" specific ROIs. f.e. by using the ROI property "Name".
class CCircleRestrict
{
    number x0,y0
    object Init( object self, number cx, number cy ){ x0 = cx; y0 = cy; return self; }
    void OnRestrict( object self, number e_fl, ImageDisplay idisp, number r_fl, number r_fl2, ROI theROI )
    {
        if ( theROI.ROIGetName() != "special" ) return; // Skip, if it isn't "our" ROI
        if ( !theROI.ROIIsOval() ) return;  // Skip, if it isn't an oval ROI
        // get size of ROI ( as currently dragged by user )
        number t, l, b, r
        theROI.ROIGetOval( t, l, b, r )
        number radius = max( b - t, r - l ) / 2
        // Re-Set the ROI centered on x0/y0 with the new radius
        theROI.ROISetOval( y0 - radius, x0 - radius, y0 + radius, x0 + radius )
    }
}

// Main script "attaches" the display listener to 
void main()
{
    // Create and show test image 
    number size = 512
    number r1 = 20
    number r2 = 20
    number off = 100
    image test := realImage( "Test", 4, size, size )
    test.ShowImage()
    imageDisplay disp = test.ImageGetImageDisplay(0)
    // Add two oval ROIs, name one of them "special" for identification
    ROI specialROI = NewROI()
    specialROI.ROISetName( "special" )
    specialROI.ROISetOval( size/2 - r1, size/2 - r1, size/2 + r1, size/2 + r1 )
    specialROI.ROISetVolatile(0)
    specialROI.ROISetColor(0.1,0.9,0.1)
    disp.ImageDisplayAddROI(specialROI)
    ROI otherROI = NewROI()
    otherROI.ROISetOval( off + size/2 - r2, off +  size/2 - r2, off +  size/2 + r2, off + size/2 + r2 )
    otherROI.ROISetVolatile(0)
    disp.ImageDisplayAddROI(otherROI)
    // Create listener object and attach listener to display
    object dispListener = Alloc(CCircleRestrict).Init( size/2, size/2 )
    disp.ImageDisplayAddEventListener( dispListener, "roi_property_changed:OnRestrict" )
}

EGUPerformActionWithAllShownImages( "Delete" )
main()
EGUPerformActionWithAllShownImages( "Arrange" )

2)将侦听器附加到ROI对象本身

// EXAMPLE using ROI listener
// This will handle changes a specific ROI, regardless of the display(s) it is on
class CCircleRestrict
{
    number x0,y0
    object Init( object self, number cx, number cy ){ x0 = cx; y0 = cy; return self; }
    void OnRestrict( object self, ROI theROI )
    {
        if ( !theROI.ROIIsOval() ) return;  // Skip, if it isn't an oval ROI
        // get size of ROI ( as currently dragged by user )
        number t, l, b, r
        theROI.ROIGetOval( t, l, b, r )
        number radius = max( b - t, r - l ) / 2
        // Re-Set the ROI centered on x0/y0 with the new radius
        theROI.ROISetOval( y0 - radius, x0 - radius, y0 + radius, x0 + radius )
    }
}

// Main script "attaches" the listener to the ROI
void main()
{
    // Create and show test image 
    number size = 512
    number r1 = 20
    number r2 = 20
    number off = 100
    image test := realImage( "Test", 4, size, size )
    test.ShowImage()
    imageDisplay disp = test.ImageGetImageDisplay(0)
    // Add two oval ROIs
    ROI specialROI = NewROI()
    specialROI.ROISetOval( size/2 - r1, size/2 - r1, size/2 + r1, size/2 + r1 )
    specialROI.ROISetVolatile(0)
    specialROI.ROISetColor(0.1,0.9,0.1)
    disp.ImageDisplayAddROI(specialROI)
    ROI otherROI = NewROI()
    otherROI.ROISetOval( off + size/2 - r2, off +  size/2 - r2, off +  size/2 + r2, off + size/2 + r2 )
    otherROI.ROISetVolatile(0)
    disp.ImageDisplayAddROI(otherROI)
    // Create listener object and attach listener to specific ROI
    object roiListener = Alloc(CCircleRestrict).Init( size/2, size/2 )
    ConnectObject( specialROI.ROIGetID(), "changed", "EventID_Name", roiListener, "OnRestrict" )
}

EGUPerformActionWithAllShownImages( "Delete" )
main()
EGUPerformActionWithAllShownImages( "Arrange" )

上述两个例子都将椭圆形ROI限制为圆形,但是可以直接改变椭圆形ROI,从而实现椭圆形的特定纵横比。

  

然而,重要的是要考虑“新设定”并进行调整   ROI本身将再次触发听众。必须确保这一点   没有以这种方式创建无限循环,即触发   第二次的方法不得导致新的限制。

具有1:2宽高比的椭圆形ROI的简单示例将使用限制方法,如:

void OnRestrict( object self, ROI theROI )
{
    ar = 2
    if ( !theROI.ROIIsOval() ) return;  // Skip, if it isn't an oval ROI
    // get size of ROI ( as currently dragged by user )
    number t, l, b, r
    theROI.ROIGetOval( t, l, b, r )
    number w = r - l
    number h = b - t
    number newW = max( W, AR*H )
    number newH = newW/AR
    // Re-Set the ROI centered on x0/y0 with the new radius
    theROI.ROISetOval( y0 - newH/2, x0 - newW/2, y0 + newH/2, x0 + newW/2 )
}

答案 1 :(得分:1)

上面的答案指定了要求的限制类型,但为了完整起见,还应该提到有一些ROI 属性在这种情况下很有用。

来自F1帮助文档:

F1 help

但是,可移动属性取代可调整大小的属性,即如果您无法移动,则无法调整大小。