numpy matlab到python的转换(sub2ind和array)

w9apscun  于 2023-05-29  发布在  Matlab
关注(0)|答案(1)|浏览(123)

我正在尝试将以下matlab代码转换为pyhton:

Im = rand(961, 220)+1;
x0 = rand(961, 220)+1;
y0 = rand(961, 220)+1;

% 
[a1 b1]=size(x0);
re_x0=reshape(x0,a1*b1,1);
re_y0=reshape(y0,a1*b1,1);
eIm1=Im(sub2ind(size(Im),floor(re_x0'+1),floor(re_y0'+1)));
Im1=reshape(eIm1',size(Im));

以下是我目前为止用Python编写的脚本:

import numpy as np
Im = np.random.rand(961, 220) + 1
x0 = np.random.rand(961, 220) + 1
y0 = np.random.rand(961, 220) + 1


[a1, b1] = x0.shape
re_x0 = x0.reshape(a1 * b1, 1)
re_y0 = y0.reshape(a1 * b1, 1)

ind=np.ravel_multi_index((np.int64(np.floor(re_x0.T + 1))-1,np.int64(np.floor(re_y0.T + 1))-1),dims=Im.shape,order='F')
eIm1=Im[ind]

我得到了与matlab相同的维度和索引值。然而,对于最后一行eIm1=Im[ind]。我得到以下错误。

IndexError: index 962 is out of bounds for axis 0 with size 961

变量ind的维数为:

ind=1x211420 double ; the matrix in python  looks like this : [[962 962 962 962 962 962....]]

我如何编写eIm1=Im[ind]语法来解决错误。先谢谢你了。

qni6mghb

qni6mghb1#

有多个问题,主题令人困惑...
首先修复输入矩阵-为了测试,值应该覆盖更大的范围(特别是索引):

Im = rand(961, 220)*100; % Scale by 100 for testing
x0 = rand(961, 220)*200+1; % Scale X indices by 200 (range about [1, 202])
y0 = rand(961, 220)*900+1; % Scale Y indices by 900 (range about [1, 902])

我们最好保存输入,以便在MATLAB和Python中使用相同的输入:

if exist('input_data.mat', 'file')
    load('input_data.mat');
else
    % Create random data only if data.mat not exist
    Im = rand(961, 220)*100; % Scale by 100 for testing
    x0 = rand(961, 220)*200+1; % Scale X indices by 200 (range about [1, 202])
    y0 = rand(961, 220)*900+1; % Scale Y indices by 900 (range about [1, 902])
    save('input_data.mat', 'Im', 'x0', 'y0', '-v7'); % Save the data to be used as input to Python
end

sub2ind函数的参数顺序是yx
eIm1 = Im(sub2ind(size(Im), floor(re_x0'+1), floor(re_y0'+1)));替换为:

eIm1 = Im(sub2ind(size(Im), floor(re_y0'+1), floor(re_x0'+1)));

注意事项:
这部分只是为了遵循惯例(使事情不那么混乱)。
在Python代码中,读取input_data.mat到NumPy数组,并整形:

input_data = scipy.io.loadmat('input_data.mat')  # https://stackoverflow.com/questions/874461/read-mat-files-in-python
Im = input_data['Im']
x0 = input_data['x0']
y0 = input_data['y0']

[a1, b1] = x0.shape  # [a1, b1] = size(x0);
re_x0 = x0.reshape(a1 * b1, 1)  # re_x0 = reshape(x0, a1*b1, 1);
re_y0 = y0.reshape(a1 * b1, 1)  # re_y0 = reshape(y0, a1*b1, 1);

使用np.ravel_multi_index时,建议使用NumPy约定行优先(C样式)。
在Python中使用NumPy约定似乎是合适的,因为我们正在使用NumPy。

  • 删除order='F'
  • 使用dims=(b1, a1)-第一个维度应用X(水平)轴,第二个维度应用Y(垂直)轴。
ind = np.ravel_multi_index((np.int64(np.floor(re_x0.T + 1))-1, np.int64(np.floor(re_y0.T + 1))-1), dims=(b1, a1))

我们不能在Python中使用线性索引eIm1 = Im[ind]
我们必须将2D数组表示为“长”1D数组。
我们可以使用ravel()方法:eIm1 = Im.ravel()[ind]
由于MATLAB数组是转置的(eIm1'):Im1 = reshape(eIm1', size(Im));,我们还必须在ravel()之前转置Im

eIm1 = Im.T.ravel()[ind]

Im1 = eIm1.reshape(a1, b1)  # Reshape eIm1 to 2D array

比较Python输出和MATLAB输出:

output_data = scipy.io.loadmat('output_data.mat')
Im1_matlab = output_data['Im1']

assert np.array_equal(Im1_matlab, Im1)  # The output arrays are exactly equal

更新MATLAB代码:

if exist('input_data.mat', 'file')
    load('input_data.mat');
else
    % Create random data only if data.mat not exist
    Im = rand(961, 220)*100; % Scale by 100 for testing
    x0 = rand(961, 220)*200+1; % Scale X indices by 200 (range about [1, 202])
    y0 = rand(961, 220)*900+1; % Scale Y indices by 900 (range about [1, 902])
    save('input_data.mat', 'Im', 'x0', 'y0', '-v7'); % Save the data to be used as input to Python
end

[a1, b1] = size(x0);
re_x0 = reshape(x0, a1*b1, 1);
re_y0 = reshape(y0, a1*b1, 1);
% eIm1 = Im(sub2ind(size(Im), floor(re_x0'+1), floor(re_y0'+1)));
% The correct order in MATLAB sub2ind is: y, x
eIm1 = Im(sub2ind(size(Im), floor(re_y0'+1), floor(re_x0'+1)));
Im1 = reshape(eIm1', size(Im));

save('output_data.mat', 'Im1', '-v7'); % Save the output to be used as reference for testing in Python

Python代码更新:

import numpy as np
import scipy.io

#Im = np.random.rand(961, 220) + 1
#x0 = np.random.rand(961, 220) + 1
#y0 = np.random.rand(961, 220) + 1

# Read the data from mat file (we want to have the same data as in MATLAB).
input_data = scipy.io.loadmat('input_data.mat')  # https://stackoverflow.com/questions/874461/read-mat-files-in-python
Im = input_data['Im']
x0 = input_data['x0']
y0 = input_data['y0']

[a1, b1] = x0.shape  # [a1, b1] = size(x0);
re_x0 = x0.reshape(a1 * b1, 1)  # re_x0 = reshape(x0, a1*b1, 1);
re_y0 = y0.reshape(a1 * b1, 1)  # re_y0 = reshape(y0, a1*b1, 1);

# eIm1 = Im(sub2ind(size(Im), floor(re_y0'+1), floor(re_x0'+1)));
#ind = np.ravel_multi_index((np.int64(np.floor(re_x0.T + 1))-1, np.int64(np.floor(re_y0.T + 1))-1), dims=Im.shape, order='F')

# Use dims=(b1, a1) - the first dimension applies the X (horizontal) axis, and the second dimension applies Y (vertical) axis.
# Don't use order='F', because we want the indices in NumPy conventions row-major (C-style).
ind = np.ravel_multi_index((np.int64(np.floor(re_x0.T + 1))-1, np.int64(np.floor(re_y0.T + 1))-1), dims=(b1, a1))

# eIm1 = Im(...);
#eIm1 = Im[ind]
#eIm1 = Im.ravel()[ind]  # Represent Im as 1D array using ravel() method. The elements order is row-major (C-style).
eIm1 = Im.T.ravel()[ind]  # We also have to transpose Im for matching MATLAB eIm1'

# Im1 = reshape(eIm1', size(Im));
Im1 = eIm1.reshape(a1, b1)  # Reshape eIm1 to 2D array

# Compare the result to MATLAB output.
################################################################################
output_data = scipy.io.loadmat('output_data.mat')
Im1_matlab = output_data['Im1']

assert np.array_equal(Im1_matlab, Im1)  # The output arrays are exactly equal

相关问题