Регион Растет в DM

Кто-нибудь знает какой-нибудь более быстрый способ выполнения роста региона в DM? У меня есть изображения частиц, похожие на тестовое изображение в приведенном ниже примере, каждая частица имеет меньшие области с более низкой интенсивностью внутри частицы. Я хочу вырастить эти области с самой низкой интенсивностью, чтобы заполнить границы всей частицы. Этот скрипт работает с расширением, и если поставить x = 1024 или 2048, он уже будет слишком медленным....

редактировать:

Я знаю образ seg заранее. Но я не понимаю, как можно добиться конечных результатов с помощью простой команды tert(), поскольку разные частицы имеют разные значения. Идея субрегионов может сработать, для этого потребуется подсчет частиц. Есть команда меню "анализировать частицы", которая может это сделать, но как это можно сделать быстро с помощью скрипта? Вот реальный пример:

введите здесь описание изображения ( Внешняя ссылка для TIF в полном разрешении (DropBox) )

Например, самая большая частица будет иметь значения 29, наименьшее число внутри этой частицы. Я также отредактировал код для работы с передним изображением.

// $BACKGROUND$

image front:=getfrontimage()
image newfront = front


number x,y,i,su,su1,val=14,ok=1,count = 0,min,max,z,j,mmax=0
getsize(front,x,y)


image seg := binaryimage("",x,y)
image new := binaryimage("",x,y)


image mp:= binaryimage("",x,y)


minmax(front,min,max)



    image front1 = front
    seg=tert(front1>0,1,0)

    for(i=1;i<=max;i++)
    {

    new=tert(front1==i,1,0)
    su = sum(new)
    result(" int "+i+" of "+max+"  \n")
        while(ok)
        {
        mp = MPdilate( new ,7)
        mp = mp*seg
        if(sum(mp)==su) ok=0
        su = sum(mp)
        count++
        new=mp
        }
    ok=1
    front1 =  tert(new>0,i,front1) 
    }   


showimage(front1)

person Don I    schedule 26.10.2017    source источник
comment
Правильно ли я понял, что вы, по сути, хотите заполнять поток из семени, пока интенсивность выше? Я не уверен, что правильно понимаю, чего хочет добиться ваш алгоритм (при наличии шума) и каковы граничные условия. В вашем примере изображения, поскольку простое tert() tresholding уже приведет к конечному результату... (Возможно, вы захотите добавить реальное изображение в свой пост для ясности.)   -  person BmyGuest    schedule 26.10.2017
comment
В любом случае, в сценариях не будет команды увеличения региона, так что это скорее вопрос алгоритма, чем вопрос кодирования. Тем не менее, мы можем обсудить более эффективные способы ведения дел, как только станет ясно, в чем заключается задача.   -  person BmyGuest    schedule 26.10.2017
comment
Что мне не ясно, так это: знаете ли вы точную (геометрическую) границу (т.е. ваши изображения seg) или нет? Потому что, очевидно, задача отличается, если вы просто хотите заполнить дыры в известном образе seg.   -  person BmyGuest    schedule 26.10.2017
comment
Кстати, очевидным способом ускорения вашего собственного алгоритма было бы сначала найти подобласть вашей частицы, а затем использовать итеративное расширение только для этого фрагмента изображения, а не для всего.   -  person BmyGuest    schedule 26.10.2017
comment
Привет, Дон, пожалуйста, когда вы отвечаете на комментарии в StackOverflow, не забудьте написать комментарий, адресованный человеку, которому вы хотите ответить (используя @username для отправки оповещения людям). Правки в основном посте автоматически не отображаются в основном списке, и их легко пропустить. Я только сейчас увидел вашу правку от 28 октября. У меня сейчас нет времени, но я вернусь к этому, когда у меня будет время.   -  person BmyGuest    schedule 06.11.2017


Ответы (3)


Возможно, это не то, что вы ищете, но ваша «цель» мне все еще не ясна на 100%. Из вашего вопроса до сих пор кажется, что вам только нужно двоичное изображение вашей маски, которое вы бы просто получили, сохранив все изображения с нулевым значением как ноль и установив для всех остальных значение 1. Можно сделать с трет или просто двойное "не":

