python - 通过 scipy.io.loadmat 将 matlab 3D 矩阵传输到 python 3D 数组会出错

标签 python matlab numpy matrix multidimensional-array

我正在考虑 Matlab 矩阵和 Python numpy 数组的问题。我有一个医学图像处理代码,给定一个 3D 数组作为输入(512x512 图像,80 个切片 -> 大小(图像)= (512,512,80)。 输入最初由 NifTI 结构给出。 当我在 matlab 中加载 Nii 文件时,我得到的大小为 512x512x80。 当我在 python 中加载 Nii 文件时,我得到 80x512x512 大小(带有 array.shape)

通过尝试测试矩阵,我发现: Matlabs 大小语法:(x = 行,y = 列,z = 第三维切片) 大小的 python 语法:(z = 第三个维度的切片,x = 行,y = 列)

现在我必须测试另一个数据,不是以 nii 文件形式给出,而是保存在 mat 文件中。 使用 Scipy 的 loadmat,我可以轻松地将矩阵加载到我的 python 程序中。 但是:现在,Python 中的矩阵大小现在也是 (512,512,80),以下代码现在在第 3 维中采用 512 个切片、512 行和 80 列(而不是 80 个切片、512x512 图像)。 我希望这是可以理解的解释...

一个最小的例子:

我通过以下方式在 Matlab 中加载矩阵:

a = 1:12;
a = reshape(a, [1 3 4])

a(:,:,1) =

     1     2     3


a(:,:,2) =

     4     5     6


a(:,:,3) =

     7     8     9


a(:,:,4) =

    10    11    12

size(a)

ans =

     1     3     4

save a.mat a

我将 a 保存在 mat 文件中。 现在我继续我的 python 代码,使用 import scipy.io as spio 我可以访问 matfile:

mat = spio.loadmat('a.mat')
a = mat['a']
print(a)

   Output:
[[[1 4 7 10]

  [2 5 8 11]

  [3 6 9 12]]]

print(a.shape)

   Output:
(1,3,4)

但这是错误的!它在 3 维中没有 4 个切片,而只是一个 3x4 矩阵。 我应该是:

[[[ 1 2 3]]

 [[ 4 5 6]]

 [[ 7 8 9]]

 [[10 11 12]]]

with shape (4,1,3)

那么,如何以准确的 python 顺序加载 Matlab-Matrices,以便我的代码采用正确的切片? 此外,我有兴趣再次将生成的 python 数组传输回 matlab 矩阵。

提前非常感谢!

最佳答案

你误会了matlab的可视化:

a(:,:,1) =

     1     2     3

是否表示a的最后一个轴包含1 2 3,它表示第二个的第一个元素组成的组轴是1 2 3。 Python 只是向您显示完整的数组,matlab 向您显示该数组的(我将第二个轴的列称为第二个轴,假设我们忽略第一个轴,因为第一个轴是空的)。

您可以通过在 Python 中键入来检查 matlab 和 python 加载的数组是否等效:

>>> a[:, :, 0]
array([[1, 2, 3]], dtype=uint8)

它给出的结果与 matlab 的可视化结果相同。

Python 和 matlab 只是可视化 3 维数组的方式不同。


请注意,matlab 是按 Fortran 顺序排列的,这意味着数组中首先是列,然后是行。因此,

matlab> reshape(1:6, [2, 3])
ans =

     1     3     5
     2     4     6

这次,由于矩阵只有 2 列,因此可视化效果符合您的预期。如果你在 python 中加载该矩阵,它也会被正确加载(python 足够智能,可以使用 Fortran 排序加载 numpy 数组)。但是,请注意,当您尝试在 python 中创建等效矩阵时,结果非常不同:

python> np.arange(1,7).reshape(2, 3)
array([[1, 2, 3],
       [4, 5, 6]])

顺序不同。在 numpy 中,数组默认是 C 顺序的。


最后,使用任何最新的 numpy/scipy 版本,您应该能够从 matlab 导入/导出矩阵而无需任何修改。

matlab> a = rand(512, 512, 10);
matlab> save /tmp/a.mat a

然后在python中加载它:

python> a = spio.loadmat('/tmp/a.mat')['a']
python> a.shape
(512, 512, 10)

矩阵是相同的。因此,matlab -> python 转换没有任何问题。您似乎只是想要一个转置版本以便在 python 中使用它。


如果你想要一个pythonic (10, 512, 512)数组,你只需转置它:

python> a = np.ascontiguousarray(a.T)

如果您只想转置第二个和最后一个轴(如您的示例中所示),您可以使用 swapaxes 来实现:

python> a = np.ascontiguousarray(np.swapaxes(a, 1, 2))

请注意,ascontigiousarray 会将数组(如果需要)复制到 C 顺序连续内存块。更有效地进行进一步的 numpy 处理例程。


最后,我们来看一个带有虚拟样本a矩阵的示例:

>>> np.swapaxes(a, 1, 2)
array([[[ 1,  2,  3],
        [ 4,  5,  6],
        [ 7,  8,  9],
        [10, 11, 12]]], dtype=uint8)

我仍然会用 np.ascontigouslyarray 包装它,以确保数据被复制到新的内存块!

关于python - 通过 scipy.io.loadmat 将 matlab 3D 矩阵传输到 python 3D 数组会出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37117779/

相关文章:

python - 在 wxpython 中选择多个 TextCtrl 上的文本

python - 究竟什么是序列?

Python:找不到 '__main__' 模块

python - 减少行梯队表单脚本在特定情况下不起作用

python - 使用 Tqdm 在下载文件时添加进度条

matlab - 如何将 Photoshop 滤镜和 Action 复制到 MATLAB 中?

image - 如何在不更改 Matlab colorbar 中的值的情况下反转图片的颜色

matlab - `A(A == -Inf) = -realmax;`的含义

python - 如何从包含杂散回车符和换行符的文本文件加载 numpy 数组?

python numpy argmax到多维数组中的最大值