2016-12-22 8 views
3

Я хотел бы написать «синтаксический сахар» Octave или Matlab zero-padding, на которые пользователь отправляет n-мерный объект и вектор < = n записей. Вектор содержит новые, равные или большие размеры для объекта, а объект имеет нулевое значение для соответствия этим измерениям. Любые размеры, не указанные, остаются в силе. Один ожидается, использование, учитывая, например, 5d блок-Х 3d объемов медицинских изображений, можно назватьMatlab/Octave: как написать n-мерный алгоритм нулевого заполнения без eval

y = simplepad(X, [128 128 128]); 

и, таким образом площадку первые три размеры по степени двух для вейвлет-анализа (на самом деле я использую отдельный function nextpwr2, чтобы найти эти размеры), оставив остальные.

Я ломал голову над тем, как написать этот метод, избегая страшного eval, но до сих пор не нашел пути. Может ли кто-нибудь предложить решение? Вот более или менее то, что у меня есть:

function y = simplepad(x, pad) 
szx = size(x); 
n_pad = numel(pad); 
szy = [pad szx(n_pad+1:end)]; 
y = zeros(szy); 
indices_string = '('; 
for n = 1:numel(szx) 
    indices_string = [indices_string, '1:', num2str(szx(n))]; 
    if n < numel(szx) 
     indices_string = [indices_string, ',']; 
    else 
     indices_string = [indices_string, ')']; 
    end 
end 
command = ['y',indices_string,'=x;']; 
eval(command); 
end 

ответ

2

Как я понимаю, вы хотите просто передать некоторые динамические аргументы для работы. Вы можете сделать это, преобразовывая эти аргументы в ячейку и вызывая свою функцию с передачей содержимого ячейки. Таким образом, ваша функция будет выглядеть следующим образом:

function y = simplepad(x, pad) 
    szx = size(x); 
    n_pad = numel(pad); 
    szy = [pad szx(n_pad+1:end)]; 
    y = x; 
    szyc = num2cell(szy); 
    y(szyc{:}) = 0; % warning: assume x array only grows 
end 
+0

Очень приятно. Мне пришлось перечитать это несколько раз. :) – beaker

+0

да, последняя строка просто устанавливает последний элемент n-dim-массива в ноль. –

+2

Одна маленькая проблема: если размеры уже равны «pad», вы замените существующее значение на ноль. – gnovice

4

Вот решение, которое должно обрабатывать все маленькие случаи угловыми:

function A = simplepad(A, pad) 

    % Add singleton dimensions (i.e. ones) to the ends of the old size of A 
    % or pad as needed so they can be compared directly to one another: 

    oldSize = size(A); 
    dimChange = numel(pad)-numel(oldSize); 
    oldSize = [oldSize ones(1, dimChange)]; 
    pad = [pad ones(1, -dimChange)]; 

    % If all of the sizes in pad are less than or equal to the sizes in 
    % oldSize, there is no padding done: 

    if all(pad <= oldSize) 
    return 
    end 

    % Use implicit zero expansion to pad: 

    pad = num2cell(pad); 
    A(pad{:}) = 0; 

end 

И несколько тестов:

>> M = magic(3) 
M = 
    8  1  6 
    3  5  7 
    4  9  2 
>> simplepad(M, [1 1]) % No change, since the all values are smaller 
ans = 
    8  1  6 
    3  5  7 
    4  9  2 
>> simplepad(M, [1 4]) % Ignore the 1, pad the rows 
ans = 
    8  1  6  0 
    3  5  7  0 
    4  9  2  0 
>> simplepad(M, [4 4]) % Pad rows and columns 
ans = 
    8  1  6  0 
    3  5  7  0 
    4  9  2  0 
    0  0  0  0 
>> simplepad(M, [4 4 2]) % Pad rows and columns and add a third dimension 
ans(:,:,1) = 
    8  1  6  0 
    3  5  7  0 
    4  9  2  0 
    0  0  0  0 
ans(:,:,2) = 
    0  0  0  0 
    0  0  0  0 
    0  0  0  0 
    0  0  0  0