2012-01-06 27 views
2

我有一个大的D大小为MxNxK的矩阵。给定尺寸为M×N的二进制掩码B,我想矩阵D分成两个子矩阵:D0D1,在这样一种方式,矩阵D0具有与0's在二进制掩码相关联矩阵D的值。这同样适用于D1,但在二进制掩码中使用了1's。 目前,我正在通过使用循环解决这个问题,但我想知道是否有更有效的方法来解决这个问题?使用二进制掩码从大型3d矩阵中拉取子集 - Matlab

mat_zeros = []; 
mat_ones = []; 

for m=1:M 
    for n=1:N 

     matval = matrixbig(m,n,:); 
     matval = matval(:)'; % mapping matval to a K-dimensional vector 

     if (binmask(m,n) == 1) 
      mat_ones = [mat_ones; matval]; 
     elseif (binmask(m,n) == 0) 
      mat_zeros = [mat_zeros; matval]; 
     end 
    end 
end 

所有建议都欢迎;-)

+0

看看这个[SO问题](http://stackoverflow.com/questions/3407525/how-can-i-index-a-3-d-matrix-with-a-2- d-mask-in-matlab) – Maurits 2012-01-06 16:38:08

回答

1

K尺寸的迭代只会导致一个循环更高效的代码。请参见下面的代码较短的算法部分:

% Some data 
clear; M = 3; N = 2; K = 4; 
matrixbig = rand(M,N,K); 
binmask = round(matrixbig(:,:,1)); 

% Original algorithm 
mat_zeros = []; mat_ones = []; 
for m=1:M 
    for n=1:N 
    matval = matrixbig(m,n,:); 
    matval = matval(:)'; 

    if (binmask(m,n) == 1) 
     mat_ones = [mat_ones; matval]; 
    elseif (binmask(m,n) == 0) 
     mat_zeros = [mat_zeros; matval]; 
    end 
    end 
end 

% Shorter algorithm 
mat_zeros1 = []; mat_ones1 = []; 
mask = (binmask == 1)'; 
for k = 1:K 
    matval = matrixbig(:,:,k)'; 
    mat_ones1 = [mat_ones1, matval(mask)]; 
    mat_zeros1 = [mat_zeros1, matval(~mask)]; 
end 

% Compare results of two algorithms 
isequal(mat_ones, mat_ones1) 
isequal(mat_zeros, mat_zeros1) 
0

最有效的方法是使用线性索引和完全避免循环。您必须预先计算掩码中的1和0的索引。以下应该工作:

% You must define M,N in order for the code to work 

mat_zeros = []; 
mat_ones = []; 

indOnes=find(binmask==1); %returns linear indices 
indZeros=find(binmask==0); %returns linear indices 

mat_ones = [matrixbig(indOnes) matrixbig(indOnes+M*N) matrixbig(indOnes+2*M*N)]; 
mat_zeros = [matrixbig(indZeros) matrixbig(indZeros+M*N) matrixbig(indZeros+2*M*N)]; 

那里你有它!

1

你也可以做到这一点没有任何循环可言,通过复制2D二进制掩码成3D掩盖你的数据的大小,然后做逻辑索引。

binmask_big = repmat(binmask, [1 1 K]); 
mat_ones = matrixbig(binmask_big==1); 
mat_zeros = matrixbig(binmask_big==0); 
+0

@ Matt,谢谢,但理想情况下,我希望'mat_ones'和'mat_zeros'它们都有'K'列。遵循你的建议,我得到1列矩阵。 – Tin 2012-01-07 10:32:54