使用numpy、python和opencv 2.4遍历多维数组

1 投票
1 回答
1054 浏览
提问于 2025-04-17 13:14

最近我在这个问题上发过一个帖子,但最后我用了一种不太优雅的方法解决了它。

我有两张图片,它们是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 个回答

1

你的代码有几个地方可以改进。

  1. 不要用 arr[a][b][c] 这样的方式来访问数组。这样做实际上是在创建一个新的 Python 对象 arr[a],然后再从这个对象创建另一个对象 arr[a][b],最后得到你想要的对象 arr[a][b][c]。如果你用 numpy 的元组索引 arr[a, b, c],就可以省去这些中间的创建和销毁过程。

  2. 不要在不需要的时候使用循环!与其这样

    for j in xrange(len(a)) :
        a[j] = b[j]
    

    你可以这样做

    a[:] = b[:]
    

    这其实就是 numpy 强大的地方,所以要好好利用它!

关于加速你的代码……你应该检查一下 imgLlab.shapeimgRlab.shapedisp.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)

这只是你的第一个例子,但其他的例子在你理解了这个之后应该也很容易构建。如果有问题,随时回来问!

撰写回答