如何在 MATLAB 中使用 2-D 掩码索引 3-D 矩阵?

Posted

技术标签:

【中文标题】如何在 MATLAB 中使用 2-D 掩码索引 3-D 矩阵?【英文标题】:How can I index a 3-D matrix with a 2-D mask in MATLAB? 【发布时间】:2011-03-25 08:46:25 【问题描述】:

假设我有 D,一个 X×Y×Z 数据矩阵。我也有 M,一个 X-by-Y“掩蔽”矩阵。我的目标是当 M 中的 (Xi,Yi) 为假时,将 D 中的元素 (Xi,Yi,:) 设置为 NaN。

有没有办法避免循环执行此操作?我尝试使用ind2sub,但失败了:

M = logical(round(rand(3,3))); % mask
D = randn(3,3,2); % data

% try getting x,y pairs of elements to be masked
[x,y] = ind2sub(size(M),find(M == 0));
D_masked = D;
D_masked(x,y,:) = NaN; % does not work!

% do it the old-fashioned way
D_masked = D;
for iX = 1:size(M,1)
    for iY = 1:size(M,2)
        if ~M(iX,iY), D_masked(iX,iY,:) = NaN; end
    end
end

我怀疑我在这里遗漏了一些明显的东西。 (:

【问题讨论】:

【参考方案1】:

Reshape 是basically for free,您可以在此处使用它以获得有效的解决方案。将整体简化为二维问题。

sz=size(D);
D=reshape(D,[],sz(3)); %reshape to 2d
D(isnan(M(:)),:)=nan; %perform the operation on the 2d matrix
D=reshape(D,sz); %reshape back to 3d

【讨论】:

【参考方案2】:

您可以通过使用REPMAT 在第三维度上复制逻辑掩码M 来实现这一点,使其大小与D 相同。然后,索引:

D_masked = D;
D_masked(repmat(~M,[1 1 size(D,3)])) = NaN;

如果不希望复制掩码矩阵,还有另一种选择。您可以首先找到M 等于0 的一组线性索引,然后复制该组size(D,3) 次,然后将每组索引移动numel(M) 的倍数,以便它索引D 的不同部分第三个维度。我将在这里使用BSXFUN 来说明这一点:

D_masked = D;
index = bsxfun(@plus,find(~M),(0:(size(D,3)-1)).*numel(M));
D_masked(index) = NaN;

【讨论】:

啊,当然可以。对于 D 和 M 的巨大尺寸,尽管可能仍然希望不必复制它...... @Matt:由于M 是一个逻辑矩阵,它每个元素只使用 1 个字节,因此复制它不会像复制双精度矩阵那样消耗内存。事实上,M 的复制版本将仅使用 D 的总内存的 1/8。 @Matt:为了完整起见,我添加了另一个避免复制M 的解决方案。如果在一个非常大的矩阵 M 中只有几个零值,从内存使用的角度来看,这种新的解决方案可能更可取。 =) 我特别喜欢 BSXFUN 解决方案的查找线性索引。感谢您添加。【参考方案3】:

我的 Matlab 有点生疏,但我认为逻辑索引应该可以工作:

D_masked = D;
D_masked[ M ] = NaN;

(这可能可以与rhs上的条件表达式组合成一个语句......)

【讨论】:

啊,我应该把它包含在“我尝试过的东西”中:-) 如果你这样做,你只屏蔽第一个 Z 维度,所以 D(:,:,1) 将有屏蔽应用但不是 D(:,:,2)。不过感谢您的建议!

以上是关于如何在 MATLAB 中使用 2-D 掩码索引 3-D 矩阵?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MATLAB 中以 2-D 和 3-D 绘制图像 (.jpg)?

Matlab - 如何使用二值图像屏蔽 3-D 图像

带有特定掩码的Matlab imcrop

如何在 matlab 中使用“保存”命令作为可索引命令

Matlab3-D 网格中 2-D 选择的插值

如何从传递给某些 STL 算法的谓词中获取元素的索引?