MATLAB循環嵌套的優化,可否改成矩陣運算?

當數據量很龐大時,用matlab計算循環耗時很久,不知道能否進行優化,讓循環成其他運算方法,比如矩陣運算?
下面是題主遇到的實際問題,最後要生成兩個矩陣(均值和方差):
[m n]=size(im); %%im是個1024*2048的double型矩陣
p=(row-1)/2; %% row=col=5
q=(col-1)/2;
temp=padarray(im,[p q],『symmetric』); %%拓展矩陣,維數是(m+2p,n+2q)
temp2=zeros(row,col); %%滑動窗口,一個小的方陣,維數是(row,col)
temp_mean=zeros(m,n); %%均值矩陣
temp_var=zeros(m,n); %%方差矩陣
for ii=p+1:p+m
for jj=q+1:1:q+n
temp2=temp(ii-p:1:ii+p,jj-q:1:jj+q);
temp3=temp2(:); %%矩陣變向量
temp_mean(ii-p,jj-q)=mean(temp3); %%取平均數
temp_var(ii-p,jj-q)=var(temp3); %%取方差
end
end


im = rand(1024,2048);
row = 5; col = 5;

% 原始程序
tic
[m,n]=size(im); %%im是個1024*2048的double型矩陣
p=(row-1)/2; %% row=col=5
q=(col-1)/2;
temp=padarray(im,[p q],"symmetric"); %%拓展矩陣,維數是(m+2p,n+2q)
temp2=zeros(row,col); %%滑動窗口,一個小的方陣,維數是(row,col)
temp_mean=zeros(m,n); %%均值矩陣
temp_var=zeros(m,n); %%方差矩陣
for ii=p+1:p+m
for jj=q+1:1:q+n
temp2=temp(ii-p:1:ii+p,jj-q:1:jj+q);
temp3=temp2(:); %%矩陣變向量
temp_mean(ii-p,jj-q)=mean(temp3); %%取平均數
temp_var(ii-p,jj-q)=var(temp3); %%取方差
end
end
toc

% 修改
tic
n = row*col;
tm = imfilter(im,ones(row,col)/n,"symmetric");
tv = imfilter(im.^2,ones(row,col)/(n-1),"symmetric")-n/(n-1)*tm.^2;
toc

% 驗證
norm(temp_mean(:)-tm(:))
norm(temp_var(:)-tv(:))

結果:

時間已過 27.949467 秒。
時間已過 0.037127 秒。
ans =
1.28280355334838e-13
ans =
1.20941060414099e-13

如果你的 GPU 支持 CUDA,可以用 gpuArray, 應該會更快些


找到了一個matlab內建的函數用於求均值矩陣,然而方差矩陣還是沒有辦法。
改進之後的代碼如下:
[m n]=size(im); %%im是個1024*2048的double型矩陣
p=(row-1)/2; %% row=col=5
q=(col-1)/2;
temp=padarray(im,[p q],『symmetric』); %%拓展矩陣,維數是(m+2p,n+2q)
temp_var=zeros(m,n); %%方差矩陣
for ii=p+1:p+m
for jj=q+1:1:q+n
temp2=temp(ii-p:1:ii+p,jj-q:1:jj+q);
temp3=temp2(:); %%矩陣變向量
temp_var(ii-p,jj-q)=var(temp3); %%取方差
end
end
temp_mean=filter2(fspecial("average",5),temp);%%均值濾波,模板是5*5
temp_mean=(temp_mean(2:(m+1),2:(n+1)));%%截取中間m*n的矩陣塊,得到所需均值矩陣

大概程序的整體運行速度比之前快了三分之一吧。


推薦閱讀:

一個N*N的矩陣,取值為0或1,有什麼好的演算法判斷一行或一列全為1啊?
卡爾曼濾波器是如何運用於多感測器融合的?
MD5加密相比於其他加密有什麼好處?
怎麼看演算法書?
演算法競賽和數學競賽對選手的考察點有什麼不同?

TAG:演算法 | MATLAB | 矩陣運算 |