我正在尝试为作业编写非局部均值过滤器。我用两种方式编写代码,但是我希望更快的方法比其他方法慢得多。
方法1 :(此方法较慢)
for i = 1:size(I,1)
tic
sprintf('%d/%d',i,size(I,1))
for j = 1:size(I,2)
w = exp((-abs(I-I(i,j))^2)/(h^2));
Z = sum(sum(w));
w = w/Z;
sumV = w .* I;
NL(i,j) = sum(sum(sumV));
end
toc
end
方法2 :(此方法更快)
for i = 1:size(I,1)
tic
sprintf('%d/%d',i,size(I,1))
for j = 1:size(I,2)
Z = 0;
for k = 1:size(I,1)
for l = 1:size(I,2)
w = exp((-abs(I(i,j)-I(k,l))^2)/(h^2));
Z = Z + w;
end
end
sumV = 0;
for k = 1:size(I,1)
for l = 1:size(I,2)
w = exp((-abs(I(i,j)-I(k,l))^2)/(h^2));
w = w/Z;
sumV = sumV + w * I(k,l);
end
end
NL(i,j) = sumV;
end
toc
end
我真的认为MATLAB会针对Matrix操作进行优化。是否有理由不在此代码中?差异非常大。对于带有512x512
的{{1}}图像,外部循环的一次迭代对于方法1需要h = 0.05
秒,对于方法2则需要24-28
秒。
答案 0 :(得分:3)
这两种方法并没有做同样的事情。在方法2中,abs(I(i,j)-I(k,l))
表达式中的w=
项是平方的,这很好,因为该项只是一个数值。
但是,在方法1中,术语abs(I-I(i,j))
实际上是一个矩阵(从矩阵I(i,j)
中的每个元素中减去数值I
,再次返回一个矩阵)。因此,当该术语与^
运算符平方时,矩阵乘法正在发生。我的猜测,基于方法2,这不是你想要的。相反,如果要平方该矩阵中的每个元素,请使用.^
运算符,如abs(I-I(i,j)).^2
矩阵乘法是一种计算量更大的操作,这可能是方法1需要更长时间的原因。
答案 1 :(得分:0)
我的猜测是你没有预先分配NL
,两个方法都在同一个函数中(或者是脚本,你在函数运行之间没有清除NL
)。这会使第一种方法减慢很多。
尝试以下操作:为两种方法创建一个函数。运行每个方法一次。然后使用profiler
查看每个函数花费大部分时间的位置。
答案 2 :(得分:0)
使用im2col
:
sum
函数对值和权重求和。此方法完全没有循环。