我有一个周期性排列的原子图像,每个原子都标有椭圆形注释。我想知道如何从图像中删除一些注释。请有人帮帮我吗?
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()
}
}
你能帮我解决一下我的代码中哪一部分是错误的,因为我无法删除位于中间中的一些注释吗?
答案 0 :(得分:1)
要使用注释执行操作,您可以使用一些简化编码界面,如参考部分所述:
或者您可以使用&#34;完成&#34;界面,我将在下面给你看。
注释是DigitalMicrograph中的一种Component
。 (其他人是ROI
,ImageDisplay
和ImageDocument
的 root 。您可以在此处找到所有需要的命令(F1帮助):
// 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
可能有多个独立ImageDisplay
。 Image
可以在没有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 :您可以将一个图像(显示)作为子图像显示另一个图像(显示)。当你将一个图像复制到另一个图像时,你会得到这样的东西:
示例2 :您可以拥有一个imageDisplay
(数据),其中包含两个不同和独立components
- 因此您可以显示相同的内容数据同时作为电子表格和光栅图像。
示例3 :您可以同时使用一个image
(也是imageDisplays
)同时坐在两个不同的ROI
上。如果你移动一个&#39;,其他&#39;也动了:
component
我鼓励你去玩&#39;使用imageDisplays
,image 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 )
,image
,imageDocument
和imageDisplay
的概念来更好地理解内部运作。对于简单的脚本,您不需要它,但是当您想要创建更复杂的东西时,它是非常宝贵的知识。
答案 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()
}