2016-05-16 4 views
1

Я читаю кадры фильма AVI и делаю некоторые вычисления на его кадрах. Это часть моего кода:Почему MATLAB сохраняет память при настройке полей предварительно распределенной структуры?

clear; clc; 
mov = mmreader('traffic.avi'); 

vidHeight = mov.Height; 
vidWidth = mov.Width; 
nFrames = mov.NumberOfFrames; 
patchsize = 5; 

frames(1:nFrames) = ... 
    struct(... 
    'gray', zeros(vidHeight, vidWidth, 'double') ,... 
    'dx', zeros(vidHeight, vidWidth, 'double') ,... 
    'dy', zeros(vidHeight, vidWidth, 'double') ,... 
    'dt', zeros(vidHeight, vidWidth, 'double') , ... 
    'Sdx', zeros(vidHeight, vidWidth, 'double') , ... 
    'Sdy', zeros(vidHeight, vidWidth, 'double') , ... 
    'Sdt', zeros(vidHeight, vidWidth, 'double')); 


h_sob_y = fspecial('sobel'); 
h_sob_x = h_sob_y'; 
h_sum = ones(patchsize); 

for k = 1 : nFrames 
    frames(k).gray = double(histeq(rgb2gray(read(mov, k))))/255; 
    frames(k).dx = imfilter(frames(k).gray, h_sob_x); 
    frames(k).dy = imfilter(frames(k).gray, h_sob_y); 
    if k > 1 
     frames(k).dt = frames(k).gray - frames(k-1).gray; 
    end 
    frames(k).Sdx = imfilter(frames(k).dx, h_sum); 
    frames(k).Sdy = imfilter(frames(k).dy, h_sum); 
    frames(k).Sdt = imfilter(frames(k).dt, h_sum); 
end 

Проблема в том, что он продолжает потреблять память внутри цикла. Я сначала подозревал read(mov, k), но это не проблема. Чем больше вычислений я делаю (чем больше полей я устанавливаю), тем больше выделяется память. На рисунке показано, что выделение красного прямоугольника выделено при запуске кода выше, оранжевый - для того же кода с последними 3 строками, прокомментированными (Sdx, Sdy и Sdt). whos метод не показывает изменений числа или размера переменных до и после запуска для цикла (за k исключением):

enter image description here

Name   Size     Bytes Class  Attributes 

    frames   1x120   129074848 struct     
    h_sob_x  3x3      72 double     
    h_sob_y  3x3      72 double     
    h_sum   5x5     200 double     
    k    1x1      8 double     
    mov   1x1      60 mmreader    
    nFrames  1x1      8 double     
    patchsize  1x1      8 double     
    vidHeight  1x1      8 double     
    vidWidth  1x1      8 double     

Это еще хуже, когда я добавить больше полей, оно потребляет всю память и отображает сообщение об ошибке.

Я что-то упустил? Как я могу это предотвратить?

BTW, я использую R2011a.

ответ

2

Вы не Фактически предопределяет структуру так, как вы ее написали. Вы назначаете такую ​​же структуру ко всем записям frames. Поскольку MATLAB фактически не делает копию до тех пор, пока данные не будут изменены, все элементы frames указывают на одинstruct в памяти.

В качестве примера

a = [1,2,3]; 

%// No copy is made yet (memory usage remains the same) 
b = a; 

%// Copy is made and then modified (memory usage doubles) 
b(1) = 2; 

Как вы идете через петлю и изменить каждый frame запись, то копия сделана и обновляется вызывая изменения в использовании памяти, что вы описываете.

Если вы действительно хотите предварительно выделить данные, вы хотите вместо этого использовать что-то вроде repmat, которое заставит сделать копию вашей инициализации struct.

frames = repmat(struct(... 
    'gray', zeros(vidHeight, vidWidth, 'double') ,... 
    'dx', zeros(vidHeight, vidWidth, 'double') ,... 
    'dy', zeros(vidHeight, vidWidth, 'double') ,... 
    'dt', zeros(vidHeight, vidWidth, 'double') , ... 
    'Sdx', zeros(vidHeight, vidWidth, 'double') , ... 
    'Sdy', zeros(vidHeight, vidWidth, 'double') , ... 
    'Sdt', zeros(vidHeight, vidWidth, 'double')), nFrames, 1); 

Что касается уменьшения объема памяти, это действительно зависит от того, что вы пытаетесь сделать. Возможно, ваше видео слишком велико, чтобы надежно вписаться в память, и вам может понадобиться умение в том, как вы храните и обрабатываете его для сохранения памяти.