In my code, arrayfun slower than for loop

2 ビュー (過去 30 日間)
osman
osman 2014 年 8 月 1 日
回答済み: osman 2014 年 8 月 8 日
function Hist = hsv36(I)
[M,N,~] = size(I);
[H,S,V] = rgb2hsv(I);
H = H*360;
Hist = zeros(1,36);
for i = 1:M
for j = 1:N
h = H(i,j);
v = V(i,j);
s = S(i,j);
if(v>=0 && v<0.2)
l = 0+1;
Hist(l) = Hist(l)+1;
continue;
end;
if(s>=0 && s<=0.2)
if (v>=0.2 && v<=0.8)
l = floor((v-0.2)*10)+1+1;
Hist(l) = Hist(l)+1;
elseif (v>0.8 && v<=1)
l = 7+1;
Hist(l) = Hist(l)+1;
end
continue;
end
if((s>0.2 && s<=1)&&(v>=0.2 && v<=1))
if h<=22 || h>330
HF = 0;
elseif h>22 && h<=45
HF = 1;
elseif h>45 && h<=70
HF = 2;
elseif h>70 && h<=155
HF = 3;
elseif h>155 && h<=186
HF = 4;
elseif h>186 && h<=278
HF = 5;
elseif h>278 && h<=330
HF = 6;
end
if(s>0.2 && s<=0.65)
SF = 0;
elseif(s>0.65 && s<=1)
SF = 1;
end;
if(v>=0.2 && v<=0.7)
VF = 0;
elseif(v>0.7 && v<=1)
VF = 1;
end;
l = 4*HF + 2*SF + VF + 8 + 1;
Hist(l) = Hist(l) + 1;
end
end
end
%Hist = Hist/(M*N);
Hist = normr(Hist);
this is my fuction to get hsv color histogram, as you see in which have two for loops, which make code looks ugly, and matlab also doesn't recommend for loop. To make it better, i use arrafun instead of for loop, like that:
function Hist = hsv36_new(I)
[M,N,~] = size(I);
[H,S,V] = rgb2hsv(I);
H = H*360;
Hist = zeros(1,36);
function calHsvHist(i, j)
h = H(i,j);
v = V(i,j);
s = S(i,j);
if(v>=0 && v<0.2)
l = 0+1;
Hist(l) = Hist(l)+1;
return;
end;
if(s>=0 && s<=0.2)
if (v>=0.2 && v<=0.8)
l = floor((v-0.2)*10)+1+1;
Hist(l) = Hist(l)+1;
elseif (v>0.8 && v<=1)
l = 7+1;
Hist(l) = Hist(l)+1;
end
return;
end
if((s>0.2 && s<=1)&&(v>=0.2 && v<=1))
if h<=22 || h>330
HF = 0;
elseif h>22 && h<=45
HF = 1;
elseif h>45 && h<=70
HF = 2;
elseif h>70 && h<=155
HF = 3;
elseif h>155 && h<=186
HF = 4;
elseif h>186 && h<=278
HF = 5;
elseif h>278 && h<=330
HF = 6;
end
if(s>0.2 && s<=0.65)
SF = 0;
elseif(s>0.65 && s<=1)
SF = 1;
end;
if(v>=0.2 && v<=0.7)
VF = 0;
elseif(v>0.7 && v<=1)
VF = 1;
end;
l = 4*HF + 2*SF + VF + 8 + 1;
Hist(l) = Hist(l) + 1;
end
end
arrayfun(@(id1) arrayfun(@(id2) calHsvHist(id1, id2), 1:N), 1:M);
%Hist = Hist/(M*N);
Hist = normr(Hist);
end
In for loop case it juse take 0.06 second, but arrayfun case almost 2 second.. why this happen, could someone explain that to me? thank you.
  1 件のコメント
Sean de Wolski
Sean de Wolski 2014 年 8 月 5 日
With the exception of being on a GPU, arrayfun will most likely often be slower than a for-loop and harder to read. It's just a less flexible more complex for-loop.
Personally, I'd recommend against it at all cost unless you're targeting a GPU.

サインインしてコメントする。

採用された回答

Chris Turnes
Chris Turnes 2014 年 8 月 5 日
The arrayfun function simply applies a given function to each element of the array that you supply. In this sense, arrayfun is effectively looping through the input arrays and calling the supplied function on each input. Since there is some overhead involved with calling a function, this will not be faster than simply placing the loop inside of the function itself.
More specifically, the hsv36_new function given in the question uses arrayfun to call calHsvHist on each grid element. This results in a total of M*N separate calls to calHsvHist, and each of those calls introduces some overhead cost. In the end, both functions are essentially using the same looping, but the hsv36_new function is using a more expensive version since it involves the overhead of calling another function, as well.
If you do want to speed up your code, you should consider vectorizing it by replacing the for loops with matrix operations. You should be able to remove both for loops by making use of logical indexing. For example, you would be able to replace the lines
if(v>=0 && v<0.2)
l = 0+1;
Hist(l) = Hist(l)+1;
continue;
end;
with the single line
Hist(1) = nnz((v >= 0) && (v < 0.2));
The quantity (v >= 0) && (v < 0.2) is a logical matrix of the same size as v whose elements v(i,j) are true if the conditions v(i,j) >= 0 and v(i,j) < 0.2 are both satisfied and false otherwise. The function nnz is then used to count the number of non-zero elements ( i.e., the number of elements that are true).
You could apply similar logic to account for the other if conditions as well, and would then not need the nested for loops.

その他の回答 (1 件)

osman
osman 2014 年 8 月 8 日
Thank your sir for your detailed answer, and I learn a new technique from you.

カテゴリ

Help Center および File ExchangeLoops and Conditional Statements についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by