如何从图像中删除一些注释?

时间:2017-06-01 05:14:51

标签: annotations dm-script

我有一个周期性排列的原子图像,每个原子都标有椭圆形注释。我想知道如何从图像中删除一些注释。请有人帮帮我吗?

第一次回答后编辑

image img := GetFrontImage()
component imgdisp = ImageGetImageDisplay( img, 0 )
number count_oval = imgdisp.ComponentCountChildrenOfType(6)
okdialog("There are "+count_oval+" oval annotations")
number i

    for( i=1; i<=count_oval; i++)
    {   while(3<=i<=5)
         { component annot=imgdisp.ComponentGetNthChildOfType(6,0)
           annot.ComponentRemoveFromParent()
         }
    }

你能帮我解决一下我的代码中哪一部分是错误的,因为我无法删除位于中间中的一些注释吗?

2 个答案:

答案 0 :(得分:1)

要使用注释执行操作,您可以使用一些简化编码界面,如参考部分所述:

enter image description here

或者您可以使用&#34;完成&#34;界面,我将在下面给你看。 注释是DigitalMicrograph中的一种Component。 (其他人是ROIImageDisplayImageDocument root 。您可以在此处找到所有需要的命令(F1帮助):

enter image description here

// Get the imageDisplay from the image
// (It is the "parent" component of all things displayed on the image.)
image img := GetFrontImage()
imageDisplay disp = img.ImageGetImageDisplay(0)

// If you want to remove components of a specific type
number annoType = 5 // Box
number nBoxAnno = disp.ComponentCountChildrenOfType( annoType )
OKDialog( "There are " + nBoxAnno + " annotations of type " + annoType + ".\nRemove them now." )
for( number i = 0; i<nBoxAnno; i++ )
{
    // Get first existing component of a specific type
    component boxComp = disp.ComponentGetNthChildOfType( annoType, 0 )  
    // Remove it from its parent component (the imageDisplay)
    boxComp.ComponentRemoveFromParent()
}

// If you want to remove all components of a specific type
number nAllAnno = disp.ComponentCountChildren()
OKDialog( "There are " + nAllAnno + " child components.\nRemove them now." )
for( number i = 0; i<nAllAnno; i++ )
{
    // Get first existing component 
    component anyComp = disp.ComponentGetChild( 0 ) 
    // Remove it from its parent component (the imageDisplay)
    anyComp.ComponentRemoveFromParent()
}
  

在示例中,我删除了一种类型的所有注释。如果要删除的一些,则需要修改for循环。您可以对组件执行不同的检查,以查看是否要将其删除。

更好理解的一些更广泛的解释:

您需要知道每个Image是内存中的数据(加上校准和标签)。每个Image可以有一个或多个ImageDisplays,它们是负责在屏幕上显示数据的对象。 (如Raster,LinePlot,Spreadsheet ......)。写入硬盘的整体对象是ImageDocument

每个ImageDisplay只与一个Image(数据)相关联,但每个Image可能有多个独立ImageDisplayImage可以在没有ImageDisplay的情况下存在(它在内存中只是不可见,并且在脚本结束时将从内存中删除。)ImageDisplay在没有{{1}的情况下不能存在}。

每个Image包含多个ImageDocument(以及相关的ImageDisplays)。 Images也可以不包含“ImageDisplay”。 - 那时它是一个空页。

在&#39; normal&#39;简单的情况是,当您在脚本中创建ImageDocument时,它首先是不可见的,没有image且没有ImageDisplay,但是当您第一次显示它时,{{1}并自动创建ImageDocument

ImageDisplay

现在,正如所说的那样,注释只是ImageDocument中的一种 - 就像image img := RealImage( "Test", 4, 100, 100 ) // imageDisplay disp1 = img.ImageGetImageDisplay(0) // Does not work yet! img.ShowImage() imageDisplay disp = img.ImageGetImageDisplay(0) imageDocument doc = img.ImageGetOrCreateImageDocument() // Always works 本身一样 - 因此可以使用component的所有命令。任何&#39;组件&#39;可以有子组件(构建一棵树)。因此,您首先需要找到,然后您可以计算子项的数量 - 全部或特定类型的子项 - 并迭代以获取它们。然后,您可以修改它们(颜色等)或从父项中删除,如上所示。

  

为什么这么复杂?
因为它是一个非常通用和灵活的概念!

示例1 :您可以将一个图像(显示)作为子图像显示另一个图像(显示)。当你将一个图像复制到另一个图像时,你会得到这样的东西:

enter image description here

示例2 :您可以拥有一个imageDisplay(数据),其中包含两个不同和独立components - 因此您可以显示相同的内容数据同时作为电子表格和光栅图像。

示例3 :您可以同时使用一个image(也是imageDisplays)同时坐在两个不同的ROI上。如果你移动一个&#39;,其他&#39;也动了:

component

我鼓励你去玩&#39;使用imageDisplaysimage img1 := RealImage( "img1", 4, 100, 100 ) image img2 := RealImage( "img2", 4, 100, 100 ) ROI theROI = NewROI() theROI.ROISetVolatile(0) theROI.ROISetRectangle( 10, 10, 30, 30 ) img1.ShowImage() img2.ShowImage() img1.ImageGetImageDisplay(0).ImageDisplayAddROI( theROI ) img2.ImageGetImageDisplay(0).ImageDisplayAddROI( theROI ) imageimageDocumentimageDisplay的概念来更好地理解内部运作。对于简单的脚本,您不需要它,但是当您想要创建更复杂的东西时,它是非常宝贵的知识。

