如果一次重塑然后重塑回原始大小,Matlab矩阵会改变吗?

Will Matlab matrix change if reshaped once then reshaped back to the original size?

基本上,我有一个原始的128 x 128 x 3矩阵,它描述了RGB图像(128 * 128点,每个点分别是一个1x3矢量,分别包含红色,绿色和蓝色强度),我也从中选择了16个点(此点 是最简单的部分),现在我想在128 x 128 x 3矩阵与16个点之间进行成对距离计算。

但是问题在于Matlab函数," pdist2"仅采用大小为M1 x N和M2 x N的2个矩阵,而没有其他任何东西,因此我打算将128 x 128 x 3矩阵转换为(128 * 128) x 3个 稍后,在对新转换的矩阵进行一些计算之后,我需要将其转换回原始大小,以便显示图像并检查结果。 但是我不确定这些元素是否会保留在原处还是会被改组? 请帮我非常感谢!


从文档中

The data type and number of elements in B are the same as the data type and number of elements in A. The elements in B preserve their column-wise ordering from A.

如果您需要结果与原始大小相同,则只需在初始转换之前存储该大小,并在执行数据操作后将其用作reshape的输入即可。

1
2
3
4
5
6
7
8
9
10
% Store the original size
originalSize = size(data);

% Reshape it to your new 2D array
data = reshape(data, [], 3);

% Do stuff

% Reshape it back to it's original size
data = reshape(data, originalSize);

在2D版本中,元素在技术上不会与在3D矩阵中的位置相同,因为...好吧,这是2D而不是3D。但是,如果将其重塑回3D(周围没有移动元素),则元素顺序将与原始3D矩阵相同。

更新资料

您可以轻松地自己检查。

1
2
R = rand([10, 20, 3]);
isequal(R, reshape(reshape(R, [], 3), size(R)))

之所以这样做,是因为reshape实际上并不更改基础数据,而是更改其访问方式。我们可以通过使用format debug轻松查看数据存储位置。

我们还可以使用我编写的一个匿名函数来查看给定变量在内存中的存储位置。

1
2
format debug;
memoryLocation = @(x)regexp(evalc('disp(x)'), '(?<=pr\\s*=\\s*)[a-z0-9]*', 'match')

好的,让我们创建一个矩阵并检查MATLAB在内存中的存储位置

1
2
3
A = rand(10);
memoryLocation(A)
%   7fa58f2ed9c0

现在让我们重塑形状并再次检查内存位置以查看它是否在其他位置(即顺序或值已修改)

1
2
3
B = reshape(A, [], 10);
memoryLocation(B)
%   7fa58f2ed9c0

如您所见,内存位置没有改变,这意味着元素的顺序必须相同,否则MATLAB将需要在内存中进行复制。


底层数据表示以及Suever答案正确的原因:

MATLAB中的基础数组数据本质上是双精度浮点数组。在c ++中,它将是:

1
double *array_data;

MATLAB以列主格式存储数据。如果箭头有n_rows行,则元素A_{i,j}(即第i行,第j列(索引为零)将由下式给出:

1
array_data[i + j * n_rows]

调用reshape函数时,变量n_rowsn_cols等发生了变化。array_data不变。

示例(无需触摸数组数据即可调整数组大小):

1
array_data = [1, 2, 3, 4, 5, 6];

使用n_rows = 2和列主格式,这将是:

1
2
3
4
5
6
7
8
9
10
A = [1, 3, 5
     2, 4, 6]


A11 = array_data[0 + 0 * 2] = array_data[0] = 1
A21 = array_data[1 + 0 * 2] = array_data[1] = 2
A12 = array_data[0 + 1 * 2] = array_data[2] = 3
A22 = array_data[1 + 1 * 2] = array_data[3] = 4
A13 = array_data[0 + 2 * 2] = array_data[4] = 5
A23 = array_data[1 + 2 * 2] = array_data[5] = 6

使用n_rows = 3并使用相同的基础array_data,您将拥有:

1
2
3
4
5
6
7
8
9
10
A = [1, 4
     2, 5
     3, 6]

A11 = array_data[0 + 0 * 3] = array_data[0] = 1
A21 = array_data[1 + 0 * 3] = array_data[1] = 2
A31 = array_data[2 + 0 * 3] = array_data[2] = 3
A12 = array_data[0 + 1 * 3] = array_data[3] = 4
A22 = array_data[1 + 1 * 3] = array_data[4] = 5
A32 = array_data[2 + 1 * 3] = array_data[5] = 6

调整大小只是更改n_rowsn_cols等...