窗口在图像中滑动

时间:2018-08-02 23:02:46

标签: python multithreading numpy

目标:在2D图像(灰度)中滑动2D“窗口”。对于图像的每个像素,复制窗口(图案)内的所有像素,然后移至下一个像素。

问题:非常慢。我想加快速度。

使用Cython(ewwww)除外。

我在具有48个内核的服务器中使用此代码,因此可以选择并行处理。 因此,我对如何使用numpy处理多线程解决方案感到困惑。

说明:我有一种称为提取的方法。此方法接收灰度图像,位置i和j指的是窗口居中的图像的x轴和y轴。对于i和j的每个位置,我会将窗口看到的内容复制到另一个数组。

img是2d NumPy数组。

pat可以删除,我可以返回该模式。没关系。

ij是整数。

def extract(self, img, i, j, pat):
        pattern = pat
        win = self.window
        hh = win.shape[0]
        ww = win.shape[1]
        hh2 = hh / 2
        ww2 = ww / 2
        k = 0

        for l in range(-hh2, hh2 + 1):
            for m in range(-ww2, ww2 + 1):
                    try:
                        pattern[k] = img[i + l, j + m]
                    except:
                        pattern[k] = 0
                    k += 1

1 个答案:

答案 0 :(得分:1)

显而易见的答案是将这些循环矢量化。没有完整的示例,很难进行任何测试,因此我只给出一个草图。

我们要转这个:

for m in range(-ww2, ww2 + 1):
        try:
            pattern[k] = img[i + l, j + m]
        except:
            pattern[k] = 0
        k += 1

…在patternimg的切片上进行单个分配,而不是对patternimg的索引进行循环分配。


首先,让我们忘记边界的东西,以使其更简单。我们如何才能将这些i + lj + mk全部向量化?

  • m是您范围内的索引,并且j是常数,因此j + m的范围超过j-ww2:j+ww2+1
  • k是您范围的索引减去范围的起始值。因此它来自ww2:2*ww2+1
  • il在内部循环中都是恒定的,因此我们根本不需要在那里进行任何更改。

所以:

pattern[ww2:2*ww2+1] = img[i + l, j-ww2:j+ww2+1]

现在,边界问题呢?这总是很痛苦的-在这里我无能为力,因为我不知道这些值之间如何相互关联或您担心的边界是什么,但您可能需要这样的东西:

lok, hik = ww2, 2*ww2+1
lojm, hijm = max(0, j-ww2), min(j+ww2+1, width)
pattern[lok:hik] = img[i+l, lojm:hijm]

如果一条边的另一边需要为0,那么快速而肮脏的答案是将其手动插入,例如:

if hijm == width:
    pattern[hik] = 0

一旦完成这项工作,就有望将内循环速度提高一个数量级。

如果内部循环大小适中(即ww2不是一个很小的数字),那么您就可以完成。如果很小,您可能需要对外循环进行类似的转换,但这并不比我们刚刚做的难。