2012-01-06 31 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