使用numpy、python和opencv 2.4遍历多维数组
最近我在这个问题上发过一个帖子,但最后我用了一种不太优雅的方法解决了它。
我有两张图片,它们是numpy数组,我想通过遍历这两张图片来创建一个新的数组。我有三种情况,做了如下操作:
delta= np.empty((h, w, 3),int)
for z in range (0,3):
for i in range(0, (h-1)):
for j in range(0, (w-1)):
delta[i][j][z]=np.sqrt(((imgLlab[i][j][0]-imgRlab[i][j-disp[i][j]][0])**2) + ((imgLlab[i][j][1]-imgRlab[i][j-disp[i][j]][1])**2) + ((imgLlab[i][j][2]-imgRlab[i][j-disp[i][j]][2])**2) )
delta= np.empty((h, w, 3),int)
for z in range (0,3):
for i in range(0, (h-1)):
for j in range(0, (w-1)):
delta[i][j][z]=np.sqrt(((imgLlab[i][j][0]-imgRlab[i][j-disp[i][j]][0])**2) )
for z in range (0,3):
for i in range(0, (h-1)):
for j in range(0, (w-1)):
delta[i][j][z]=np.sqrt(((imgLlab[i][j][1]-imgRlab[i][j-disp[i][j]][1])**2) + ((imgLlab[i][j][2]-imgRlab[i][j-disp[i][j]][2])**2) )
我希望能避免每次都重复遍历,尽量快速完成这个操作。
有没有其他方法可以用numpy来实现这个呢?
编辑:在Jaime的帮助下,我把代码改成了这样:
disp= np.hstack([disp, disp, disp]).reshape(h,w,3).astype(np.int)
rows = np.arange(h).reshape(h, 1, 1)
cols = np.arange(w).reshape(1, w, 1)
planes = np.arange(3).reshape(1, 1, 3)
print rows.shape, cols.shape, planes.shape, disp.shape, h
data = imgLlab[rows, cols, planes] - imgRlab[rows ,cols - disp[rows, cols, planes], planes]
data = data**2
data = np.sum(data, axis=-1)
data = np.sqrt(data)
我需要调整dist的形状,因为它和imglLab、imgRLab的形状不一样。也就是说,imglLab的形状是(288, 384, 3),而disp的形状是(288, 384)。另外,如果我打印disp(288, 384, 1),我会得到同样的错误,感觉里面没有值,但维度和其他的都是一样的。不过现在这三个数组的维度都一致了,但我遇到了一个索引错误:索引(384)超出了范围(0<=索引(383)在维度1中)。
1 个回答
你的代码有几个地方可以改进。
不要用
arr[a][b][c]
这样的方式来访问数组。这样做实际上是在创建一个新的 Python 对象arr[a]
,然后再从这个对象创建另一个对象arr[a][b]
,最后得到你想要的对象arr[a][b][c]
。如果你用 numpy 的元组索引arr[a, b, c]
,就可以省去这些中间的创建和销毁过程。不要在不需要的时候使用循环!与其这样
for j in xrange(len(a)) : a[j] = b[j]
你可以这样做
a[:] = b[:]
这其实就是 numpy 强大的地方,所以要好好利用它!
关于加速你的代码……你应该检查一下 imgLlab.shape
、imgRlab.shape
和 disp.shape
是否都是一样的,格式是 (h, w, 3)
。你的索引错误提示其中一个可能比较小。无论如何,为了达到你的目标,我们需要利用一下 广播 和 花式索引。好好看看这些链接,否则接下来的内容可能就不太好理解了:
rows = np.arange(h).reshape(h, 1, 1)
cols = np.arange(w).reshape(1, w, 1)
planes = np.arange(3).reshape(1, 1, 3)
data = imgLlab[rows, cols, planes] - \
imgRlab[planes, rows - disp[rows, cols, planes], planes]
# data is of shape (h, w, 3)
data = data**2
# data is of shape (h, w, 3)
data = np.sum(data, axis=-1)
# data is of shape (h, w)
data = np.sqrt(data)
# data is of shape (h, w)
如果你真的想把同一个数组复制到你的 delta
数组的三个平面上,可以这样做:
delta[...] = data.reshape(h, w, 1) # equivalent to data.reshape(-1, 1)
这只是你的第一个例子,但其他的例子在你理解了这个之后应该也很容易构建。如果有问题,随时回来问!