尽管在线有很多例子,但我无法让我的MATLAB repmat等效于python

时间:2014-03-04 22:03:44

标签: arrays matlab python-2.7 numpy tile

我正在尝试做一些numpy矩阵数学,因为我需要从MATLAB复制repmat函数。我知道网上有一千个例子,但我似乎无法让他们中的任何一个工作。

以下是我尝试运行的代码:

def getDMap(image, mapSize):
    newSize = (float(mapSize[0]) / float(image.shape[1]), float(mapSize[1]) / float(image.shape[0]))
    sm = cv.resize(image, (0,0), fx=newSize[0], fy=newSize[1])
    for j in range(0, sm.shape[1]):
        for i in range(0, sm.shape[0]):
            dmap = sm[:,:,:]-np.array([np.tile(sm[j,i,:], (len(sm[0]), len(sm[1]))) for k in xrange(len(sm[2]))])
    return dmap 

函数getDMap(image,mapSize)需要一个OpenCV2 HSV图像作为其图像参数,这是一个具有3维维度的numpy数组:[:,:,:]。它还期望一个带有2个元素的元组作为其 imSize 参数,当然要确保传递参数的函数考虑到在numpy数组中行和列交换(:x,y,:y,x)。

然后

newSize 包含一个元组,其中包含用于将输入图像调整为特定比例的分数, sm 成为输入图像的调整大小版本。一切正常。

这是我的目标:

以下一行:

np.array([np.tile(sm[i,j,:], (len(sm[0]), len(sm[1]))) for k in xrange(len(sm[2]))])

应该等效于MATLAB表达式:

repmat(sm(j,i,:),[size(sm,1) size(sm,2)])

这是我的问题:

测试一下,尺寸 800x479x3 的OpenCV2图像作为图像参数传递,(64,48)(一个元组)作为 imSize 参数传递。 但是在测试时,我得到以下 ValueError:

  

dmap = sm [:,:,]: - np.array([np.tile(sm [i,j,:],(len(sm [0]),   len(sm [1])))for x in xrange(len(sm [2]))])
  ValueError:无法与操作数一起广播   形状(48,64,3)(64,64,192)

所以似乎数组维度不匹配,numpy有问题。但我的问题是什么?我该如何使用呢?

2 个答案:

答案 0 :(得分:2)

len(sm[0])len(sm[1])不是sm的第一维和第二维的大小。它们是sm的第一行和第二行的长度,并且都应返回相同的值。您可能希望将它们替换为sm.shape[0]sm.shape[1],它们等同于您的Matlab代码,但我不确定它是否会像您期望的那样工作。

答案 1 :(得分:2)

这两个计算匹配:

octave:26> sm=reshape(1:12,2,2,3)
octave:27> x=repmat(sm(1,2,:),[size(sm,1) size(sm,2)])
octave:28> x(:,:,2)
   7   7
   7   7


In [45]: sm=np.arange(1,13).reshape(2,2,3,order='F')
In [46]: x=np.tile(sm[0,1,:],[sm.shape[0],sm.shape[1],1])
In [47]: x[:,:,1]
Out[47]: 
array([[7, 7],
       [7, 7]])

这运行:

 sm[:,:,:]-np.array([np.tile(sm[0,1,:], (2,2,1)) for k in xrange(3)])

但它产生一个(3,2,2,3)数组,在第一维上复制。我不认为你想要k循环。

意图是什么?

 for i in ...:
     for j in ...:
         data = ...

您只会获得上次迭代的结果。你想要data += ...吗?如果是这样,这可能有效(对于(N,M,K)形状sm

np.sum(np.array([sm-np.tile(sm[i,j,:], (N,M,1)) for i in xrange(N) for j in xrange(M)]),axis=0)

z = np.array([np.tile(sm[i,j,:], (N,M,1)) for i in xrange(N) for j in xrange(M)]),axis=0)
np.sum(sm - z, axis=0)  # let numpy broadcast sm

实际上我甚至不需要瓷砖。让广播做这项工作:

 np.sum(np.array([sm-sm[i,j,:] for i in xrange(N) for j in xrange(M)]),axis=0)

我可以用repeat摆脱循环。

sm1 = sm.reshape(N*M,L)  # combine 1st 2 dim to simplify repeat
z1 = np.repeat(sm1, N*M, axis=0).reshape(N*M,N*M,L)
x1 = np.sum(sm1 - z1, axis=0).reshape(N,M,L)

我也可以将广播应用到最后一个案例

x4 = np.sum(sm1-sm1[:,None,:], 0).reshape(N,M,L)
# = np.sum(sm1[None,:,:]-sm1[:,None,:], 0).reshape(N,M,L)

使用sm我必须扩展(和求和)2维:

x5 = np.sum(np.sum(sm[None,:,None,:,:]-sm[:,None,:,None,:],0),1)