在MatLab中对二进制矩阵进行修剪

6
我有一个二进制矩阵,像这样:
0 0 0 0 0 0
0 0 0 1 0 0
0 1 0 0 0 0
0 0 1 0 1 0
0 0 0 1 0 0
0 0 0 0 0 0

我想要裁剪这个矩阵(换句话说,去除边界处的零),让它变成像这样:
0 0 1 0
1 0 0 0
0 1 0 1
0 0 1 0

怎样用“Matlab”的方法解决这个问题?也就是不使用传统的循环和条件语句
更明确地说,矩阵应该缩小到从第一列开始至少有一个1的列,直到最后一列具有相同条件,包括在内。任何超出此范围的列都应被删除。行也适用同样的规则。
谢谢。

你的输入矩阵是否总是有一圈 0 的边界,还是只想修剪所有为 0 的边缘? - High Performance Mark
只返回所有边都是“0”的边。 - Ahmed Khalaf
1
重复的问题:如何从向量中去除前导和尾随的零,使用 MATLAB? - Junuxx
1
@Junuxx 这是一个二维矩阵,所以它不是一个完全重复的副本。 - shoelzer
@shoelzer:你只需要将答案应用于两个轴。是的,有一些差异,但它们非常微不足道。 - Junuxx
显示剩余2条评论
3个回答

9
如果您的数据以矩阵M形式存在...
x = find(any(M,2),1,'first'):find(any(M,2),1,'last');
y = find(any(M),1,'first'):find(any(M),1,'last');
M(x, y)

或者,如果您知道每行/列除了边缘都会有一个1:

M(any(M,2), any(M))

如果中间有一行/列全部为零,这个程序是否按预期工作? - Junuxx
如果矩阵在中心位置有额外的零列或行,这种方法会出现问题。 - Danil Asotsky
@Junuxx 很好的发现。我自己也看到了并在你评论后立即修复了它。 - shoelzer
+1 对于“任何”解决方案。如果假设成立,它非常优雅。但我仍然认为这个问题是重复的 :p - Junuxx
不错。好的是它也可以写成匿名函数: trim_mat = @(M) M(find(any(M,2),1,'first'):find(any(M,2),1,'last'), find(any(M),1,'first'):find(any(M),1,'last')); - p8me

1

扩展到更高的维度:

假设要修剪一个三维矩阵,这更加直观简单:

M=rand(3,3,3); % generating a random 3D matrix
M(2,:,:)=0; % just to make a check if it works in extreme case of having zeros in the         middle

padded = padarray(M,[2 2 2]); % making some zero boundaries

[r,c,v]=ind2sub(size(padded),find(padded));

recoveredM=padded(min(r):max(r),min(c):max(c),min(v):max(v));

check=M==recoveredM  % checking to see if M is successfully recovered 

0
你可以利用 find 函数返回行和列索引的特性:
[r1, c1] = find(x, 1, 'first')
[r2, c2] = find(x, 1, 'last')
x(r1:r2, c1:c2)

1
这样做不行,因为findx视为线性数组,然后转换为行/列索引。它在类似[1 0 0; 1 1 0; 1 0 0]的矩阵上会出错。 - shoelzer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接