2016-05-16 45 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,SdySdt)。 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     

更糟糕,當我添加更多的字段,它消耗的所有內存並顯示一條錯誤消息。

我錯過了什麼嗎?我怎樣才能防止這一點?

順便說一句,我正在使用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); 

至於減少你的內存佔用,它真的取決於你想要做什麼。這可能只是因爲您的視頻太大而無法可靠地存儲在內存中,並且您可能需要明智地存儲和處理它以節省內存。