【问题标题】:Region Growing in DMDM 区域增长
【发布时间】:2017-10-26 09:12:30
【问题描述】:

有人知道在 DM 中执行区域增长的更快方法吗? 我有类似于下面示例中的测试图像的粒子图像, 每个粒子在粒子内部具有较小的面积和较低的强度。 我想扩大这些最低强度的区域来满足整个粒子的边界。 该脚本使用膨胀和 如果一个人把 x = 1024 或 2048,它已经太慢了....

编辑:

我事先知道 seg 图像。但我看不到一个人如何达到目的 使用简单的 tert() 命令得到结果,因为不同的粒子具有不同的值。子区域的想法可能会奏效,这将需要粒子计数。有一个菜单命令“分析粒子”可以做到这一点,但怎么能 这可以快速完成脚本吗? 这是一个实际的例子:

(External Link for full res 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)

【问题讨论】:

  • 我是否理解正确,只要强度更高,您基本上想从种子中填充?我不确定我是否正确理解您的算法想要实现的目标(在存在噪声的情况下)以及“边界条件”是什么。在您的示例图像中,因为简单的 tert() 阈值处理会导致最终结果......(为了清晰起见,您可能希望在帖子中添加真实图像。)
  • 无论如何,脚本中不会有“区域增长”命令,所以这更像是一个算法问题而不是编码问题。一旦明确了任务是什么,我们仍然可以讨论更有效的做事方式。
  • 我不清楚的是:您是否知道确切的(几何)边界(即您的“seg”图像)?因为,显然,如果你“只是”想填补已知“seg”图像中的漏洞,任务就不同了。
  • 顺便说一句,加速您自己的算法的一个明显方法是首先找到您的粒子的“子区域”,然后只在这个子图像上使用迭代扩张,而不是在整个子图像上。跨度>
  • 嗨,“唐,我”,当您在 StackOverflow 上“回答”cmets 时,请务必写一条评论,指出您要回答的人(使用 @username 向人们)。主帖中的编辑不会自动“显示”在主列表中,并且很容易被遗漏。我现在才看到您从 10 月 28 日开始的编辑。我现在没时间了,等我有时间再回来。

标签: dm-script


【解决方案1】:

这可能不是您要寻找的,但我仍然不是 100% 清楚您的“目标”。到目前为止,从您的问题来看,您似乎想要一个掩码的二进制图像,您只需将所有 0 值图像保持为零并将所有其他图像设置为 1 即可获得。可以用或只是一个双“非”:

image src := GetFrontImage()

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

但是,我想您的真正目标是为每个 individual 粒子单独获取这些二进制掩码,即当您有 10 个不同(空间分离)时,获得 10 个仅显示一个粒子的二进制掩码粒子。这是一项有些不同的任务。

【讨论】:

    【解决方案2】:

    在您的帖子中,您似乎说“粒子分析”可能已经在做您想要的,所以解决您问题的一种方法可能是立即使用粒子分析!

    很遗憾,该软件的这一部分目前无法通过脚本 API 正确访问。然而,只要有一点“开箱即用”的想法和一些黑客技能,就可以使用与 UI 相关的命令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()    
    }
    

    【讨论】:

    • 感谢大家的时间和cmets!我会试试这些,看看什么对我有用,然后在这里发布脚本!
    【解决方案3】:

    您可能想要获取每个粒子的像素坐标。要存储它,您需要创建一个 taglist 的 taglist。从 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”函数来使该粒子变暗并返回循环。

    【讨论】:

    • 我不太清楚你的 'dfs()' 会做什么。返回 binSrc 中连接像素的 tagList?你能发布'dfs()'吗?
    • 是的。返回连接像素的标记列表,起点是 (x,y)。由于工作场所限制,我无法在此处发布完整代码。该算法可以在这里找到:geeksforgeeks.org/depth-first-traversal-for-a-graph.
    • 感谢您的链接。基于 DM 脚本的算法实现大约有多快?我想在for循环中使用单像素操作非常慢......但是算法只会遇到那些“连接”的像素,而不是图像中的所有像素?
    • 总像素 = 11885 持续时间:2.74526sec
    • 总像素,numberOfClusters = 24785, 568 持续时间:8.75389 秒。这是仅用于搜索的实时时间。以前运行时会执行清理大小小于阈值的集群的额外操作。
    猜你喜欢
    • 2011-08-16
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    相关资源
    最近更新 更多