Matlab/Octave: 不用eval怎么写n维补零算法
Matlab/Octave: how to write n-dimensional zero padding algorithm without eval
我想编写一个 "syntactical sugar" Octave 或 Matlab 零填充函数,用户向其发送一个 n 维对象和一个包含 <= n 个条目的向量。该向量包含对象的新的、相等或更大的维度,并且对象被零填充以匹配这些维度。任何未指定的尺寸均保持不变。一个预期的用途是,例如,给定 3d 医学图像体积的 5d 块 X,我可以调用
y = simplepad(X, [128 128 128]);
因此将前三个维度填充为 2 的幂以进行小波分析(实际上我使用单独的函数 nextpwr2 来查找这些维度),同时保留其他维度。
我绞尽脑汁想如何写这个方法来避免可怕的评估,但至今找不到方法。谁能提出解决方案?这或多或少是我所拥有的:
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
据我了解,您只想将一些动态参数传递给函数。
您可以通过将这些参数转换为单元格并使用传递的单元格内容调用您的函数来完成此操作。因此,您的函数将如下所示:
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
这是一个应该可以处理所有小问题的解决方案:
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
我想编写一个 "syntactical sugar" Octave 或 Matlab 零填充函数,用户向其发送一个 n 维对象和一个包含 <= n 个条目的向量。该向量包含对象的新的、相等或更大的维度,并且对象被零填充以匹配这些维度。任何未指定的尺寸均保持不变。一个预期的用途是,例如,给定 3d 医学图像体积的 5d 块 X,我可以调用
y = simplepad(X, [128 128 128]);
因此将前三个维度填充为 2 的幂以进行小波分析(实际上我使用单独的函数 nextpwr2 来查找这些维度),同时保留其他维度。
我绞尽脑汁想如何写这个方法来避免可怕的评估,但至今找不到方法。谁能提出解决方案?这或多或少是我所拥有的:
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
据我了解,您只想将一些动态参数传递给函数。 您可以通过将这些参数转换为单元格并使用传递的单元格内容调用您的函数来完成此操作。因此,您的函数将如下所示:
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
这是一个应该可以处理所有小问题的解决方案:
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