2016-02-17 3 views
0

У меня есть массив (1xn) ячеек A, где каждая матрица 1000x1000.Как добавить матрицы внутри массива ячеек?

В принципе, я хочу сделать {1} + A {2} + A {3} + ... + A {N}

Я не знаю размер массива заранее. Поэтому я должен сделать размер (A) и добавить все доступные матрицы внутри.

  • Я хочу суммировать все из них с помощью цикла
  • Но предпочтительно в векторизованном, как я в конце концов, добавить тысячи из них и нуждается в улучшении скорости.

Как хранить данные в массив ячеек:

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' 

Предлагаемое решение не работает:

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

Это дает мне неправильные результаты. Я проверил одну из ячеек, и она имеет нулевое значение, хотя оно должно иметь 1,8 (пример).


Рабочий раствор

%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); 
+0

Если матрицы одинакового размера нет необходимо использовать массив ячеек. – excaza

+0

Каков рекомендуемый способ его хранения? В основном, я использую функцию imread для хранения одинаковых файлов tif в массиве ячеек ... – maximusdooku

+1

Матрицы могут иметь более двух измерений: 'A (:,:, n)'. – excaza

ответ

1

Чтобы добавить их в векторизованного образом:

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

Однако, добавляя много матриц, как выше способ является очень плохая идея если ваши матрицы уже большие. Ваши 2D-матрицы уже находятся в памяти; для создания 3D-матрицы, которая будет векторизовать ваше добавление, будет потреблять еще раз этот объем памяти, но теперь в области смежных областей памяти. Из-за фрагментации памяти вполне вероятно, что у вас будет всего объем памяти для выполнения векторизованной суммы, но не в смежной области памяти; поэтому ваша программа будет неудачной.

То, что я бы рекомендовал в этом случае хороший хорошо себя цикл:

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

Однако, цикл имеет свои собственные проблемы, а скорость не один. Дело в том, что накопление в постоянно растущей манере может привести к ошибкам точности (для типов с плавающей запятой) или целых переполнений (для целых типов).

Чтобы преодолеть ошибки переполнения, вызванные целочисленного типа возвращаемого imread, не конвертировать данные в более широком типа (double является лучшим выбором):

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

Я не получаю правильные результаты, используя это. Вероятно, точность ошибок. Не знаете, как это исправить. – maximusdooku

+0

Первый ответ дает мне правильный результат. Но, как вы сказали, скорость ограничена. – maximusdooku

+0

@maximusdooku неверные результаты могут быть вызваны переполнениями из-за целочисленного типа (i bet 'imread' возвращает некоторые типы' int 'или' uint '. Одной из идей было бы преобразование матриц в более широкий тип. Я отредактирую свой ответ на эту возможность; пожалуйста, дайте мне знать, если это трюк для вас. –

Смежные вопросы