Как удалить некоторые аннотации с изображения?

У меня есть изображение с периодически расположенными атомами, где каждый отмечен овальной аннотацией. Я хотел бы знать, как удалить некоторые аннотации с изображения. Может кто-то мне помочь, пожалуйста?

РЕДАКТИРОВАТЬ после 1-го ответа

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()
         }
    }

Не могли бы вы помочь мне, какая часть моего кода неверна, так как я не могу удалить некоторые аннотации, расположенные посередине?


person Aning    schedule 01.06.2017    source источник


Ответы (2)


Чтобы работать с аннотациями, вы можете использовать некоторый упрощенный интерфейс кодирования, как описано в справочном разделе здесь:

введите здесь описание изображения

Или вы можете использовать полный интерфейс, как я покажу вам ниже. Аннотации — это один из видов Component в DigitalMicrograph. (Другие — ROI, ImageDisplay и корень ImageDocument). Здесь вы найдете все необходимые команды (справка 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, которые являются объектами, отвечающими за отображение данных на экране. (Как растр, линейный график, электронная таблица...). Общий объект, который записывается на жесткий диск, — это ImageDocument.

Каждый ImageDisplay связан ровно с одним Image (данными), но каждый Image может иметь более одного независимого ImageDisplay. Image может существовать без ImageDisplay (тогда он просто невидим в памяти и будет удален из памяти после завершения сценария). ImageDisplay не может существовать без Image.

Каждый ImageDocument содержит несколько ImageDisplays (плюс связанные Images). ImageDocument также может не содержать «ImageDisplay» - тогда это пустая страница.

В «нормальном» простом случае, когда вы создаете image в скрипте, он сначала невидим и без ImageDisplay, и без 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, как и сам imageDisplay, поэтому можно использовать все команды для components. Любой «компонент» может иметь дочерние компоненты (построение дерева). Итак, сначала вам нужно найти родителя, затем вы можете подсчитать количество дочерних элементов — либо всех, либо определенного типа — и выполнить итерацию, чтобы получить их. Затем вы можете изменить их (цвета и т. д.) или удалить их из родительского элемента, как показано выше.

Почему это так сложно?
Потому что это очень общая и гибкая концепция!

Пример 1: у вас может быть одно изображение (отображение), у которого есть другое изображение (отображение) в качестве дочернего элемента. Вы получаете такую ​​вещь, когда копируете одно изображение на другое:

введите здесь описание изображения

Пример 2. У вас может быть один image (данные) с двумя разными и независимыми imageDisplays, чтобы вы могли одновременно отображать одни и те же данные в виде электронной таблицы и растра. изображение.

Пример 3: у вас может быть один ROI (который также является component) одновременно на двух разных 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, ROI и Component, чтобы лучше понять внутреннюю работу. Вам не понадобится это для простых сценариев, но это бесценное знание, когда вы хотите создавать более сложные вещи, к которым вы стремитесь.

person BmyGuest    schedule 01.06.2017
comment
большое спасибо! Как вы предложили, я попытался изменить цикл, чтобы удалить некоторые аннотации, но это не помогло, потому что некоторые аннотации, которые я хочу удалить, находятся в середине (что означает, скажем, что есть 10 овальных аннотаций и те, которые я хочу удалить, это 3-я, 4-я и 5-я аннотации). Мой код выглядит следующим образом: - person Aning; 02.06.2017

Этот ответ относится к неработающему примеру сценария

Вы не можете сделать цикл while так, как вы это сделали.

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]

    Ой! Не то, что мы хотели...

Итак, чтобы решить эту проблему, вам нужно настроить цикл 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)!)


Наконец, иногда вам нужно поработать над конкретными компонентами, и количество компонентов меняется, например. из-за взаимодействия с пользователем - чтобы можно было не рассчитывать на индексацию. Вы решаете эту проблему, идентифицируя компоненты по их идентификационному номеру. Этот номер уникален во время сеанса 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()
}
person BmyGuest    schedule 02.06.2017