Algorithm 有效实施侵蚀/扩张

Algorithm 有效实施侵蚀/扩张,algorithm,math,computer-vision,filtering,convolution,Algorithm,Math,Computer Vision,Filtering,Convolution,因此,通常情况下,非常低效的最小/最大滤波器是通过使用四个for循环来实现的 (index1

因此,通常情况下,非常低效的最小/最大滤波器是通过使用四个for循环来实现的

(index1 对于(index2val)?像素:val;//最大值 } } dst(index2,index1)=val; } } 但是,这种方法非常低效,因为它会再次检查以前检查过的值。所以我想知道,在下一次迭代中,有什么方法可以使用以前检查过的值来实现这一点

可以对结构元素大小/原点进行任何假设


更新:我特别想知道关于这种或那种实现的任何见解:

提高复杂性的理论方法是为KxK像素维护BST,删除先前的Kx1像素,并向其添加下一个Kx1像素。此操作的成本为2K log K,重复次数为NxN次。总的来说,计算时间将从nxkxk变为nxkxlog K。我能想到的唯一方法是缓冲最大像素值和找到它们的行,这样,当最大值不再在内核大小的行/列上时,您只需对该行/列进行完整迭代。
在下面的类C伪代码中,我假设有符号整数、源和目标的2d行主数组以及[±dx,±dy]上的矩形内核

//初始化最大值及其行位置
对于(x=0;x=buf[x])
{
行[x]=y;
buf[x]=src[y][x];
}
}
}
//初始化最大列位置
col=-1;
对于(sx=0;sx
当源从左上角的最大值平滑过渡到右下角的最小值时,会出现最糟糕的性能,这会迫使在每一步进行完整的行或列扫描(尽管它仍然比原始嵌套循环更有效)。
不过,我希望平均情况性能会更好,因为包含递增值(行和列)的区域将在需要扫描之前更新最大值。

也就是说,由于没有实际测试,我建议您运行一些基准测试,而不是相信我的直觉

我关注这个问题已经有一段时间了,希望有人能写出一个充实的答案,因为我也在思考同样的问题

这是我自己迄今为止的尝试;我没有对此进行测试,但我认为您可以对任何结构元素重复进行膨胀和侵蚀,只需访问每个像素两次:

假设:假设结构元素/内核是一个KxL矩形,图像是一个NxM矩形。假设K和L是奇数

您概述的基本方法有四个for循环,需要
O(K*L*N*M)
时间才能完成

通常,您希望使用同一个内核重复扩展,因此时间再次乘以所需的扩展次数

我有三个加速扩张的基本想法:

  • KxL内核的膨胀等于Kx1内核的膨胀,然后是1xL内核的膨胀。你可以用三个for循环来完成这两个膨胀,单位是O(KNM)和O(LNM)

  • 但是,使用Kx1内核可以更快地进行扩展:只需访问每个像素一次。为此,您需要一个特定的数据结构,如下所述。这允许您以O(N*M)为单位进行单个扩展,而不管内核大小如何

  • Kx1核的重复扩张等于较大核的单一扩张。如果使用Kx1内核扩展P次,这等于使用
    ((K-1)*P+1)x1
    内核进行单个扩展。 因此,您可以在一次过程中,以O(N*M)的时间对任意大小的内核进行重复膨胀


  • 现在查看步骤2的详细说明。
    您需要具有以下属性的队列:

    • 以固定时间将元素推到队列的后面
    • 以固定时间从队列前面弹出一个元素
    • 以固定时间查询队列中当前最小或最大的元素
    此stackoverflow回答中描述了如何构建这样的队列:。 不幸的是,没有太多的伪代码,但基本思想似乎是正确的

    使用这样的队列,您可以在一次过程中计算Kx1膨胀:

    Assert(StructuringElement.dy()==1);
    int kernel_half=(StructuringElement.dx()-1)/2;
    对于(y
    同样的优化可以用作“非最大抑制”算法

    在1D中,在O(N)中使用形态小波变换:


    你可以在2D中得到O(N*M)。HugoRune解决方案更简单,可能更快(尽管这个可能会得到改进)。

    这不是一个完整的解决方案,只是一个想法:我认为操作是可分解的,也就是说,你可以通过执行一行3x1和1x3的扩张来获得3x3的扩张,这要快得多