答案 1 :(得分:1)

这个答案是指破碎的示例脚本

  

你不能像你那样做一个循环。

while( 2 <= i <= 5 )不是有效条件。如果你需要做这样的循环,它必须是while( (2 <= i) && ( i <= 5) ),你需要确保i实际上改变了循环中的值,或者它是一个无限循环! 你基本上继续“去除椭圆形注释的第一次出现”,直到不再存在。然后下一个调用再也找不到了,脚本崩溃了。

  

您的脚本实际结束,因为发生了错误。

如果您只是删除错误的while循环,那么您的脚本完全没问题!

image img := GetFrontImage()
component imgdisp = ImageGetImageDisplay( img, 0 )
number count_oval = imgdisp.ComponentCountChildrenOfType(6)
okdialog("There are "+count_oval+" oval annotations")
number i

for( i=1; i<=count_oval; i++)
{   
    //while(3<=i<=5)  // Don't do this!
     { 
       component annot=imgdisp.ComponentGetNthChildOfType(6,0)
       annot.ComponentRemoveFromParent()
     }
}

就个人而言,我会稍微改写代码,但这只是风格不起作用的问题:

for( number i = 0; i<count_oval; i++)
{   
    component annot=imgdisp.ComponentGetNthChildOfType(6,0)
    annot.ComponentRemoveFromParent()
}

如果你想摆脱一个类型的所有注释,你也可以不计算它们,只是继续寻找它们,直到所有注释被删除:

number type = 6
image img := GetFrontImage()
component imgdisp = ImageGetImageDisplay( img, 0 )

while( 0 != imgdisp.ComponentCountChildrenOfType(type) )
    imgdisp.ComponentGetNthChildOfType(type,0).ComponentRemoveFromParent()

现在,如果要删除组中“中间”的子集,则必须注意当删除项目时,会将其余项目的位置向下移动到列表中。只需考虑要删除中间两个的4个注释的示例。你想要在第1和第2位连续删除,因为:

  • 1位置删除 [anno0], [anno1] ,[anno2],[anno3]

  • 2位置删除 [anno0],[anno2], [anno3]

  • [anno0],[anno2]

    Oups!不是我们想要的......

所以要解决这个问题,你需要调整你的for循环。如果它是一个连续段,您只需将“get at”索引调整到该范围的第一个位置:

number type = 6
image img := GetFrontImage()
component imgdisp = ImageGetImageDisplay( img, 0 )
number nTotal = imgdisp.ComponentCountChildrenOfType(type)
number start = 2    // start index, so we are starting with the 3rd annotation
number nRange = 2   // We want to delete 3 annotations ( 3rd, 4th and 5th )

for( number i = 0; i < nRange; i++ )
    imgdisp.ComponentGetNthChildOfType(type,start).ComponentRemoveFromParent()
  

注意:程序员的惯例是以0作为第一个位置开始索引。如果你从一开始就在自己的代码中开始遵循这个约定,那么你可以节省很多错误。 (对于索引像素,这也是如此。图像中的第一个像素是(0,0)而不是(1,1)!)

最后,有时你需要处理特定的组件和组件数量的变化 - f.e.因为用户交互 - 所以你不能依赖索引。您可以通过ID号识别组件来解决此问题。这个数字在DigitalMicrograph会议期间是独一无二的。 在识别组件时,您需要“存储”该号码。然后你可以稍后找到该组件。 (但如果找到了,你需要检查。) 这是一个例子:

number type = 6
image img := GetFrontImage()
component imgdisp = ImageGetImageDisplay( img, 0 )
number nTotal = imgdisp.ComponentCountChildrenOfType(type)

// Find the IDs of all annotations of this type 
// and store them in a tagGroup
ClearResults()
TagGroup compIDgroup = NewTagList()
for( number i = 0; i < nTotal; i++ )
{
    number cID =imgdisp.ComponentGetNthChildOfType(type,i).ComponentGetID()
    Result( "Annotation at index " + i + " has ID:" + cID + "\n" )
    compIDgroup.TagGroupInsertTagAsLong(  infinity(), cID ) // add to end of list
}

If ( TwoButtonDialog( "Show tags?", "Yes", "No" ))
    compIDgroup.TagGroupOpenBrowserWindow( "cIds", 0 )

// ... do whatever which adds or removes other components

// Process "your" annotations by the ID
number nIDs = compIDgroup.TagGroupCountTags()
for ( number i = 0 ; i < nIDs; i++ )
{
    number cID
    compIDGroup.TagGroupGetIndexedTagAsLong( i, cID )
    Result( "Processing tag of ID " + cID + "\n" )
    component comp = imgDisp.ComponentGetChildByID( cID )
    if ( !comp.ComponentIsValid() )
    {
        Result( "  NOT FOUND. Skip.\n" )
        continue        // jump to next step of for-loop 
    }
    comp.ComponentRemoveFromParent()
}