捕获 "Pixel outside the boundaries" 异常?

Catching the "Pixel outside the boundaries" exception?

我有一张原子周期性排列的图像。

我正在尝试编写一个脚本,通过在左上角的原子上分配一个 ROI 来计算第一列中排列的原子数,然后让脚本从 scan从左到右(逐列)。我的想法是,通过使用从左到右 扫描 的 ROI,当它 命中 超出边界的像素时(这意味着,它超出图像),脚本 returns 一行中的原子数,而不是给出错误输出说 "A pixel outside the boundaries of the image has been referenced".

有什么办法可以把上面的案例写成脚本吗?

谢谢。

您可以捕获脚本代码抛出的任何异常,使用

自行处理
Try(){ }
Catch{ break; } 

构建。但是,这不是您问题的最佳解决方案。如果您 知道 图像的大小,那么您真的应该使用该知识来防止访问债券之外的数据。使用 Try{}Catch{} 最好留给可能发生 "anything unexpected" 的情况,而您仍然想处理该问题。

这是您问题的代码示例。

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] ) );
        }

回答采纳答案评论中的问题: 您可以查询图像上的任何 ROI/Selection 并使用此信息来限制迭代。 以下示例显示了这一点。它还显示了如何正确使用 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 )
    }