2012-08-30 58 views
0

我在Numpy中有一个16x16x4数组。查找(x,y)坐标,其中z在numpy中通过测试

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

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

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

以2048x1285和替换16×16:

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] 

实际上几乎是有用的。如果z = [True,True,True,True],那么如何从16x16x4阵列到16x16x1阵列,其中array [x,y]为1,否则为0?

+1

什么,你在每一个有趣的point'意思'洪水补办?在符合标准的每个点上进行的处理是否可能比搜索这些点需要更多的时间? – DGH

+0

当位图= Image.open(“image.jpeg”)。load() – closeparen

+0

当位图= Image.open(“image.jpeg”).load()时,相同的循环在2-3秒内完成。 当位图= numpy.asarray(Image.open(“image.jpeg”))时,该循环花费7.5分钟。 (我不介意在PIL图像上工作,但它最终会从skimage.color.colorconv中运行,它在NumPy阵列上运行)。 (对不起,最后一个评论在回车键上提交,当我完成作品时不可编辑...) – closeparen

回答

0

for环路上ndarray迭代的效率不是很高,因为你已经注意到了。如果你想找到满足你的条件的条目的索引,你的确应该使用

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

这将返回一个三元素元组给予沿着第一,第二和第三轴解决方案的指标。由于您只对前两个维度感兴趣,因此您可以放弃第三个项目。如果你想有一个系列一样的(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功能,但你要测试的值必须是np.array太:

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

这一次,indices只会是一个2元组,你可以得到(x,y)夫妇与之前介绍的zip(*indices)

+0

我认为应该有一个'np.all(位图== ...,-1)',或两者都被视为rec数组。强迫所有人平等或“任何”避免重复。 – seberg

+0

那么,用'a = np.arange(16 * 16 * 4).reshape(16,16,4)','np.where(a == [956,957,958,959])'给出元组索引=(array ([14,14,14,14]),array([15,15,15,15]),array([0,1,2,3]))',如预期的那样... –

+0

是的,但是我意思是:'a = np.arange(16 * 16 * 4).reshape(16,16,4); a [:,:,0] = 0; print np.where(a == [0,957,958,959])' – seberg

0

原来我描述了什么是

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

根据任何文件哪家不清楚实现,但你有它。 (编辑:缺乏阿尔法信道是不显著。)

我感兴趣的测试实际上并不等于一个点,但欧几里得距离该点在阈值内。

numpy.apply_along_axis(distance_from_white ... 

其中distance_from_white是白色返回欧几里得距离的函数,工作在16×16,但在2048x1245只需要几分钟。 scipy.spatial.distance.pdist(或者cdist?)可能是那里的答案,但我无法弄清楚如何使它对一个点计算距离,而不是计算两个数组中所有点之间的距离(这可以在16x16,但它太浪费计算了,我甚至不敢尝试以实际大小来尝试)。

+0

在@DSM的回答中构造'm'和'b',对于小于阈值的点的欧几里德距离由'numpy.sum(np。 sqrt((m - b)** 2),axis = 2) YXD

1

我无法重现您的速度 - 即使我现在古老的笔记本电脑上的蛮力迭代速度大约快了14倍 - 我不确定where的工作方式与您认为的一样,所以我怀疑大部分时间都花在其他地方(比如在填写时)。总之:

如何从一个16x16x4阵列去16x16x1数组,其中数组[X,Y] 是1,如果Z = [真,真,真,真],否则为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 
相关问题