image src := GetFrontImage()

image binMask = !!src
binMask.SetName( "Binary" )
binMask.ShowImage()

Однако я предполагаю, что ваша реальная цель состоит в том, чтобы получить эти бинарные маски для каждой отдельной частицы по отдельности, то есть получить 10 бинарных масок, показывающих только одну частицу, когда у вас есть 10 разных (пространственно разделенных) частиц. Это несколько другая задача.

person BmyGuest    schedule 06.11.2017

В своем сообщении вы, кажется, говорите, что «Анализ частиц», вероятно, уже делает то, что вы хотите, поэтому одним из решений вашей проблемы может быть фактическое использование анализа частиц прямо сейчас!

К сожалению, эта часть программного обеспечения в настоящее время недоступна должным образом через скриптовый API. Тем не менее, обладая небольшим количеством нестандартного мышления и некоторыми навыками взлома, можно получить доступ к необходимой функциональности с помощью связанной с пользовательским интерфейсом команды ChooseMenuItem().

Ниже я публикую небольшой пример, который я только что собрал. Сначала он обрабатывает бинарное входное изображение, затем применяет анализ частиц по умолчанию, затем получает изображение результатов и использует содержащуюся информацию для вырезания частиц.

Извините за неаккуратное кодирование, но вы можете модифицировать этот скрипт под свои нужды.

number GetMeasurementsColumnIndex( image input, string colLabel )
{
    // Basic checks... return <0 if fail.
    if ( !input.ImageIsValid() ) return -1
    if ( input.GetName() != "Measurements" ) return -2
    if ( 0 == input.ImageCountImageDisplays() ) return -3

    imageDisplay disp = input.ImageGetImageDisplay( 0 ) 
    number sx = input.ImageGetDimensionSize( 0 )
    for( number c = 0; c<sx; c++ )
        if ( colLabel == disp.SpreadsheetImageDisplayGetColumnLabel(c) ) 
            return c

    return -4 // not found
}


// Main Script (Test)
number bOnNewWorkSpace = 1

// Pre-#1: Ensure relevant information is computed by particle Anlaysis
// The info is stored in the tags, but it seems it is only read from there
// on start-up... (needs checking)
GetPersistentTagGroup().TagGroupSetTagAsBoolean( "Private:Particles:Configuration:Length", 0 ) 
GetPersistentTagGroup().TagGroupSetTagAsBoolean( "Private:Particles:Configuration:Width", 1 ) 
GetPersistentTagGroup().TagGroupSetTagAsBoolean( "Private:Particles:Configuration:CenterX", 1 ) 
GetPersistentTagGroup().TagGroupSetTagAsBoolean( "Private:Particles:Configuration:CenterY", 1 ) 

// #1 Act on binary image mask based on front-image (temp)
image source := GetFrontImage()
image binSrc = !!source


// #2 Potentially work on "clean" workspace
if ( bOnNewWorkSpace )
{
    number wsID_src = WorkSpaceGetActive()
    number wsID_results = WorkSpaceAdd( WorkSpaceGetIndex(wsID_src) + 1 )
    WorkSpaceSetActive( wsID_results )
}

// #3 Treshold the mask by script. (Requires display)
binSrc.ShowImage()
imageDisplay disp = binSrc.ImageGetImageDisplay( 0 )
disp.RasterImageDisplaySetThresholdOn( 1 ) 
disp.RasterImageDisplaySetThresholdLimits( 0.1, 1 ) 

// #4 Perform Particle analysis, grab results, close temp. source
ChooseMenuItem( "Analysis", "Particles", "Analyze Particles" )
binSrc.DeleteImage()
image particleList := GetFrontImage()

// #5 Perfrom checks on results before proceeding. 
// (Particle Analysis may be configured by script by modifying persistent tags. See pre-step #1)
number pxIndex = GetMeasurementsColumnIndex( particleList, "CenterX" )
number pyIndex = GetMeasurementsColumnIndex( particleList, "CenterY" )
number pRIndex = GetMeasurementsColumnIndex( particleList, "MaxRadii" ) 

