如果重塑一次然后重塑回原始大小,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" 只需要 2 个大小为 M1 x N 和 M2 x N 的矩阵,而不是其他任何东西,所以我打算转换 128 x 128 x 3 矩阵到 (128 * 128) x 3 一个。稍后,在对新转换的矩阵进行一些计算后,我需要将其转换回原始大小以显示图像并检查结果。但我不确定这些元素是否会保留在它们的位置,或者它们会被洗牌吗?请帮帮我,非常感谢!

来自documentation

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 的输入执行您对数据的操作。

% 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 矩阵相同。

更新

您可以轻松地自己检查一下。

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

为什么 这是因为 reshape 实际上并没有改变底层数据,而是改变了访问数据的方式。我们可以通过使用 format debug 查看数据的存储位置来轻松检查这一点。

我们还可以使用 查看给定变量在内存中的存储位置。

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

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

A = rand(10);
memoryLocation(A)
%   7fa58f2ed9c0

现在让我们重塑它并再次检查内存位置,看看它是否在不同的地方(即修改了顺序或值)

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

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

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

MATLAB中的底层数组数据本质上是一个双精度浮点数数组。在 C++ 中它将是:

double *array_data;

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

给出
array_data[i + j * n_rows]

当你调用reshape函数时,变量n_rowsn_cols等有什么变化....它不会 改变 array_data.

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

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

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

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,您将拥有:

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 等...