【发布时间】:2017-05-29 07:51:40
【问题描述】:
我有一张带有周期性排列的原子的图像。
我正在尝试编写一个脚本,通过在左上角原子上分配一个 ROI 来计算第一列中排列了多少原子,然后让脚本从左到右 扫描(列按列)。我的想法是,通过使用从左到右扫描的ROI,当它命中像素超出边界(这意味着,它超出图像),该脚本返回一行中的原子数,而不是给出错误输出“已引用图像边界外的像素”。
有没有什么办法可以让上面的案例写成脚本?
谢谢。
【问题讨论】:
我有一张带有周期性排列的原子的图像。
我正在尝试编写一个脚本,通过在左上角原子上分配一个 ROI 来计算第一列中排列了多少原子,然后让脚本从左到右 扫描(列按列)。我的想法是,通过使用从左到右扫描的ROI,当它命中像素超出边界(这意味着,它超出图像),该脚本返回一行中的原子数,而不是给出错误输出“已引用图像边界外的像素”。
有没有什么办法可以让上面的案例写成脚本?
谢谢。
【问题讨论】:
您可以捕获脚本代码抛出的任何异常,并使用
自行处理Try(){ }
Catch{ break; }
构造。但是,这不是解决您的问题的最佳解决方案。如果您知道图像的大小,那么您确实应该使用该知识来防止访问绑定之外的数据。使用Try{}Catch{} 最好留给那些“任何意外” 可能发生的情况,并且您仍然想处理问题。
这是您问题的代码示例。
number boxSize = 3
number sx = 10
number sy = 10
image img := realImage( "Test", 4, sx, sy )
img = random()
// Output "sum" over scanned ROI area
// Variant 1: Just scan -- Hits an exception, as you're moving out of range
/*
for( number j=0;j<sy;j++)
for( number i=0;i<sx;i++)
{
Result("\n ScanPos: " + i +" / " + j )
Result("\t SUM: "+ sum( img[j,i,j+boxSize,i+boxSize] ) );
}
*/
// Variant 2: As above, but catch exception to just continue
for( number j=0;j<sy;j++)
for( number i=0;i<sx;i++)
{
Result("\n ScanPos: " + i +" / " + j )
Try
{
Result( "\t SUM: "+ sum( img[j,i,j+boxSize,i+boxSize] ) );
}
catch
{
Result( "\t ROI OUT OF RANGE" )
break; // Needed in scripting, or the exception is re-thrown
}
}
// Variant 3: (Better) Avoid hitting the exception by using the knowlede of data size
for( number j=0;j<sy-boxSize;j++)
for( number i=0;i<sx-boxSize;i++)
{
Result("\n ScanPos: " + i +" / " + j )
Result("\t SUM: "+ sum( img[j,i,j+boxSize,i+boxSize] ) );
}
【讨论】:
要回答已接受答案的 cmets 中的问题: 您可以查询图像上的任何 ROI/选择,并使用此信息来限制迭代。 以下示例显示了这一点。它还显示了如何正确使用 ROI 对象,以获取选择以及添加新的 ROI。更多信息可在 F1 帮助中找到:
脚本采用最前面的图像,上面只有一个选择。 然后它从左上角(以给定的步长)迭代选择并输出区域的总和值。最后,您可以选择将使用过的区域绘制为新的 ROI。
ClearResults()
// 1) Get image and image size
image img := GetFrontImage()
number sx = img.ImageGetDimensionSize(0)
number sy = img.ImageGetDimensionSize(0)
Result( "Image size: "+ sx + "x"+ sy+"\n")
// 2) Get the size of the user-drawn selection (ROI)
// 2a)
// If you are only dealing with the simple, user-drawn rectangle selections
// you can use the simplified code below instead.
number t, l, b, r
img.GetSelection(t,l,b,r)
Result( "Marker coordinates (simple): ["+t+","+l+","+b+","+r+"]\n" )
// 2b)
// Or you can use the "full" commands to catch other situations.
// The following lines check ROIs in a more general way.
// Not strictly needed, but to get you started if you want
// to use the commands outlined in F1 help section
// "Scripting > Objects > Document Object Model > ROI Object"
imageDisplay disp = img.ImageGetImageDisplay(0)
if( 0 == disp.ImageDisplayCountROIs() )
Throw( "No ROI on the image." )
if( 1 < disp.ImageDisplayCountROIs() )
Throw( "More than one ROI on the image." )
ROI theMarker = disp.ImageDisplayGetROI(0) // First (and only) ROI
if ( !theMarker.ROIIsRectangle() )
Throw( "ROI not a rectangle selection." )
if ( !theMarker.ROIGetVolatile() )
Throw( "ROI not voltaile." ) // Voltile = ROI disappears when another is drawn. Dashed outline.
number top, left, bottom, right
theMarker.ROIGetRectangle( top, left, bottom, right )
Result( "Marker coordinates (ROI commands): ["+top+","+left+","+bottom+","+right+"]\n" )
// 3) Iterate within bounds
number roiWidth = right - left
number roiHeight = bottom - top
number roiXStep = 100 // We shift the ROI in bigger steps
number roiYStep = 100 // We shift the ROI in bigger steps
if ( !GetNumber( "The ROI is " + roiWidth + "pixels wide. Shift in X?", roiWidth, roiXStep ) )
exit(0)
if ( !GetNumber( "The ROI is " + roiHeight + "pixels heigh. Shift in Y?", roiHeight, roiYStep ) )
exit(0)
for ( number j = 0; j<sy-roiHeight; j+=roiYStep )
for ( number i = 0; i<sx-roiWidth; i+=roiXStep )
{
Result( "Sum at "+i+"/"+j+": " + sum( img[j,i,j+roiHeight,i+roiWidth] ) + "\n" )
}
// 4) If you want you can "show" the used positions.
if ( !TwoButtonDialog("Draw ROIs?","Yes","No") )
exit(0)
for ( number j = 0; j<sy-roiHeight; j+=roiYStep )
for ( number i = 0; i<sx-roiHeight; i+=roiXStep )
{
roi markerROI = NewRoi()
markerROI.ROISetRectangle( j, i, j+roiHeight, i+roiWidth )
markerROI.ROISetVolatile(0)
markerROI.ROISetColor(0,0.4,0.4)
markerROI.ROISetMoveable(0)
markerROI.ROISetLabel( ""+i+"/"+j ) // Start with "" to ensure the parameter is recognized as string
disp.ImageDisplayAddRoi( markerROI )
}
【讨论】: