Simply image rotation - Why does function calls take so long?

1 visualización (últimos 30 días)
Novice DTU Engineer
Novice DTU Engineer el 14 de Dic. de 2019
Comentada: Image Analyst el 15 de Dic. de 2019
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?

Respuestas (1)

Image Analyst
Image Analyst el 14 de Dic. de 2019
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 comentarios
Novice DTU Engineer
Novice DTU Engineer el 15 de Dic. de 2019
Why would that make it faster? When it comes to coding, most of my education so far, has been on methods and algorithms, and not so much about efficient code, with the exception being C coding. From that all I see is a large additional usage of memory. Please forgive me ignorance
Image Analyst
Image Analyst el 15 de Dic. de 2019
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.

Iniciar sesión para comentar.

Community Treasure Hunt

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

Start Hunting!

Translated by