Exception 抓住",;边界外的像素“;例外?

Exception 抓住",;边界外的像素“;例外?,exception,pixel,dm-script,Exception,Pixel,Dm Script,我有一张原子周期性排列的图像 我正试图编写一个脚本,通过在左上角的atom上指定一个ROI来计算第一列中排列了多少个原子,然后让脚本从左到右(逐列)扫描。我的想法是,通过使用从左到右扫描的ROI,当它击中超出边界的像素时(也就是说,它超出了图像),脚本返回一行中的原子数,而不是给出错误输出说“图像边界外的像素已被引用” 有没有办法让上面的例子可以用脚本编写 谢谢。您可以捕获脚本代码引发的任何异常,并使用 Try(){ } Catch{ break; } 构造。然而,这并不是解决你问题的最好办

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

我正试图编写一个脚本,通过在左上角的atom上指定一个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] ) );
        }
number-boxSize=3
数字sx=10
数字sy=10
图像img:=真实图像(“测试”,4,sx,sy)
img=random()
//在扫描的ROI区域上输出“总和”
//变体1:只需扫描——当您移出范围时,会遇到异常
/*

对于(数字j=0;j)回答接受答案评论中的问题: 您可以查询图像上的任何ROI/选择,并使用此信息限制迭代。 以下示例显示了这一点。它还显示了如何正确使用ROI对象,以获得选择以及添加新的ROI。更多信息可在F1帮助中找到:

该脚本获取最前面的图像,其中只有一个选择。 然后,它从左上角开始(以给定的步长)迭代选择并输出区域的和值。最后,您可以选择将使用的区域绘制为新的ROI

ClearResults()
//1)获取图像和图像大小
图像img:=GetFrontImage()
数字sx=img.ImageGetDimensionSize(0)
编号sy=img.ImageGetDimensionSize(0)
结果(“图像大小:+sx+“x”+sy+“\n”)
//2)获取用户绘制选择的大小(ROI)
//2a)
//如果您只处理简单的、用户绘制的矩形选择
//您可以使用下面的简化代码。
数字t,l,b,r
img.GetSelection(t、l、b、r)
结果(“标记坐标(简单):[“+t+”、“+l+”、“+b+”、“+r+”]\n”)
//2b)
//或者可以使用“full”命令捕捉其他情况。
//以下几行以更一般的方式检查ROI。
//这不是严格需要的,但是如果你想开始的话
//使用F1帮助部分中概述的命令的步骤
//“脚本>对象>文档对象模型>ROI对象”
imageDisplay disp=img.ImageGetImageDisplay(0)
如果(0==disp.ImageDisplayCountROIs())
抛出(“图像上没有ROI。”)
如果(1for(数字j=0;jt非常感谢你的回答!有一件事我不太明白。“异常被重新抛出”是什么意思?@bmygueste本质上,任何代码(C++)都可能遇到一些“意外”的问题。(比如通过零或任何除法。)在这种时刻,“异常被抛出”,基本上是发送一条消息“有点不对劲”。代码的另一部分“捕捉到”了这一点并相应地采取行动-即提示错误消息。如果没有代码捕捉到异常,应用程序可能会崩溃并关闭。“脱离绑定”错误就是这样一个时刻-您要求程序访问一些不存在的内存!通常是“脚本引擎”捕获此错误并提示错误。如果改为使用“Try{}Catch{}”,则..您自己可以“处理”如上所示的情况。但是,如果您不将“break”放在Catch循环中,则原始的“exception”未从队列中删除,并且DM脚本代码仍会提示您错误消息。只需在不使用“中断”的情况下尝试上面的代码。谢谢!我确实尝试了上面的代码,现在我明白了重新抛出的含义。但当我尝试在脚本中尝试尝试尝试捕获的想法时,效果并不理想。因为我让特定大小的ROI一个原子列一个原子列地移动,当它移动到靠近图像一侧的最后一个原子列时(但不是在图像的最后一个像素处),脚本仍将运行,并导致ROI结束于图像之外。我可以知道如何处理上述情况吗?作为补充信息,我确实知道图像的大小,但ROI的移动不是固定的。因此,当ROI位于最后一个原子列时,它不位于图像的最后一个像素处。而不是让ROI保持移动,因为有在它们前面的一些像素处,我试图使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 )
    }