1

我在 Numpy 中有一个 16x16x4 数组。

维度 1:水平位置 [0,15]

维度 2:垂直位置 [0,15]

维度 3:RGB 值 0-255 [0,3]

将 16x16 替换为 2048x1285 并且:

for x in range(0,15):
    for y in range(0,15):

不削减它(超过 7 分钟的时间来执行此操作,并在每个有趣的点进行洪水填充)。迭代 PIL 图像非常快,但是 numpy 数组会拖累(即 7 分钟以上)。

numpy.where(bitmap == [red, green, blue, alpha])

看起来这不是我要找的。什么是一种相当快速的方法来解决这个问题?

编辑:

bitmap == [red, green, blue, alpha]

实际上几乎有用。如何从 16x16x4 数组转到 16x16x1 数组,如果 z = [True,True,True,True] 则数组 [x,y] 为 1,否则为 0?

4

3 回答 3

1

我无法重现你的速度——即使是我现在古老的笔记本上的蛮力迭代也快了大约 14 倍——而且我不确定where你认为它的工作方式,所以我怀疑你的大部分时间用在其他地方(比如你自己填)。反正:

如何从 16x16x4 数组转到 16x16x1 数组,如果 z = [True,True,True,True] 则数组 [x,y] 为 1,否则为 0?

我会:

In [169]: m = numpy.random.randint(0, 16, size=(2048, 1285, 4))

In [170]: b = [4,5,6,7]

In [171]: matches = (m == b).all(axis=2)*1

In [172]: matches.shape
Out[172]: (2048, 1285)

它非常快:

In [173]: timeit matches = (m == b).all(axis=2)*1
10 loops, best of 3: 137 ms per loop
于 2012-08-31T02:51:06.287 回答
0

事实证明,我描述的是通过

zip(*numpy.where(numpy.logical_and.reduce(image == [255,255,255])))

根据任何文件都不清楚,但你有它。(编辑:缺少 alpha 通道并不重要。)

我感兴趣的测试实际上并不是一个点的相等性,而是到那个点的欧几里得距离在一个阈值内。

numpy.apply_along_axis(distance_from_white ...

其中 distance_from_white 是返回与白色的欧几里得距离的函数,在 16x16 下工作,但在 2048x1245 下需要几分钟。scipy.spatial.distance.pdist (或 cdist?)可能是那里的答案,但我不知道如何让它计算与单个点的距离而不是 2 个数组中所有点之间的距离(这适用于 16x16,但它浪费了太多的计算,我什至不敢尝试实际尺寸)。

于 2012-08-31T02:47:20.643 回答
0

for正如您所注意到的,在 a 上使用循环进行迭代ndarray不是很有效。如果您想找到满足您条件的条目的索引,您确实应该使用

indices = np.where(bitmap == [R, G, B, A])

这将返回一个 3 元素元组,给出沿第 1、第 2 和第 3 轴的解的索引。由于您只对前两个维度感兴趣,因此您可以删除第三个项目。如果你想要一系列索引(x,y),你只需要使用类似的东西

zip(*indices[:2])

第二种可能性是将(N,M,4)标准整数查看ndarray(N,M)结构化数组中dtype=[[('',int)]*4](不要打扰字段名称,它们将自动扩展为'f0', 'f1', ...

alt_bitmap = bitmap.view([('',int)'*4).squeeze()

squeeze引入了将数组折叠(N,M,1)(N,M)数组)

然后您可以使用该np.where函数,但您要测试的值也必须是 a np.array

indices = np.where(bitmap==np.array((R, G, B, A), dtype=bitmap.dtype))

这一次,indices将只有一个 2 元组,并且您可以获得前面介绍的(x,y)情侣。zip(*indices)

于 2012-08-30T23:44:48.727 回答