Using cellfun
, how do I apply a function to all the cells created by the mat2cell
function? My function is defined in another file, here it is referred to by myFunc
. This function takes two arguments, which should be a cell and an integer.
e.g. function H = myFunc(img,Q)
My code is as follows:
% Split into grid and process each cell
width = size(img,2) % get image width
height = size(img,1) % get image height
depth = size(img,3) % get depth
C = mat2cell(img,[height/2 height/2],[width/2 width/2],[depth/2 depth/2]); % divides image into sections
F = cellfun(@myFunc,C);
save(fout,'F');
The issue is of course with the line F = cellfun(@myFunc,C);
. How do I pass the cells and a chosen integer e.g. 4 into myFunc
for each cell?
Many thanks.
Description. A = cellfun( func , C ) applies the function func to the contents of each cell of cell array C , one cell at a time. cellfun then concatenates the outputs from func into the output array A , so that for the i th element of C , A(i) = func(C{i}) .
C = cell( n ) returns an n -by- n cell array of empty matrices. C = cell( sz1,...,szN ) returns a sz1 -by-... -by- szN cell array of empty matrices where sz1,...,szN indicate the size of each dimension. For example, cell(2,3) returns a 2-by-3 cell array.
A = cell2mat( C ) converts a cell array into an ordinary array. The elements of the cell array must all contain the same data type, and the resulting array is of that data type. The contents of C must support concatenation into an N-dimensional rectangle. Otherwise, the results are undefined.
Recently came across this problem, and noticed that while Octave has implicit cell expansion of parameters in cellfun, Matlab doesn't. Calling an anonymous function has more overhead than calling the function directly (although Matlab is not nearly as bad as Octave in that regard) so I found passing the parameter as a cell array to be a bit faster, shown here with a simple example:
abc = {magic(2), magic(3), magic(4)}
abc =
3×1 cell array
{2×2 double}
{3×3 double}
{4×4 double}
def = cellfun (@(x) sum(x,2), abc, "UniformOutput", false) %anonymous function method
def =
3×1 cell array
{2×1 double}
{3×1 double}
{4×1 double}
def{:}
ans =
4
6
ans =
15
15
15
ans =
34
34
34
34
expanding the parameter into a cell array and passing it as another input produces the same correct output:
def = cellfun (@sum, abc, num2cell(2*ones(size(abc))), "UniformOutput", false) % cell expansion method
def =
3×1 cell array
{2×1 double}
{3×1 double}
{4×1 double}
def{:}
ans =
4
6
ans =
15
15
15
ans =
34
34
34
34
a quick tic/toc check shows this to be a bit faster in Matlab 2021a:
tic;
for idx = 1:100000
cellfun(@(x) sum(x,2), abc,"UniformOutput",false);
end
toc
Elapsed time is 4.017116 seconds.
tic,
for idx = 1:100000
cellfun(@sum, abc, num2cell(2*ones(size(abc))),"UniformOutput",false);
end
toc
Elapsed time is 1.217712 seconds
I haven't tried this with non-simple parameters, but repmat could do the same for, say, string inputs, but repmat seems to add quite a bit back to the overhead:
tic
for idx = 1:100000
cellfun(@sum, abc, repmat({2}, size(abc)),"UniformOutput",false);
end
toc
Elapsed time is 4.367002 seconds.
So perhaps there's a better way to expand those. Take note that this is a very simple test case with a small array, and that this time savings may not hold true as things scale up, or as you add multiple parameters. Also, you are multiplying the memory requirement for each parameter you do this with, as each is expanded to the size of the input array.
A quick test shows the same time savings hold true with a custom myfunc
as with a matlab function like sum
.
Well, simply define a new anonymous function as @(x) myFunc(x,4)
and use it this way:
F = cellfun(@(x) myFunc(x,4), C)
By using an anonymous function:
F = cellfun(@(Q) myFunc(Q,4),C);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With