我目前正致力于2D Hartley变换。代码如下所示:
for u=1:size(img,1)
for v=1:size(img,2)
for x=1:size(img,1)
for y=1:size(img,2)
a = 2*pi*u*x/size(img,1);
b = 2*pi*v*y/size(img,2);
temp= img(x,y)*(cos(a+b) + sin(a+b));
X(u,v)= X(u,v)+temp;
end
end
end
end
它有4个for
循环,执行它需要很长时间。有没有什么方法可以通过减少for
循环的数量来提高效率?任何与此相关的内容都会非常有用。
参考:Andrew B. Watson和Allen Poirson的可分离的二维离散Hartley变换。
答案 0 :(得分:3)
如果你可以适应内存,你可以使用bsxfun
一些额外的单身尺寸:
N = size(img,1);
M = size(img,2);
x = [1:N].'; %' vector of size N x 1 ( x 1 x 1)
y = 1:M; % vector of size 1 x M ( x 1 x 1)
u = permute(1:N,[1 3 2]); %vector of size 1 x 1 x N ( x 1)
v = permute(1:M,[1 3 4 2]); %vector of size 1 x 1 x 1 x M
a = 2*pi/N*bsxfun(@times,u,x); % N x 1 x N x 1
b = 2*pi/M*bsxfun(@times,v,y); % 1 x M x 1 x M
apb = bsxfun(@plus,a,b); % N x M x N x M
%img is N x M (x 1 x 1)
X2 = squeeze(sum(sum(bsxfun(@times,img,cos(apb)+sin(apb)),1),2));
不可否认,这是一种非常强大的力量,人们可能会提出一种更节省内存的解决方案。该解决方案大量使用每个数组隐含拥有无限数量的尾随单例维度,我在评论中试着注意到这一点。
使用N=20; M=30; img=rand(N,M);
与原始循环版本进行比较:
>> max(max(abs(X-X2)))
ans =
1.023181539494544e-12
>> max(max(abs(X)))
ans =
3.091143465722029e+02
这意味着他们在机器精度范围内提供相同的解决方案。
答案 1 :(得分:3)
Andras和Divakar几乎提出了我在写作过程中采用的相同方法。因此,这个答案将简单地为您提供一种加速使用规范实现的方法。
您可以通过手动指定跨越图像范围的ndgrid
空间坐标来消除使用for
和x
作为变量的嵌套y
循环对。此外,等式中的变换从 0 开始索引,但您的代码从1开始。您需要使用MATLAB开始索引为1,但计算等式中的项,您需要从0开始。因此,当您计算a
和b
时,您必须从x
,y
,u
和{中减去1 {1}}。
在任何情况下,您都可以计算元素方面的产品并将所有值相加。 预先分配输出效率也是一个好主意:
v
您希望能够获得更好的性能提升。将此与安德拉斯或迪瓦卡的解决方案进行比较,看看您对使用哪种解决方案感到满意。
答案 2 :(得分:3)
此处使用bsxfun
和fast matrix-multiplication
进行矢量化解决方案 -
%// Store size parameters
[m,n] = size(img);
%// Get vectorized versions of a and b
A = 2*pi*(1:m).'*(1:m)/m;
B = 2*pi*(1:n).'*(1:n)/n;
%// Add vectorized a and b's to form a 4D array. Get cos + sin version.
AB = bsxfun(@plus,permute(A,[1 3 2 4]),permute(B,[3 1 4 2]));
cosAB = cos(AB) + sin(AB);
%// Finally bring in magic of matrix-multiplication for final output
Xout = reshape(img(:).'*reshape(cosAB,m*n,[]),m,n);