将矢量化的Matlab代码传输到python,numpy

时间:2014-06-26 20:50:44

标签: arrays matlab python-2.7 numpy indexing

我正在将我的matlab代码传输到python。有很多东西我试图在python和numpy中找到替换

Matlab代码:

    [m,n]=size(Image);

    canvas=zeros(m,n);

    U_res_sel=squeeze(loading);
    [s1,s2]=size(U_res_sel);

    if mod(s1,2)==0
        dy=s1/2-1;
    else
        dy=(s1-1)/2;
    end
    if mod(s2,2)==0
        dx=s2/2-1;
    else
        dx=(s2-1)/2;
    end

    xmin=dx+1;
    ymin=dy+1;
    xmax=n-(s2-dx-1);
    ymax=m-(s1-dy-1);

    [x,y]=meshgrid(xmin:xmax,ymin:ymax);

    ind=sub2ind([m,n],y(:),x(:));

    nps=repmat(((-dx+(0:s2-1))*m-dy),s1,1)+repmat((0:(s1-1)).',1,s2);

    ind=repmat(ind,1,numel(nps))+repmat(nps(:).',numel(ind),1);

    A=(Image(ind)-repmat(mean(Image(ind),2),1,numel(nps)));

    B=repmat((U_res_sel(:)-mean(U_res_sel(:))).',size(ind,1),1);

    canvas(ymin:ymax,xmin:xmax)=reshape(sum(A.*B,2)./sqrt(sum((A.^2),2).*sum((B.^2),2)),ymax-ymin+1,[]);

    canvas = canvas(y1+1:z1+y1+1,y2+1:z2+y2+1);

我想我会逐行解释问题的发生。

我正在使用

将numpy导入为np

用于numpy函数

1

变量工作正常,直到我到达python中的meshgrid行。

    [x,y] = np.mgrid[xmin:xmax,ymin:ymax]
matlab中的

x使用测试数据的大小为517,517 python中的x的大小有516乘516所以我用

更改了代码的python部分
    xmax=n-(s2-dx-1) + 1
    ymax=m-(s1-dy-1) + 1

    [y,x] = np.mgrid[xmin:xmax,ymin:ymax]

使其与matlab代码具有相同的数据集。但我不确定索引是否合理。如果我在matlab中使用完全相同的矩阵到numpy数组它们是等价的吗?

2

下一个matlab系列让我弄清楚。

    ind=sub2ind([m,n],y(:),x(:));

表示x(:)和y(:​​)我正在使用

    x = np.reshape(x,(x.size,1))
    y = np.reshape(y,(y.size,1))
    x = np.int64(x)
    y = np.int64(y)

我在python中使用的sub2ind函数

    ind = np.ravel_multi_index((y,x), dims=(m,n) )

但这里是数字搞乱的地方。

在matlab中的

我得到一个范围为3723到278760的列向量,用于某个数据集 并为相同的数据集 在python中,我得到一个4264到279292的列向量,其间有不同的步进。

它们两者的大小相同(267289,1)。

3

这条线我在matlab和python中运行良好我只是把它放在这里所以我可以简洁自己。

MATLAB:

    nps=repmat(((-dx+(0:s2-1))*m-dy),s1,1)+repmat((0:(s1-1)).',1,s2);

蟒:

    dtx = (-dx + np.arange(0,s2,1))
    dtx_2 = np.arange(0,s1,1)
    dtx_2 = np.reshape(dtx_2,(dtx_2.size,1))

    nps = np.tile(   dtx*m-dy,(s1,1)  ) + np.tile(   dtx_2  ,(1,s2)  )

(4)。

for matlab中的行

    ind=repmat(ind,1,numel(nps))+repmat(nps(:).',numel(ind),1);

在python中我正在尝试

    a = np.tile(ind,(1,nps.size))
    b = np.tile( np.transpose(dtind) , (ind.size,1) )
    ind = a + b

我把它分成a和b,使其更具可读性。

但这并没有真正按预期工作。

(5)。

我不确定如何在python中通过索引访问变量。

在matlab中我可以做Image(ind),但是现在我的代码在python中没用了,因为我找不到替代方案吗?

如果您尝试运行matlab代码,请注意,如果您在大数据集上运行它,它将导致您的计算机和matlab冻结并崩溃而不会发出警告。我通过将代码放在一个包装器中来解决这种情况,该包装器索引数据的较小部分以获得防止内存溢出的最终大图像。

我希望我的代码混乱得足够清楚。这段代码在matlab中运行得很好,但是matlab在我的项目基础上非常糟糕,主要是因为我无法将代码提供给其他人。

编辑:

这个函数是一个矢量化程序,它基本上可以:(这是伪代码,所以索引可能不是我的头脑)

此段中也没有填充。我使用的加载变量是高斯矩阵或Lapacian,其范围可以从6x6到64x64。它可以是任何尺寸,只要它小于图像。

    correlation_coeficcient_surface = function(Image,loading)
    [m,n] = size(image)
    [u1,u2] = size(loading)
    canvas = zeros(size(image))
    for yii = 1:n
         for xii = 1:m
              image_segment = Image(yii-floor(u1/2):yii+ceil(u1/2),xii-floor(u2/2):xii+ceil(u2/2));
              if(size(image_segment) == size(loading)
                  canvas(yii-floor(u1/2):yii+ceil(u1/2),xii-floor(u2/2):xii+ceil(u2/2)) = corr2(Image_segment,loading);
              end
          end
     end


    end

它必须被矢量化,因为迭代每个元素使得在大图像上花费很长时间。

修改编辑:

这是我的过滤器实际上做的事情。

这是一个示例图像

http://i.imgur.com/o9kV3nK.png

这是我用来与

关联的示例加载形状

http://i.imgur.com/oYW3k2K.png

这是在我的matlab过滤器完成之后,图像没有对齐,我只是通过裁剪示例来向您展示它的形状。

http://i.imgur.com/aa4ljue.png

这是scipy.signal.convolve2d,它做了我不想要的事情。

http://i.imgur.com/vJhXMam.png

3 个答案:

答案 0 :(得分:2)

我认为你应该放慢一点,阅读一些关于python数组基础知识的资料,比如索引和广播。首先,我在http://www.sam.math.ethz.ch/~raoulb/teaching/PythonTutorial/intro_numpy.html阅读了基础教程。另外http://mathesaurus.sourceforge.net/matlab-numpy.html包含一个表,其中包含某些numpy和matlab操作之间的对应关系。但是,总的来说,我会保持开放的心态,并意识到matlab方式通常不是最好的方式。

我没有直接回答你的所有问题,但以下是一些想法。

  1. Python索引是零索引的。因此,matlab arr(1:100)与numpy arr[0:100]相同。
  2. 您可以使用逻辑数组或索引数组索引numpy数组,就像在matlab
  3. 中一样
  4. 通常,repmat的功能由智能广播处理,不需要手动调用tile。例如,下面的代码生成一个随机的100x100数组,计算行平均值,并从行中减去行均值(例如,将数据居中):

    arr = np.random.rand(100,100)
    mu  = arr.mean(axis=1)
    centered = arr - mu[:,None]
    

    mu[:,None]数组的大小(100,1),而numpy足够聪明,以及#34;广播"它的大小(100,100)来计算centered。继续这个例子,mu[:,None,None]的大小(100,1,1)。

  5. Matlab' size(arr)与numpy' arr.shape相同。

  6. 祝你好运!

    编辑:例如,您可以更简洁地完成#3:

    nps = (-dx+np.arange(s2)*m -du)[None,:] + np.arange(s1)[:,None]
    

    和#4:

    ind=  ind[:, None] + nps.ravel()[None, :]  
    

答案 1 :(得分:2)

关于xy - 值的顺序不同,如果您尝试展平它们,您会看到:

x(:)'
1 1 ... 2 2 ....

x.flatten()
array([ 1,  2,  ... 10,  1,  2,...])

那就是MATLAB数组的排列方式类似于'F'numpy数组,而不是默认的'C'。


对于小尺寸,我可以将octave和numpy与:

匹配
"""
octave:47> [x,y]=meshgrid(1:3,3:4)
x =
   1   2   3
   1   2   3
y =
   3   3   3
   4   4   4
octave:48> ind=sub2ind([5,5],y,x)
    3    8   13
    4    9   14
"""
Y,X=np.mgrid[2:4,0:3]
"""
array([[2, 2, 2],
       [3, 3, 3]])
array([[0, 1, 2],
       [0, 1, 2]])
"""
ind = np.ravel_multi_index((X,Y),(5,5))
# np.ravel_multi_index((Y,X),(5,5),order='F')
"""
array([[ 2,  7, 12],
       [ 3,  8, 13]])

“”“

我对Image(ind)问题感到困惑。 Image是[m,n]数组,对吧?

答案 2 :(得分:1)

除了使用我的其他答案中的提示从头开始翻译代码之外,这看起来像卷积,你可能只使用convolve2d(这里没有填充):

scipy.signal.convolve2d(Image, loading, mode='full', fillvalue=0.0)

如果你想做一些比零填充更有趣的事情,请参见http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve2d.html

修改:有关卷积的详情,请参阅2D Convolution in Python similar to Matlab's conv2

编辑2:以下代码应计算滑动窗口上的局部相关系数。它应该正确处理边界。

from scipy.signal import correlate2d
import numpy as np

# Generate random image
Image = np.random.rand(100,100)

# make kernel
x = np.arange(-10,11)
loading = np.exp( -(x[:,None]**2 + x[None,:]**2 )/10)


Image = np.tile(loading, (10,10))
m,n = loading.shape

oneskernel = np.ones(loading.shape)

# get number of points within each box of the sliding window
num = correlate2d(np.ones(Image.shape), oneskernel, mode='same')

# get mean over sliding window
Image_mu = correlate2d(Image, oneskernel, mode='same')/num

# Get sig of sliding window
Image_sig = np.sqrt(correlate2d((Image - Image_mu)**2,
                        oneskernel, mode='same')
                        / num)

loading_mu  =loading.mean() # mean of kernel
loading_sig = loading.std() # sig  of kenrel


# calculate sliding corrcoeff
C = correlate2d(( Image-Image_mu) / Image_sig , (loading -loading_mu)/loading_sig, mode='same') / num