if ( pxIndex < 0 ) Throw( "Need to setup Analysis to create 'CenterX' output." )
if ( pyIndex < 0 ) Throw( "Need to setup Analysis to create 'CenterY' output." )
if ( pRIndex < 0 ) Throw( "Need to setup Analysis to create 'MaxRadii' output." )

// #6 Use results. Example Create Individual crops from source
//  ( This may still include intruding pixels from neighboring particles )
number nParticles = particleList.ImageGetDimensionSize( 1 )
nParticles = 5 // for testing...
for( number p = 0; p<nParticles; p++ )
{
    number px = particleList.GetPixel( pxIndex, p )
    number py = particleList.GetPixel( pyIndex, p )
    number pR = particleList.GetPixel( pRIndex, p )
    number y0 = py - pr
    number x0 = px - pr

    image crop := source.Slice2( x0,y0,0, 0,pR*2,1, 1,pR*2,1).ImageClone()
    crop.ShowImage()    
}
person BmyGuest    schedule 06.11.2017
comment
Спасибо всем за ваше время и комментарии! Я попробую их и посмотрю, что работает для меня, и опубликую сценарий здесь! - person Don I; 09.11.2017

Возможно, вы захотите получить координаты пикселей для каждой частицы. Чтобы сохранить его, вы создаете taglist taglists. Начните с кратких кодов BeMyGuest, вы можете сделать это:

image source := GetFrontImage()
image binSrc = !!source
taggroup tgPartcleList=newTagList()
taggroup tgParticleIndividual=newTagList()
number val, x, y
while (1) {
   val=binSrc.max(x, y)
   if (val==0) break
   else {
      tgParticleIndividual=dfs(binSrc, x, y)
   }
   tgPartcleList.taggroupInsertTagAsTagGroup(infinity(), tgParticleIndividual)
   turnOffpixels(binSrc, tgParticleIndividual)
}

функция dfs - это "поиск в глубину". По сути, это один из видов «поиска связанных компонентов». Алгоритмов для этого много. Я использовал «сначала в глубину», который можно закодировать со структурой стека, смоделированной с помощью группы тегов. после каждого dfs вы вызываете функцию «turnOffpixels», чтобы затемнить эту частицу и вернуться к циклу.

person user6406828    schedule 09.11.2017
comment
Я не совсем понимаю, что будет делать ваш 'dfs()'. Вернуть список тегов связанных пикселей в binSrc? Не могли бы вы опубликовать «dfs ()»? - person BmyGuest; 09.11.2017
comment
Да. вернуть список связанных пикселей, начальная точка (x, y). Я не могу опубликовать здесь полный код из-за ограничений на рабочем месте. Алгоритм можно найти здесь: geeksforgeeks.org/depth-first- обход графа. - person user6406828; 10.11.2017
comment
Спасибо за ссылку. Насколько быстро реализуется алгоритм на основе DM-скрипта? Я предполагаю, что использование однопиксельной операции в цикле for довольно медленно... Но алгоритм будет встречать только те связанные пиксели, а не все пиксели в изображении? - person BmyGuest; 10.11.2017
comment
всего пикселей = 11885 Продолжительность: 2,74526 сек. - person user6406828; 11.11.2017
comment
всего пикселей = 24773 Продолжительность: 9,5487 сек. Да. Только связанные пиксели. Время, указанное здесь, относится к изображению размером 1024 x 1024 с множеством ярких линий. Общее время указано для всех ярких пикселей, каждый связанный кластер сгруппирован в отдельный список тегов, а все кластеры сгруппированы в один главный список тегов. Это не быстро. Определенно намного медленнее, чем метод мультипроекции Шаффера, но это для всех ярких пикселей в бинарном изображении. - person user6406828; 11.11.2017
comment
Насколько я понимаю, нельзя уйти от попиксельной операции для подсчета связанных точек. Потому что вам нужно постоянно проверять отношения соседей. Буду рад увидеть, если есть более быстрый способ. - person user6406828; 11.11.2017
comment
всего пикселей, numberOfClusters = 24785, 568 Продолжительность: 8,75389 сек. Это реальное время только для поиска. Предыдущий запуск выполнялся с дополнительными действиями по очистке кластеров размером меньше порогового значения. - person user6406828; 11.11.2017