简体   繁体   中英

How can I add matrices inside a cell array?

I have a (1xn) cell array A where each matrix is a 1000x1000.

Basically, I want to do A{1}+A{2}+A{3}+...+A{n}

I don't know the size of the array beforehand. So I should do a size(A) and add all the available matrices inside.

  • I want to sum all of them using a loop
  • But preferably in a vectorized way as I'll eventually add thousands of them and need the speed improvement.

How I store data into the cell array:

for k = 1:length(pcpFileNames)
    pcp{k} = imread(pcpFileNames{k}); %Read all pcp files
end

where 

pcpFileNames = 

    'PCPRATE.20110612.000000.tif'
    'PCPRATE.20110612.000500.tif'
    'PCPRATE.20110612.001000.tif'
    'PCPRATE.20110612.001500.tif'
    'PCPRATE.20110612.002000.tif'
    'PCPRATE.20110612.002500.tif'
    'PCPRATE.20110612.003000.tif'
    'PCPRATE.20110612.003500.tif'
    'PCPRATE.20110612.004000.tif'
    'PCPRATE.20110612.004500.tif'

Proposed solution not working:

pcpAccum = pcp{1};
for m = 2:numel(pcp)
    pcpAccum = pcpAccum + pcp{k};
end

This is giving me incorrect results. I checked one of the cells and it has zero value even though it should have 1.8 (example).


Working solution

%Create a multidimensional array to store the data

precip = zeros(3501,7001,length(pcpFileNames)); %Pre-allocating an array

for k = 1:length(precipFileNames)
    precip(:,:,k) = imread(precipFileNames{k}); %Read all files
end

pcpAccum = sum(pcp,3); 

To add them in a vectorized way:

B = sum(cat(3,A{:}),3);

However, adding a lot of matrices like above way is a very bad idea if your matrices are already big. Your 2D matrices are already in memory; to create the 3D matrix that will vectorize your addition will consume once again that amount of memory, but now in a contiguous memory area . Due to memory fragmentation is quite likely that you'll have the total amount of memory to do the vectorized sum, but not in a contiguous area of memory ; so your program will fail needlessly.

What I would recommend in this case is a nice well-behaved loop:

B = A{1};
for k = 2:numel(A)
        B = B + A{k};
end;

However, the loop has its own issues, and the speed is not one. The thing is that accumulating in an ever growing manner might give you precision errors (for floating point types) or integer overflows (for integer types).

To overcome the overflow errors caused by an integer type returned by imread , convert the data to a wider type ( double is the best bet):

B = double(A{1});
for k = 2:numel(A)
        B = B + double(A{k});
end;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM