Simply image rotation - Why does function calls take so long?
1 次查看(过去 30 天)
显示 更早的评论
I recently took a class on entry level image analysis, and have attempted to implement some simple backwards mapping functions for image transformations. In particular I made a rotation function. I noticed that it takes a while, though i suspect that it is because of matlabs abysmal loop speeds. However I also noticed that if I input the code for bilinear interpolation straight into the rotation function, it becomes 3 times faster, then if I leave the bilinear interpolation in another function and call it. This seems very weird to me, can anyone explain to me what is going on? Heres the code:
function I0 = im_rotate(I,degree)
R_inv = [cosd(degree) sind(degree); -sind(degree) cosd(degree)];
H = size(I,1); Hh = (H-1)/2;
L = size(I,2); Ll = (L-1)/2;
I0 = zeros(H,L);
for i = 1:H
for j = 1:L
% Using Backwards mapping to find the original point
p = R_inv*[i-Hh;j-Ll]+[Hh;Ll];
% If the original point found, is outside the original
% image; skip
if (p(1) < H && p(1) > 1) && (p(2) < L && p(2) > 1)
% Bilinear Interpolation of point "p"
% Finding delta distance
dv = [p(1) - floor(p(1)); p(2) - floor(p(2))];
% finding the nearest points
P(:,1) = floor(p);
P(:,2) = [ceil(p(1)); floor(p(2))];
P(:,3) = [floor(p(1)); ceil(p(2))];
P(:,4) = ceil(p);
% Interpolating
gXY = I(P(1,1),P(2,1))*(1-dv(1))*(1-dv(2))+ ...
I(P(1,2),P(2,2))*(dv(1))*(1-dv(2))+ ...
I(P(1,3),P(2,3))*(1-dv(1))*(dv(2))+ ...
I(P(1,4),P(2,4))*(dv(1)*dv(2));
I0(i,j) = round(gXY);
%I0(i,j) = bilinear_interpolation(p,I);
else
end
end
end
end
function gXY = bilinear_interpolation(p,I)
% INPUT
% p1 : Vector of coordinates [x;y] to interpolate
% A : The matrix of coordinates and values [x;y;v]
dv = [p(1) - floor(p(1)); p(2) - floor(p(2))];
% finding the nearest points
P(:,1) = floor(p);
P(:,2) = [ceil(p(1)); floor(p(2))];
P(:,3) = [floor(p(1)); ceil(p(2))];
P(:,4) = ceil(p);
% Using bilinear interpolation
gXY = I(P(1,1),P(2,1))*(1-dv(1))*(1-dv(2))+ ...
I(P(1,2),P(2,2))*(dv(1))*(1-dv(2))+ ...
I(P(1,3),P(2,3))*(1-dv(1))*(dv(2))+ ...
I(P(1,4),P(2,4))*(dv(1)*dv(2));
gXY = round(gXY);
end
If I remove the bilinear interpolation from "im_rotate", and instead call "bilinear_interpolation(p,I)", then on my current test image, it takes at least 3 times as long. Besides using loops, and that its a very straight forward implementation, why is this the case, and can I improve it?
0 个评论
回答(1 个)
Image Analyst
2019-12-14
Try having the inner loop being over rows not columns, and the outer loop be over columns, not rows. MATLAB is column-major so it goes down rows first in memory before jumping to the next column.
4 个评论
Image Analyst
2019-12-15
You'd have to check but I think doing one large matrix multiplication in advance of the loop may be faster than doing a bunch of small matrix multiplications in the loop. Have you edited imrotate.m to see how they do it? Sometimes the algorithm is in there but sometimes it just calls a DLL to do the heavy lifting.
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!