我想允许用户使用固定轴比率更改椭圆形ROI或注释的直径(对于圆形,比率为1:1)。此外,椭圆形应仅在中心周围打开,但不允许侧向移动。
目前,我有一个脚本可以读取ROI,并在用户偏离其中心的形状或位置时进行纠正。然而,它看起来相当烦人和令人困惑,例如当圆圈变为椭圆形然后弹回圆圈时。我希望有一些命令允许例如调整大小(选择固定轴比率)但限制(横向)移动。
非常欢迎任何建议。
答案 0 :(得分:1)
此问题是more general question here的具体应用。
诀窍是每当ROI的大小发生变化时采取行动,然后将其替换为适当的限制。这是通过附加“监听器”方法来完成的 在ROI发生变化时调用。 有两种方法可以为投资回报率做到这一点:
// 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" )
// 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)