Извлечение подмножеств из большой трехмерной матрицы с использованием бинарной маски - Matlab - PullRequest
2 голосов
/ 06 января 2012

У меня большая D Матрица размера MxNxK.Учитывая двоичную маску B размера MxN, я хотел бы разбить матрицу D на две подматрицы: D0 и D1 таким образом, чтобы матрица D0 имела значения матрицы Dсвязанный с 0's в двоичной маске.То же самое верно для D1, но с использованием 1's в двоичной маске.В настоящее время я решаю эту проблему с помощью циклов, но мне интересно, есть ли более эффективный способ решить эту проблему?

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

Все предложения приветствуются; -)

Ответы [ 3 ]

1 голос
/ 06 января 2012

Итерация по измерению 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 )
1 голос
/ 06 января 2012

Вы также можете сделать это без каких-либо циклов, скопировав 2-ую двоичную маску в 3-ую маску размером с вашими данными, а затем выполнив логическую индексацию.

binmask_big = repmat(binmask, [1 1 K]);
mat_ones = matrixbig(binmask_big==1);
mat_zeros = matrixbig(binmask_big==0);
0 голосов
/ 06 января 2012

Самый эффективный способ - использовать линейное индексирование и вообще избегать циклов. Вы должны предварительно вычислить индексы единиц и нулей в маске. Должно работать следующее:

% 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)];

И вот оно у вас!

...